def test_valid(self, fetch_allthethings_data): """Test if the function finds the right builder.""" fetch_allthethings_data.return_value = ALLTHETHINGS assert determine_upstream_builder( 'Windows 7 VM 32-bit try opt test mochitest-1') == 'WINNT 5.2 try build' assert determine_upstream_builder( 'Windows 7 VM 32-bit try debug test mochitest-1') == 'WINNT 5.2 try leak test build' assert determine_upstream_builder( 'Windows 7 32-bit mozilla-beta pgo talos tp5o') == 'WINNT 5.2 mozilla-beta build'
def test_invalid(self, fetch_allthethings_data): """Raises Exception for buildernames not in allthethings.json.""" fetch_allthethings_data.return_value = MOCK_ALLTHETHINGS with pytest.raises(Exception): determine_upstream_builder("Not a valid buildername") # Since "Platform1 mozilla-beta pgo talos tp5o" exists, # "Platform1 mozilla-beta talos tp5o" is an invalid buildername # and should return None self.assertEquals( determine_upstream_builder("Platform1 mozilla-beta talos tp5o"), None)
def test_valid(self, fetch_allthethings_data): """Test if the function finds the right builder.""" fetch_allthethings_data.return_value = ALLTHETHINGS assert determine_upstream_builder( 'Windows 7 VM 32-bit try opt test mochitest-1' ) == 'WINNT 5.2 try build' assert determine_upstream_builder( 'Windows 7 VM 32-bit try debug test mochitest-1' ) == 'WINNT 5.2 try leak test build' assert determine_upstream_builder( 'Windows 7 32-bit mozilla-beta pgo talos tp5o-e10s' ) == 'WINNT 5.2 mozilla-beta build'
def generate_builders_relations_dictionary(): """Create a dictionary that maps every upstream job to its downstream jobs.""" builders = list_builders() relations = collections.defaultdict(list) for buildername in builders: if is_downstream(buildername): relations[determine_upstream_builder(buildername)].append(buildername) return relations
def test_valid(self, fetch_allthethings_data): """Test if the function finds the right builder.""" fetch_allthethings_data.return_value = MOCK_ALLTHETHINGS self.assertEquals( determine_upstream_builder('Platform1 repo opt test mochitest-1'), 'Platform1 repo build') self.assertEquals( determine_upstream_builder('Platform1 repo debug test mochitest-1'), 'Platform1 repo leak test build') self.assertEquals( determine_upstream_builder('Platform1 mozilla-beta pgo talos tp5o'), 'Platform1 mozilla-beta build') # Since "Platform2 mozilla-beta pgo talos tp5o" does not exist, # "Platform2 mozilla-beta talos tp5o" is a valid buildername self.assertEquals( determine_upstream_builder('Platform2 mozilla-beta talos tp5o'), 'Platform2 mozilla-beta build')
def test_valid(self, fetch_allthethings_data): """Test if the function finds the right builder.""" fetch_allthethings_data.return_value = MOCK_ALLTHETHINGS self.assertEquals( determine_upstream_builder('Platform1 repo opt test mochitest-1'), 'Platform1 repo build') self.assertEquals( determine_upstream_builder( 'Platform1 repo debug test mochitest-1'), 'Platform1 repo leak test build') self.assertEquals( determine_upstream_builder( 'Platform1 mozilla-beta pgo talos tp5o'), 'Platform1 mozilla-beta build') # Since "Platform2 mozilla-beta pgo talos tp5o" does not exist, # "Platform2 mozilla-beta talos tp5o" is a valid buildername self.assertEquals( determine_upstream_builder('Platform2 mozilla-beta talos tp5o'), 'Platform2 mozilla-beta build')
def main(): orphan_builders = [] for builder in sorted(query_builders()): # To be fixed in issue 124 if "l10n" in builder or "nightly" in builder: continue try: if determine_upstream_builder(builder) is None: orphan_builders.append(builder) except: orphan_builders.append(builder) for x in sorted(orphan_builders): print x
def test_no_testers_without_builders(): # We need to assert that allthethings.json has been generated # before running this test rather than fetching the one from the server # This is important as we want to test against the latest list of builders assert os.path.exists("allthethings.json") orphan_builders = [] j = fetch_allthethings_data(verify=False) builders = j["builders"].keys() assert builders is not None, "The list of builders cannot be empty." for builder in sorted(builders): if determine_upstream_builder(builder) is None: orphan_builders.append(builder) assert len(orphan_builders) == 0, \ "There are downstream builders without upstream builders to trigger them."
def jobs_per_revision(revision): """Generate a json graph of existing and possible jobs.""" load_relations() all_jobs = get_jobs(revision) if all_jobs is None: return upstream_jobs, downtream_jobs = separate_downstream(all_jobs) processed_jobs = {} processed_jobs["new_builds"] = {"existing": [], "possible": []} for build_job in upstream_jobs: buildername, status = build_job if status == 0: processed_jobs[buildername] = {"existing": [], "possible": []} else: processed_jobs["new_builds"]["existing"].append(buildername) for test_job in downtream_jobs: buildername = test_job[0] upstream = determine_upstream_builder(buildername) if upstream in processed_jobs: if buildername not in processed_jobs[upstream]["existing"]: processed_jobs[upstream]["existing"].append(buildername) for build_job in processed_jobs.keys(): if build_job == "new_builds": continue existing_downstream = set(processed_jobs[build_job]["existing"]) possible_downstream = sorted(list(set(UPSTREAM_TO_DOWNSTREAM[build_job]) - existing_downstream)) processed_jobs[build_job]["possible"] = possible_downstream processed_jobs[build_job]["existing"].sort() all_build_jobs = get_upstream_buildernames(" try ") + get_upstream_buildernames("_try_") for build_job in all_build_jobs: if build_job not in processed_jobs.keys() + processed_jobs["new_builds"]["existing"]: processed_jobs["new_builds"]["possible"].append(build_job) processed_jobs["new_builds"]["possible"].sort() return processed_jobs
def test_no_testers_without_builders(): # We need to assert that allthethings.json has been generated # before running this test rather than fetching the one from the server # This is important as we want to test against the latest list of builders assert os.path.exists("allthethings.json") orphan_builders = [] j = fetch_allthethings_data(verify=False) builders = j["builders"].keys() assert builders is not None, "The list of builders cannot be empty." for builder in sorted(builders): # Bug 1330680 - patches to disable bb nightlies on linux32/linux64/android # there are talos jobs that don't have associated build jobs as part # of tc migration if 'talos' in builder and 'Ubuntu HW' in builder: return if determine_upstream_builder(builder) is None: orphan_builders.append(builder) assert len(orphan_builders) == 0, \ "There are downstream builders without upstream builders to trigger them."
def determine_trigger_objective(revision, buildername, trigger_build_if_missing=True): """ Determine if we need to trigger any jobs and which job. Returns: * The name of the builder we need to trigger * Files, if needed, to trigger such builder """ builder_to_trigger = None files = None repo_name = query_repo_name_from_buildername(buildername) build_buildername = determine_upstream_builder(buildername) if VALIDATE and not valid_builder(build_buildername): raise MozciError("Our platforms mapping system has failed.") if build_buildername == buildername: # For a build job we know that we don't need files to # trigger it and it's the build job we want to trigger return build_buildername, None # Let's figure out which jobs are associated to such revision query_api = BuildApi() # Let's only look at jobs that match such build_buildername build_jobs = query_api.get_matching_jobs(repo_name, revision, build_buildername) # We need to determine if we need to trigger a build job # or the test job working_job = None running_job = None failed_job = None LOG.debug("List of matching jobs:") for job in build_jobs: try: status = query_api.get_job_status(job) except buildjson.BuildjsonException: LOG.debug( "We have hit bug 1159279 and have to work around it. We will " "pretend that we could not reach the files for it.") continue # Sometimes running jobs have status unknown in buildapi if status in (RUNNING, PENDING, UNKNOWN): LOG.debug( "We found a running/pending build job. We don't search anymore." ) running_job = job # We cannot call _find_files for a running job continue # Having a coalesced build is the same as not having a build available if status == COALESCED: LOG.debug( "The build we found was a coalesced one; this is the same as " "non-existant.") continue # Successful or failed jobs may have the files we need files = _find_files(job) if files != [] and _all_urls_reachable(files.values()): working_job = job break else: LOG.debug("We can't determine the files for this build or " "can't reach them.") files = None LOG.info("We found a job that finished but it did not " "produced files. status: %d" % status) failed_job = job # End of for loop if working_job: # We found a build job with the necessary files. It could be a # successful job, a running job that already emitted files or a # testfailed job LOG.debug(str(working_job)) LOG.info("We have the necessary files to trigger the downstream job.") # We have the files needed to trigger the test job builder_to_trigger = buildername elif running_job: LOG.info( "We found a running/pending build job. We will not trigger another one." ) LOG.info( "You have to run the script again after the build job is finished to " "trigger %s." % buildername) builder_to_trigger = None elif failed_job: LOG.info( "The build job %s failed on revision %s without generating the " "necessary files. We will not trigger anything." % (build_buildername, revision)) builder_to_trigger = None else: # We were trying to build a test job, however, we determined # that we need an upstream builder instead if not trigger_build_if_missing or not _unique_build_request( build_buildername, revision): # This is a safeguard to prevent triggering a build # job multiple times if it is not intentional builder_to_trigger = None if not trigger_build_if_missing: LOG.info( "We would have to triggered build '%s' in order to trigger " "job '%s'. On this mode we will not trigger either." % (build_buildername, buildername)) else: LOG.info("We will trigger 1) " "'%s' instead of 2) '%s'" % (build_buildername, buildername)) LOG.info("We need to trigger the build job once (1) " "in order to be able to run the test job (2).") if repo_name == 'try': LOG.info( "You'll need to run the script again after (1) is done to " "trigger (2).") else: LOG.info( "After (1) is done and if no coalesccing happens the test " "jobs associated with it will be triggered.") builder_to_trigger = build_buildername if files: return builder_to_trigger, files['packageUrl'], files[ 'testPackagesUrl'] else: return builder_to_trigger, None, None
def determine_trigger_objective(revision, buildername, trigger_build_if_missing=True, will_use_buildapi=False): """ Determine if we need to trigger any jobs and which job. Returns: * The name of the builder we need to trigger * Files, if needed, to trigger such builder """ builder_to_trigger = None files = None repo_name = query_repo_name_from_buildername(buildername) build_buildername = determine_upstream_builder(buildername) if VALIDATE and not valid_builder(build_buildername): raise MozciError("Our platforms mapping system has failed.") if build_buildername == buildername: # For a build job we know that we don't need files to # trigger it and it's the build job we want to trigger return build_buildername, None, None # Let's figure out which jobs are associated to such revision query_api = BuildApi() # Let's only look at jobs that match such build_buildername build_jobs = query_api.get_matching_jobs(repo_name, revision, build_buildername) # We need to determine if we need to trigger a build job # or the test job working_job = None running_job = None failed_job = None LOG.debug("List of matching jobs:") for job in build_jobs: try: status = query_api.get_job_status(job) except buildjson.BuildjsonException: LOG.debug("We have hit bug 1159279 and have to work around it. We will " "pretend that we could not reach the files for it.") continue # Sometimes running jobs have status unknown in buildapi if status in (RUNNING, PENDING, UNKNOWN): LOG.debug("We found a running/pending build job. We don't search anymore.") running_job = job # We cannot call _find_files for a running job continue # Having a coalesced build is the same as not having a build available if status == COALESCED: LOG.debug("The build we found was a coalesced one; this is the same as " "non-existant.") continue # Successful or failed jobs may have the files we need files = _find_files(job) if files != [] and _all_urls_reachable(files.values()): working_job = job break else: LOG.debug("We can't determine the files for this build or " "can't reach them.") files = None LOG.info("We found a job that finished but it did not " "produced files. status: %d" % status) failed_job = job # End of for loop if working_job: # We found a build job with the necessary files. It could be a # successful job, a running job that already emitted files or a # testfailed job LOG.debug(str(working_job)) LOG.info("We have the necessary files to trigger the downstream job.") # We have the files needed to trigger the test job builder_to_trigger = buildername elif running_job: LOG.info("We found a running/pending build job. We will not trigger another one.") LOG.info("You have to run the script again after the build job is finished to " "trigger %s." % buildername) builder_to_trigger = None elif failed_job: LOG.info("The build job %s failed on revision %s without generating the " "necessary files. We will not trigger anything." % (build_buildername, revision)) builder_to_trigger = None else: # We were trying to build a test job, however, we determined # that we need an upstream builder instead if not trigger_build_if_missing or not _unique_build_request(build_buildername, revision): # This is a safeguard to prevent triggering a build # job multiple times if it is not intentional builder_to_trigger = None if not trigger_build_if_missing: LOG.info("We would have to triggered build '%s' in order to trigger " "job '%s'. On this mode we will not trigger either." % (build_buildername, buildername)) else: if will_use_buildapi: LOG.info("We will trigger 1) '%s'" % build_buildername) LOG.info("instead of 2) '%s'" % buildername) LOG.info("We need to trigger the build job once (1) " "in order to be able to run the test job (2).") if repo_name == 'try': LOG.info("You'll need to run the script again after (1) is done to " "trigger (2).") else: LOG.info("After (1) is done and if no coalesccing happens the test " "jobs associated with it will be triggered.") builder_to_trigger = build_buildername if files: return builder_to_trigger, files['packageUrl'], files['testsUrl'] else: return builder_to_trigger, None, None
def _determine_trigger_objective(revision, buildername): """ Determine if we need to trigger any jobs and which job. Returns: * The name of the builder we need to trigger * Files, if needed, to trigger such builder """ builder_to_trigger = None files = None repo_name = query_repo_name_from_buildername(buildername) build_buildername = determine_upstream_builder(buildername) assert valid_builder(build_buildername), \ "Our platforms mapping system has failed." if build_buildername == buildername: # For a build job we know that we don't need files to # trigger it and it's the build job we want to trigger return build_buildername, None # Let's figure out which jobs are associated to such revision all_jobs = query_jobs(repo_name, revision) # Let's only look at jobs that match such build_buildername build_jobs = _matching_jobs(build_buildername, all_jobs) # We need to determine if we need to trigger a build job # or the test job successful_job = None running_job = None LOG.debug("List of matching jobs:") for job in build_jobs: try: status = buildapi.query_job_status(job) except buildjson.BuildjsonException: LOG.debug("We have hit bug 1159279 and have to work around it. We will pretend that " "we could not reach the files for it.") continue if status == buildapi.RUNNING: LOG.debug("We found a running build job. We don't search anymore.") running_job = job elif status == buildapi.SUCCESS: LOG.debug("We found a successful job. We don't search anymore.") files = _find_files(job) if files != [] and _all_urls_reachable(files): successful_job = job break else: LOG.debug("We can't determine the files for this build or " "can't reach them.") files = None else: LOG.debug("We found a job that finished but its status " "is not successful. status: %d" % status) if successful_job: # A build job has completed successfully and the files can be reached LOG.info("There is a _build_ job that has completed successfully.") LOG.debug(str(successful_job)) LOG.info("We have the necessary files to trigger the downstream job.") # We have the files needed to trigger the test job builder_to_trigger = buildername elif running_job: # NOTE: Note that a build might have not finished yet # the installer and test.zip might already have been uploaded # For now, we will ignore this situation but need to take note of it LOG.info("We are waiting for the associated build job to finish.") LOG.debug(str(running_job)) builder_to_trigger = None else: # We were trying to build a test job, however, we determined # that we need an upstream builder instead if not _unique_build_request(build_buildername, revision): # This is a safeguard to prevent triggering a build # job multiple times if it is not intentional builder_to_trigger = None else: LOG.info("We need to trigger the build job (1) in order to be able to run the test job (2)" "which we'll be triggered later") LOG.info("We will trigger 1) '%s' instead of 2) '%s'" % (build_buildername, buildername)) builder_to_trigger = build_buildername return builder_to_trigger, files
def test_invalid(self, fetch_allthethings_data): fetch_allthethings_data.return_value = ALLTHETHINGS with pytest.raises(Exception): determine_upstream_builder("Not a valid buildername")
def test_has_buildbot_upstream_builder(fetch_allthethings_data): fetch_allthethings_data.return_value = ALLTHETHINGS assert determine_upstream_builder( "Rev7 MacOSX Yosemite 10.10.5 mozilla-esr52 debug test cppunit") == \ 'OS X 10.7 64-bit mozilla-esr52 leak test build'
def test_no_buildbot_upstream_builder(fetch_allthethings_data): fetch_allthethings_data.return_value = ALLTHETHINGS assert determine_upstream_builder( "Ubuntu HW 12.04 x64 autoland talos g2-e10s") is None
def test_no_associated_build(self, fetch_allthethings_data): # XXX: Should this test instead raise an exception? assert determine_upstream_builder( 'Windows 7 32-bit mozilla-beta talos tp5o-e10s') is None
def test_invalid(self, fetch_allthethings_data): fetch_allthethings_data.return_value = MOCK_ALLTHETHINGS with pytest.raises(Exception): determine_upstream_builder("Not a valid buildername")
def test_no_associated_build(self, fetch_allthethings_data): # XXX: Should this test instead raise an exception? assert determine_upstream_builder('Windows 7 32-bit mozilla-beta talos tp5o') is None
def _determine_trigger_objective(revision, buildername): """ Determine if we need to trigger any jobs and which job. Returns: * The name of the builder we need to trigger * Files, if needed, to trigger such builder """ builder_to_trigger = None files = None repo_name = query_repo_name_from_buildername(buildername) build_buildername = determine_upstream_builder(buildername) assert valid_builder(build_buildername), \ "Our platforms mapping system has failed." if build_buildername == buildername: # For a build job we know that we don't need files to # trigger it and it's the build job we want to trigger return build_buildername, None # Let's figure out which jobs are associated to such revision all_jobs = query_jobs(repo_name, revision) # Let's only look at jobs that match such build_buildername build_jobs = _matching_jobs(build_buildername, all_jobs) # We need to determine if we need to trigger a build job # or the test job working_job = None running_job = None failed_job = None LOG.debug("List of matching jobs:") for job in build_jobs: # Successful, running and failed jobs may have the files we need files = _find_files(job) if files != [] and _all_urls_reachable(files): working_job = job break else: LOG.debug("We can't determine the files for this build or " "can't reach them.") files = None try: status = buildapi.query_job_status(job) except buildjson.BuildjsonException: LOG.debug("We have hit bug 1159279 and have to work around it. We will pretend that " "we could not reach the files for it.") continue if status == buildapi.RUNNING: LOG.debug("We found a running build job. We don't search anymore.") running_job = job else: LOG.info("We found a job that finished but its status " "is not successful. status: %d" % status) failed_job = job if working_job: # We found a build job with the necessary files. It could be a # successful job, a running job that already emitted files or a # testfailed job LOG.debug(str(working_job)) LOG.info("We have the necessary files to trigger the downstream job.") # We have the files needed to trigger the test job builder_to_trigger = buildername elif running_job: LOG.info("We found a running build job without files. We will not trigger another one. " "You have to run the script again after the build job is finished to trigger %s." % buildername) builder_to_trigger = None elif failed_job: LOG.info("The build job %s failed on revision %s without generating the necessary files. " "We will not trigger anything." % (build_buildername, revision)) builder_to_trigger = None else: # We were trying to build a test job, however, we determined # that we need an upstream builder instead if not _unique_build_request(build_buildername, revision): # This is a safeguard to prevent triggering a build # job multiple times if it is not intentional builder_to_trigger = None else: LOG.info("We will trigger 1) '%s' instead of 2) '%s'" % (build_buildername, buildername)) LOG.info("We need to trigger the build job once (1) in order to be able to run the test job (2).") if repo_name == 'try': LOG.info("You'll need to run the script again after (1) is done to trigger (2).") else: LOG.info("After (1) is done every test job associated with it will be triggered.") builder_to_trigger = build_buildername return builder_to_trigger, files
def test_invalid(self, fetch_allthethings_data): """Raises Exception for buildernames not in allthethings.json.""" fetch_allthethings_data.return_value = ALLTHETHINGS with pytest.raises(Exception): determine_upstream_builder("Not a valid buildername")