async def test_start_test_selection(PhabricatorMock, mock_taskcluster): bus = MessageBus() bus.add_queue(QUEUE_MONITORING_COMMUNITY) build = PhabricatorBuild( MockRequest( diff="125397", repo="PHID-REPO-saax4qdxlbbhahhp2kg5", revision="36474", target="PHID-HMBT-icusvlfibcebizyd33op", )) taskcluster_config.secrets["test_selection_enabled"] = True taskcluster_config.secrets["test_selection_share"] = 1.0 with PhabricatorMock as phab: phab.load_patches_stack(build) phab.update_state(build) phab.load_reviewers(build) bugbug_utils = BugbugUtils(phab.api) bugbug_utils.register(bus) with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps: def trigger_hook_callback(request): payload = json.loads(request.body) assert payload == { "DIFF_ID": 125397, "PHABRICATOR_DEPLOYMENT": "prod", "RUNNABLE_JOBS": "http://taskcluster.test/api/index/v1/task/gecko.v2.try.revision.MyRevision.firefox.decision/artifacts/public%2Frunnable-jobs.json", } return ( 200, { "Content-Type": "application/json" }, json.dumps({"status": { "taskId": "xxx" }}), ) rsps.add_callback( responses.POST, "http://community_taskcluster.test/api/hooks/v1/hooks/project-relman/bugbug-test-select/trigger", callback=trigger_hook_callback, ) await bugbug_utils.start_test_selection(build, "MyRevision") group_id, hook_id, task_id = await bus.receive( QUEUE_MONITORING_COMMUNITY) assert group_id == "project-relman" assert hook_id == "bugbug-test-select" assert task_id == "xxx"
async def test_process_push(PhabricatorMock, mock_taskcluster): build = PhabricatorBuild( MockRequest( diff="125397", repo="PHID-REPO-saax4qdxlbbhahhp2kg5", revision="36474", target="PHID-HMBT-icusvlfibcebizyd33op", ) ) with PhabricatorMock as phab: phab.load_patches_stack(build) phab.update_state(build) phab.load_reviewers(build) bugbug_utils = BugbugUtils(phab.api) try: await bugbug_utils.diff_to_push.rem(str(build.diff_id)) except KeyError: pass with pytest.raises(KeyError): await bugbug_utils.diff_to_push.get(str(build.diff_id)) await bugbug_utils.process_push( ( "success", build, { "treeherder_url": "https://treeherder.mozilla.org/#/jobs?repo=try&revision=123", "revision": "123", }, ) ) assert await bugbug_utils.diff_to_push.get(str(build.diff_id)) == { "revision": "123", "treeherder_url": "https://treeherder.mozilla.org/#/jobs?repo=try&revision=123", "build": build, } if "REDIS_URL" in os.environ: # Simulate a restart. bugbug_utils = BugbugUtils(phab.api) stored_push = await bugbug_utils.diff_to_push.get(str(build.diff_id)) assert stored_push["revision"] == "123" assert ( stored_push["treeherder_url"] == "https://treeherder.mozilla.org/#/jobs?repo=try&revision=123" ) assert stored_push["build"].diff_id == build.diff_id assert stored_push["build"].target_phid == build.target_phid
async def test_risk_analysis_should_trigger(PhabricatorMock, mock_taskcluster): bus = MessageBus() build = PhabricatorBuild( MockRequest( diff="125397", repo="PHID-REPO-saax4qdxlbbhahhp2kg5", revision="36474", target="PHID-HMBT-icusvlfibcebizyd33op", )) with PhabricatorMock as phab: phab.load_patches_stack(build) phab.update_state(build) # Reviewer of the patch is in the list of risk analysis users. taskcluster_config.secrets["risk_analysis_users"] = ["ehsan", "heycam"] bugbug_utils = BugbugUtils(phab.api) bugbug_utils.register(bus) assert bugbug_utils.should_run_risk_analysis(build) # Author of the patch is in the list of risk analysis users. taskcluster_config.secrets["risk_analysis_users"] = [ "ehsan", "tnguyen" ] bugbug_utils = BugbugUtils(phab.api) assert bugbug_utils.should_run_risk_analysis(build)
async def test_should_run_test_selection(PhabricatorMock, mock_taskcluster): build = PhabricatorBuild( MockRequest( diff="125397", repo="PHID-REPO-saax4qdxlbbhahhp2kg5", revision="36474", target="PHID-HMBT-icusvlfibcebizyd33op", ) ) def calc_perc(): count = sum( 1 for _ in range(1000) if bugbug_utils.should_run_test_selection(build) ) return count / 1000 with PhabricatorMock as phab: phab.load_patches_stack(build) phab.update_state(build) bugbug_utils = BugbugUtils(phab.api) taskcluster_config.secrets["test_selection_enabled"] = False taskcluster_config.secrets["test_selection_share"] = 0.0 bugbug_utils = BugbugUtils(phab.api) assert calc_perc() == 0.0 taskcluster_config.secrets["test_selection_enabled"] = False taskcluster_config.secrets["test_selection_share"] = 0.1 bugbug_utils = BugbugUtils(phab.api) assert calc_perc() == 0.0 taskcluster_config.secrets["test_selection_enabled"] = True taskcluster_config.secrets["test_selection_share"] = 0.0 bugbug_utils = BugbugUtils(phab.api) assert calc_perc() == 0.0 taskcluster_config.secrets["test_selection_enabled"] = True taskcluster_config.secrets["test_selection_share"] = 0.1 bugbug_utils = BugbugUtils(phab.api) assert 0.03 < calc_perc() < 0.18
async def test_got_try_task_end(PhabricatorMock, mock_taskcluster): bus = MessageBus() build = PhabricatorBuild( MockRequest( diff="125397", repo="PHID-REPO-saax4qdxlbbhahhp2kg5", revision="36474", target="PHID-HMBT-icusvlfibcebizyd33op", )) payload = { "routing": { "exchange": "exchange/taskcluster-queue/v1/task-completed", "key": "primary.fUAKaIdkSF6K1NlOgx7-LA.0.aws.i-0a45c84b1709af6a7.gecko-t.t-win10-64.gecko-level-1.RHY-YSgBQ7KlTAaQ5ZWP5g._", "other_routes": [ b"route.tc-treeherder.v2.try.028980a035fb3e214f7645675a01a52234aad0fe.455891" ], }, "body": { "status": { "taskId": "W2SMZ3bYTeanBq-WNpUeHA", "provisionerId": "gecko-t", "workerType": "t-linux-xlarge", "schedulerId": "gecko-level-1", "taskGroupId": "HDnvYOibTMS8h_5Qzv6fWg", "deadline": "2019-11-23T14:04:41.581Z", "expires": "2019-12-06T14:04:41.581Z", "retriesLeft": 5, "state": "completed", "runs": [{ "runId": 0, "state": "completed", "reasonCreated": "scheduled", "reasonResolved": "completed", "workerGroup": "aws", "workerId": "i-01a6b2a05e2211f7c", "takenUntil": "2019-11-22T15:51:57.083Z", "scheduled": "2019-11-22T15:31:56.661Z", "started": "2019-11-22T15:31:57.162Z", "resolved": "2019-11-22T15:42:46.684Z", }], }, "runId": 0, "task": { "tags": { "kind": "test", "worker-implementation": "docker-worker", "createdForUser": "******", "retrigger": "true", "label": "test-linux64-shippable/opt-awsy-tp6-e10s", "os": "linux", } }, "workerGroup": "aws", "workerId": "i-01a6b2a05e2211f7c", "version": 1, }, } taskGroupId = payload["body"]["status"]["taskGroupId"] taskcluster_config.secrets["test_selection_enabled"] = True taskcluster_config.secrets["test_selection_share"] = 0.1 with PhabricatorMock as phab: bus.add_queue(QUEUE_PHABRICATOR_RESULTS) phab.load_patches_stack(build) phab.update_state(build) phab.load_reviewers(build) bugbug_utils = BugbugUtils(phab.api) bugbug_utils.register(bus) try: await bugbug_utils.task_group_to_push.rem(taskGroupId) except KeyError: pass # Nothing happens for tasks that are not test tasks. payload["body"]["task"]["tags"]["kind"] = "source-test" await bugbug_utils.got_try_task_end(payload) assert bus.queues[QUEUE_PHABRICATOR_RESULTS].empty() # Nothing happens for tasks that are not registered. payload["body"]["task"]["tags"]["kind"] = "test" await bugbug_utils.got_try_task_end(payload) assert bus.queues[QUEUE_PHABRICATOR_RESULTS].empty() push = { "build": build, "revision": "028980a035fb3e214f7645675a01a52234aad0fe", } await bugbug_utils.task_group_to_push.set(taskGroupId, push) payload["body"]["status"]["state"] = "completed" await bugbug_utils.got_try_task_end(payload) mode, build_, extras = await bus.receive(QUEUE_PHABRICATOR_RESULTS) assert mode == "test_result" assert build_ == build assert extras == { "name": "test-linux64-shippable/opt-awsy-tp6-e10s", "result": UnitResultState.Pass, "details": None, } payload["body"]["status"]["state"] = "failed" await bugbug_utils.got_try_task_end(payload) mode, build_, extras = await bus.receive(QUEUE_PHABRICATOR_RESULTS) assert mode == "test_result" assert build_ == build assert extras == { "name": "test-linux64-shippable/opt-awsy-tp6-e10s", "result": UnitResultState.Fail, "details": "https://treeherder.mozilla.org/#/jobs?repo=try&revision=028980a035fb3e214f7645675a01a52234aad0fe&selectedTaskRun=W2SMZ3bYTeanBq-WNpUeHA-0", }
async def test_got_bugbug_test_select_end(PhabricatorMock, mock_taskcluster): bus = MessageBus() build = PhabricatorBuild( MockRequest( diff="125397", repo="PHID-REPO-saax4qdxlbbhahhp2kg5", revision="36474", target="PHID-HMBT-icusvlfibcebizyd33op", )) diffId = str(build.diff_id) payload = { "routing": { "exchange": "exchange/taskcluster-queue/v1/task-completed", "key": "primary.OhtlizLqT9ah2jVkUL-yvg.0.community-tc-workers-google.8155538221748661937.proj-relman.compute-large.-.OhtlizLqT9ah2jVkUL-yvg._", "other_routes": [ b"[email protected]", b"route.notify.irc-channel.#bugbug.on-failed", b"route.index.project.relman.bugbug.test_select.latest", f"route.index.project.relman.bugbug.test_select.diff.{diffId}". encode(), b"route.project.relman.bugbug.test_select", ], }, "body": { "status": { "taskId": "bugbug-test-select", "provisionerId": "proj-relman", "workerType": "compute-large", "schedulerId": "-", "taskGroupId": "HDnvYOibTMS8h_5Qzv6fWg", "deadline": "2019-11-27T17:03:07.100Z", "expires": "2019-12-27T15:03:07.100Z", "retriesLeft": 5, "state": "completed", "runs": [{ "runId": 0, "state": "completed", "reasonCreated": "scheduled", "reasonResolved": "completed", "workerGroup": "community-tc-workers-google", "workerId": "8155538221748661937", "takenUntil": "2019-11-27T15:25:02.767Z", "scheduled": "2019-11-27T15:03:07.606Z", "started": "2019-11-27T15:05:02.786Z", "resolved": "2019-11-27T15:19:24.809Z", }], }, "runId": 0, "task": { "tags": {} }, "workerGroup": "community-tc-workers-google", "workerId": "8155538221748661937", "version": 1, }, } taskGroupId = payload["body"]["status"]["taskGroupId"] taskcluster_config.secrets["test_selection_enabled"] = True taskcluster_config.secrets["test_selection_share"] = 0.1 with PhabricatorMock as phab: phab.load_patches_stack(build) phab.update_state(build) bugbug_utils = BugbugUtils(phab.api) bugbug_utils.register(bus) try: await bugbug_utils.diff_to_push.rem(diffId) except KeyError: pass try: await bugbug_utils.task_group_to_push.rem(taskGroupId) except KeyError: pass # Nothing happens when diff_to_push is empty. with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps: rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select", body=mock_taskcluster("task-bugbug-test-select.json"), content_type="application/json", ) rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select/artifacts/public%2Ffailure_risk", body=mock_taskcluster("artifact-bugbug-test-select-failure-risk"), ) rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select/artifacts/public%2Fselected_tasks", body=mock_taskcluster( "artifact-bugbug-test-select-selected-tasks"), ) with pytest.raises(KeyError): await bugbug_utils.diff_to_push.get(diffId) await bugbug_utils.got_bugbug_test_select_end(payload) with pytest.raises(KeyError): await bugbug_utils.task_group_to_push.get(taskGroupId) # Nothing happens when we are on the wrong Phabricator deployment. with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps: rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select", body=mock_taskcluster("task-bugbug-test-select.json"), content_type="application/json", ) bugbug_utils.phabricator_deployment = "dev" await bugbug_utils.diff_to_push.set(diffId, { "revision": "123", "build": build }) await bugbug_utils.got_bugbug_test_select_end(payload) with pytest.raises(KeyError): await bugbug_utils.task_group_to_push.get(taskGroupId) await bugbug_utils.diff_to_push.rem(diffId) bugbug_utils.phabricator_deployment = "prod" # Nothing happens when the failure risk is low. with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps: rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select", body=mock_taskcluster("task-bugbug-test-select.json"), content_type="application/json", ) rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select/artifacts/public%2Ffailure_risk", body=mock_taskcluster( "artifact-bugbug-test-select-failure-risk-0"), ) await bugbug_utils.diff_to_push.set(diffId, { "revision": "123", "build": build }) await bugbug_utils.got_bugbug_test_select_end(payload) with pytest.raises(KeyError): await bugbug_utils.task_group_to_push.get(taskGroupId) # Wait removal of object from diff_to_push to be done. tasks = set(asyncio.all_tasks()) tasks.remove(asyncio.current_task()) await asyncio.gather(*tasks) with pytest.raises(KeyError): await bugbug_utils.diff_to_push.get(diffId) # Nothing happens when the failure risk is high but there are no selected tasks. with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps: rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select", body=mock_taskcluster("task-bugbug-test-select.json"), content_type="application/json", ) rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select/artifacts/public%2Ffailure_risk", body=mock_taskcluster("artifact-bugbug-test-select-failure-risk"), ) rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select/artifacts/public%2Fselected_tasks", body=mock_taskcluster( "artifact-bugbug-test-select-selected-tasks-none"), ) await bugbug_utils.diff_to_push.set(diffId, { "revision": "123", "build": build }) await bugbug_utils.got_bugbug_test_select_end(payload) with pytest.raises(KeyError): await bugbug_utils.task_group_to_push.get(taskGroupId) # Wait removal of object from diff_to_push to be done. tasks = set(asyncio.all_tasks()) tasks.remove(asyncio.current_task()) await asyncio.gather(*tasks) with pytest.raises(KeyError): await bugbug_utils.diff_to_push.get(diffId) # Stuff happens. with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps: rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select", body=mock_taskcluster("task-bugbug-test-select.json"), content_type="application/json", ) rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select/artifacts/public%2Ffailure_risk", body=mock_taskcluster("artifact-bugbug-test-select-failure-risk"), ) rsps.add( responses.GET, "http://community_taskcluster.test/api/queue/v1/task/bugbug-test-select/artifacts/public%2Fselected_tasks", body=mock_taskcluster( "artifact-bugbug-test-select-selected-tasks"), ) rsps.add( responses.GET, "http://taskcluster.test/api/index/v1/task/gecko.v2.try.revision.123.taskgraph.decision", body=mock_taskcluster("index-gecko-decision.json"), content_type="application/json", ) rsps.add( responses.GET, f"http://taskcluster.test/api/queue/v1/task/{taskGroupId}/artifacts/public%2Factions.json", body=mock_taskcluster("artifact-gecko-decision-actions.json"), content_type="application/json", ) def trigger_hook_callback(request): payload = json.loads(request.body) assert payload == json.loads( mock_taskcluster("trigger-hook-add-new-jobs-post-body.json")) return ( 200, { "Content-Type": "application/json" }, mock_taskcluster("trigger-hook-add-new-jobs.json"), ) rsps.add_callback( responses.POST, "http://taskcluster.test/api/hooks/v1/hooks/project-gecko/in-tree-action-1-generic%2Fea5d85cbef/trigger", callback=trigger_hook_callback, ) push = {"revision": "123", "build": build} await bugbug_utils.diff_to_push.set(diffId, push) await bugbug_utils.got_bugbug_test_select_end(payload) assert await bugbug_utils.task_group_to_push.get(taskGroupId) == push # Wait removal of object from diff_to_push to be done. tasks = set(asyncio.all_tasks()) tasks.remove(asyncio.current_task()) await asyncio.gather(*tasks) with pytest.raises(KeyError): await bugbug_utils.diff_to_push.get(diffId)
def __init__(self, cache_root): # Create message bus shared amongst processes self.bus = MessageBus() publish = taskcluster_config.secrets["PHABRICATOR"].get( "publish", False) # Check the redis support is enabled on Heroku if heroku.in_dyno(): assert self.bus.redis_enabled is True, "Need Redis on Heroku" community_config = taskcluster_config.secrets.get( "taskcluster_community") test_selection_enabled = taskcluster_config.secrets.get( "test_selection_enabled", False) # Run webserver & pulse on web dyno or single instance if not heroku.in_dyno() or heroku.in_web_dyno(): # Create web server self.webserver = WebServer(QUEUE_WEB_BUILDS) self.webserver.register(self.bus) # Create pulse listener exchanges = {} if taskcluster_config.secrets["autoland_enabled"]: logger.info("Autoland ingestion is enabled") # autoland ingestion exchanges[QUEUE_PULSE_AUTOLAND] = [(PULSE_TASK_GROUP_RESOLVED, ["#.gecko-level-3.#"])] # Create pulse listeners for bugbug test selection task and unit test failures. if community_config is not None and test_selection_enabled: exchanges[QUEUE_PULSE_TRY_TASK_END] = [ (PULSE_TASK_COMPLETED, ["#.gecko-level-1.#"]), (PULSE_TASK_FAILED, ["#.gecko-level-1.#"]), # https://bugzilla.mozilla.org/show_bug.cgi?id=1599863 # ( # "exchange/taskcluster-queue/v1/task-exception", # ["#.gecko-level-1.#"], # ), ] self.community_pulse = PulseListener( { QUEUE_PULSE_BUGBUG_TEST_SELECT: [( "exchange/taskcluster-queue/v1/task-completed", ["route.project.relman.bugbug.test_select"], )] }, taskcluster_config.secrets["communitytc_pulse_user"], taskcluster_config.secrets["communitytc_pulse_password"], "communitytc", ) # Manually register to set queue as redis self.community_pulse.bus = self.bus self.bus.add_queue(QUEUE_PULSE_BUGBUG_TEST_SELECT, redis=True) self.bus.add_queue(QUEUE_PULSE_TRY_TASK_END, redis=True) else: self.community_pulse = None if exchanges: self.pulse = PulseListener( exchanges, taskcluster_config.secrets["pulse_user"], taskcluster_config.secrets["pulse_password"], ) # Manually register to set queue as redis self.pulse.bus = self.bus self.bus.add_queue(QUEUE_PULSE_AUTOLAND, redis=True) else: self.pulse = None else: self.bugbug_utils = None self.webserver = None self.pulse = None self.community_pulse = None logger.info("Skipping webserver, bugbug and pulse consumers") # Register queues for workers self.bus.add_queue(QUEUE_PULSE_AUTOLAND, redis=True) self.bus.add_queue(QUEUE_PULSE_BUGBUG_TEST_SELECT, redis=True) self.bus.add_queue(QUEUE_PULSE_TRY_TASK_END, redis=True) self.bus.add_queue(QUEUE_WEB_BUILDS, redis=True) # Run work processes on worker dyno or single instance if not heroku.in_dyno() or heroku.in_worker_dyno(): self.workflow = CodeReview( api_key=taskcluster_config.secrets["PHABRICATOR"]["api_key"], url=taskcluster_config.secrets["PHABRICATOR"]["url"], publish=publish, user_blacklist=taskcluster_config.secrets["user_blacklist"], ) self.workflow.register(self.bus) # Build mercurial worker and queue self.mercurial = MercurialWorker( QUEUE_MERCURIAL, QUEUE_MERCURIAL_APPLIED, repositories=self.workflow.get_repositories( taskcluster_config.secrets["repositories"], cache_root, default_ssh_key=taskcluster_config.secrets["ssh_key"], ), ) self.mercurial.register(self.bus) # Setup monitoring for newly created tasks self.monitoring = Monitoring( taskcluster_config, QUEUE_MONITORING, taskcluster_config.secrets["admins"], MONITORING_PERIOD, ) self.monitoring.register(self.bus) # Setup monitoring for newly created community tasks if community_config is not None: self.community_monitoring = Monitoring( community_taskcluster_config, QUEUE_MONITORING_COMMUNITY, taskcluster_config.secrets["admins"], MONITORING_PERIOD, ) self.community_monitoring.register(self.bus) else: self.community_monitoring = None self.bugbug_utils = BugbugUtils(self.workflow.api) self.bugbug_utils.register(self.bus) else: self.workflow = None self.mercurial = None self.monitoring = None self.community_monitoring = None self.bugbug_utils = None logger.info("Skipping workers consumers")
class Events(object): """ Listen to HTTP notifications from phabricator and trigger new try jobs """ def __init__(self, cache_root): # Create message bus shared amongst processes self.bus = MessageBus() publish = taskcluster_config.secrets["PHABRICATOR"].get( "publish", False) # Check the redis support is enabled on Heroku if heroku.in_dyno(): assert self.bus.redis_enabled is True, "Need Redis on Heroku" community_config = taskcluster_config.secrets.get( "taskcluster_community") test_selection_enabled = taskcluster_config.secrets.get( "test_selection_enabled", False) # Run webserver & pulse on web dyno or single instance if not heroku.in_dyno() or heroku.in_web_dyno(): # Create web server self.webserver = WebServer(QUEUE_WEB_BUILDS) self.webserver.register(self.bus) # Create pulse listener exchanges = {} if taskcluster_config.secrets["autoland_enabled"]: logger.info("Autoland ingestion is enabled") # autoland ingestion exchanges[QUEUE_PULSE_AUTOLAND] = [(PULSE_TASK_GROUP_RESOLVED, ["#.gecko-level-3.#"])] # Create pulse listeners for bugbug test selection task and unit test failures. if community_config is not None and test_selection_enabled: exchanges[QUEUE_PULSE_TRY_TASK_END] = [ (PULSE_TASK_COMPLETED, ["#.gecko-level-1.#"]), (PULSE_TASK_FAILED, ["#.gecko-level-1.#"]), # https://bugzilla.mozilla.org/show_bug.cgi?id=1599863 # ( # "exchange/taskcluster-queue/v1/task-exception", # ["#.gecko-level-1.#"], # ), ] self.community_pulse = PulseListener( { QUEUE_PULSE_BUGBUG_TEST_SELECT: [( "exchange/taskcluster-queue/v1/task-completed", ["route.project.relman.bugbug.test_select"], )] }, taskcluster_config.secrets["communitytc_pulse_user"], taskcluster_config.secrets["communitytc_pulse_password"], "communitytc", ) # Manually register to set queue as redis self.community_pulse.bus = self.bus self.bus.add_queue(QUEUE_PULSE_BUGBUG_TEST_SELECT, redis=True) self.bus.add_queue(QUEUE_PULSE_TRY_TASK_END, redis=True) else: self.community_pulse = None if exchanges: self.pulse = PulseListener( exchanges, taskcluster_config.secrets["pulse_user"], taskcluster_config.secrets["pulse_password"], ) # Manually register to set queue as redis self.pulse.bus = self.bus self.bus.add_queue(QUEUE_PULSE_AUTOLAND, redis=True) else: self.pulse = None else: self.bugbug_utils = None self.webserver = None self.pulse = None self.community_pulse = None logger.info("Skipping webserver, bugbug and pulse consumers") # Register queues for workers self.bus.add_queue(QUEUE_PULSE_AUTOLAND, redis=True) self.bus.add_queue(QUEUE_PULSE_BUGBUG_TEST_SELECT, redis=True) self.bus.add_queue(QUEUE_PULSE_TRY_TASK_END, redis=True) self.bus.add_queue(QUEUE_WEB_BUILDS, redis=True) # Run work processes on worker dyno or single instance if not heroku.in_dyno() or heroku.in_worker_dyno(): self.workflow = CodeReview( api_key=taskcluster_config.secrets["PHABRICATOR"]["api_key"], url=taskcluster_config.secrets["PHABRICATOR"]["url"], publish=publish, user_blacklist=taskcluster_config.secrets["user_blacklist"], ) self.workflow.register(self.bus) # Build mercurial worker and queue self.mercurial = MercurialWorker( QUEUE_MERCURIAL, QUEUE_MERCURIAL_APPLIED, repositories=self.workflow.get_repositories( taskcluster_config.secrets["repositories"], cache_root, default_ssh_key=taskcluster_config.secrets["ssh_key"], ), ) self.mercurial.register(self.bus) # Setup monitoring for newly created tasks self.monitoring = Monitoring( taskcluster_config, QUEUE_MONITORING, taskcluster_config.secrets["admins"], MONITORING_PERIOD, ) self.monitoring.register(self.bus) # Setup monitoring for newly created community tasks if community_config is not None: self.community_monitoring = Monitoring( community_taskcluster_config, QUEUE_MONITORING_COMMUNITY, taskcluster_config.secrets["admins"], MONITORING_PERIOD, ) self.community_monitoring.register(self.bus) else: self.community_monitoring = None self.bugbug_utils = BugbugUtils(self.workflow.api) self.bugbug_utils.register(self.bus) else: self.workflow = None self.mercurial = None self.monitoring = None self.community_monitoring = None self.bugbug_utils = None logger.info("Skipping workers consumers") def run(self): consumers = [] # Code review main workflow if self.workflow: consumers += [ # Process Phabricator build received from webserver self.bus.run(self.workflow.process_build, QUEUE_WEB_BUILDS, sequential=False), # Publish results on Phabricator self.bus.run( self.workflow.publish_results, QUEUE_PHABRICATOR_RESULTS, sequential=False, ), # Trigger autoland tasks self.bus.run( self.workflow.trigger_autoland, QUEUE_PULSE_AUTOLAND, sequential=False, ), # Send to phabricator results publication for normal processing and to bugbug for further analysis self.bus.dispatch( QUEUE_MERCURIAL_APPLIED, [QUEUE_PHABRICATOR_RESULTS, QUEUE_BUGBUG_TRY_PUSH], ), ] if self.bugbug_utils: consumers += [ self.bus.run(self.bugbug_utils.process_build, QUEUE_BUGBUG, sequential=False), self.bus.run( self.bugbug_utils.process_push, QUEUE_BUGBUG_TRY_PUSH, sequential=False, ), self.bus.run( self.bugbug_utils.got_try_task_end, QUEUE_PULSE_TRY_TASK_END, sequential=False, ), self.bus.run( self.bugbug_utils.got_bugbug_test_select_end, QUEUE_PULSE_BUGBUG_TEST_SELECT, sequential=False, ), ] # Add mercurial task if self.mercurial: consumers.append(self.mercurial.run()) # Add monitoring task if self.monitoring: consumers.append(self.monitoring.run()) # Add community monitoring task if self.community_monitoring: consumers.append(self.community_monitoring.run()) # Add pulse listener for task results. if self.pulse: consumers.append(self.pulse.run()) # Add communitytc pulse listener for test selection results. if self.community_pulse: consumers.append(self.community_pulse.run()) # Start the web server in its own process if self.webserver: self.webserver.start() if consumers: # Run all tasks concurrently run_tasks(consumers) else: # Keep the web server process running asyncio.get_event_loop().run_forever() # Make sure any pending task is run. run_tasks(asyncio.Task.all_tasks()) # Stop the webserver when other async processes are stopped if self.webserver: self.webserver.stop()