No bug: [fxci] Use information from hg.mozilla.org to replay hg-push tasks; r=aki
authorTom Prince <mozilla@hocat.ca>
Wed, 29 Apr 2020 21:06:09 +0000
changeset 219 ce7ae9a988cd41bf9ab5852ba8923cc43e62ea34
parent 218 6b68d2423c65a2e26faafd97d4b3cafad1580c8e
child 220 9c9a898b351909b2e0fe8420ac9d649ded523af3
push id157
push usermozilla@hocat.ca
push dateWed, 29 Apr 2020 21:18:17 +0000
treeherderci-admin@ce7ae9a988cd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaki
No bug: [fxci] Use information from hg.mozilla.org to replay hg-push tasks; r=aki Originally, we replayed hg-push push tasks by extracting the pulse message from the previously run hg-push task. But that doesn't work if the task did not get generated, or if the task has expired. We can get the information required to rebuild the pulse message from hg.mozilla.org, which does not expire, instead. Differential Revision: https://phabricator.services.mozilla.com/D73110
src/fxci/cli.py
src/fxci/hg_pushes.py
--- a/src/fxci/cli.py
+++ b/src/fxci/cli.py
@@ -93,27 +93,22 @@ async def create_worker_secrets(options)
     from .worker_secrets import create_worker_secrets
 
     await create_worker_secrets(update=options["update"])
 
 
 @app.command("replay-hg-push", help="Retrigger the on-push tasks of an mercurial push")
 @app.argument("alias", help="The project alias of the push to retrigger.")
 @app.argument("revision", help="The tip revision of the push to retrigger.")
-@app.argument("--source-environment")
 @ciconfig_arguments(app, use_environment=False)
 @run_async
 async def replay_hg_push(options):
     from .hg_pushes import replay_hg_push
 
-    await replay_hg_push(
-        alias=options["alias"],
-        revision=options["revision"],
-        source_environment_name=options["source_environment"],
-    )
+    await replay_hg_push(alias=options["alias"], revision=options["revision"])
 
 
 @app.command("list-workers")
 @app.argument("worker-pool")
 @app.argument(
     "--state",
     dest="states",
     action="append",
--- a/src/fxci/hg_pushes.py
+++ b/src/fxci/hg_pushes.py
@@ -1,71 +1,87 @@
 # -*- coding: utf-8 -*-
 
 # This Source Code Form is subject to the terms of the Mozilla Public License,
 # v. 2.0. If a copy of the MPL was not distributed with this file, You can
 # obtain one at http://mozilla.org/MPL/2.0/.
 
-import json
 import sys
 
 from taskcluster import optionsFromEnvironment
-from taskcluster.aio import Hooks, Index, Queue
+from taskcluster.aio import Hooks
 
-from ciadmin.generate.ciconfig.environment import Environment
 from ciadmin.generate.ciconfig.projects import Project
 from tcadmin.util.sessions import aiohttp_session, with_aiohttp_session
 
 TASK_URL = "{root_url}/tasks/{task_id}"
+JSON_PUSH_URL = "{}/json-pushes?version=2&changeset={}"
 
 
 @with_aiohttp_session
-async def replay_hg_push(*, alias, revision, source_environment_name):
-    projects = await Project.fetch_all()
-    projects = [project for project in projects if project.alias == alias]
-    if not projects:
+async def replay_hg_push(*, alias, revision):
+    try:
+        project = await Project.get(alias)
+    except KeyError:
         sys.stderr.write("Unknown project alias: {}\n".format(alias))
         sys.exit(1)
-    if not any(project.feature("hg-push") for project in projects):
+
+    if not project.feature("hg-push"):
         sys.stderr.write("Project {} does not have hg-push feature.\n".format(alias))
         sys.exit(1)
 
-    if source_environment_name is not None:
-        source_environment = await Environment.get(source_environment_name)
-        source_options = {"rootUrl": source_environment.root_url}
-    else:
-        source_options = optionsFromEnvironment()
-
     target_options = optionsFromEnvironment()
-
-    source_index_api = Index(source_options, session=aiohttp_session())
-    source_queue_api = Queue(source_options, session=aiohttp_session())
     target_hooks_api = Hooks(target_options, session=aiohttp_session())
 
-    index = "hg-push.v1.{alias}.revision.{revision}".format(
-        alias=alias, revision=revision
-    )
-
     try:
-        result = await source_index_api.findTask(index)
-        task = await source_queue_api.task(result["taskId"])
+        async with aiohttp_session().get(
+            JSON_PUSH_URL.format(project.repo, revision)
+        ) as response:
+            response.raise_for_status()
+            result = await response.json()
+        pushes = result["pushes"]
     except Exception as e:
         sys.stderr.write(
-            "Could not find original hg-push task: {}\n".format(str(e).splitlines()[0])
+            f"Could not get push info {alias} {revision} from hg.mozilla.org: {e}"
         )
         sys.exit(1)
-    try:
-        pulse_message = json.loads(task["payload"]["env"]["PULSE_MESSAGE"])
-    except Exception as e:
-        sys.stderr.write(
-            "Could not get pulse message from task {task_id}: {exception}\n".format(
-                task_id=result["taskId"], exception=e
+
+    if len(pushes) != 1:
+        print(
+            "Changeset {} has {} associated pushes; "
+            "only one expected".format(revision, len(pushes))
+        )
+        sys.exit(1)
+    [(push_id, push_info)] = pushes.items()
+    if revision not in push_info["changesets"]:
+        print(
+            "Changeset {} is not the tip {} of the associated push.".format(
+                revision, push_info["changesets"][0]
             )
         )
         sys.exit(1)
+
+    pulse_message = {
+        "payload": {
+            "type": "changegroup.1",
+            "data": {
+                "repo_url": project.repo,
+                "heads": [revision],
+                "pushlog_pushes": [
+                    {
+                        "user": push_info["user"],
+                        "pushid": int(push_id),
+                        "time": push_info["date"],
+                    }
+                ],
+            },
+        },
+        "_meta": {},
+    }
+
     try:
         response = await target_hooks_api.triggerHook("hg-push", alias, pulse_message)
     except Exception as e:
         sys.stderr.write("Could not get create hg-push task: {}\n".format(e))
         sys.exit(1)
 
     print(
         TASK_URL.format(