From 2b99afca5feabe3514e984064b7b08e7c9858546 Mon Sep 17 00:00:00 2001 From: Olivier Mehani Date: Thu, 23 Apr 2026 17:17:57 +1000 Subject: [PATCH 1/5] build: import example taskcluster config from taskgraph [0] https://raw.githubusercontent.com/taskcluster/taskgraph/refs/heads/main/.taskcluster.yml --- .taskcluster.yml | 423 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 329 insertions(+), 94 deletions(-) diff --git a/.taskcluster.yml b/.taskcluster.yml index a9abf90..dbc15a8 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -1,97 +1,332 @@ +# yamllint disable rule:line-length +# This file is rendered via JSON-e by +# - github events - https://github.com/taskcluster/taskcluster/tree/main/services/github +# - cron tasks - https://hg.mozilla.org/ci/ci-admin/file/default/build-decision/ +# - action tasks - taskcluster/taskgraph/actions/registry.py +--- version: 1 -policy: - pullRequests: public reporting: checks-v1 +autoCancelPreviousChecks: true +policy: + pullRequests: public_restricted tasks: - $let: - head_branch: - $if: 'tasks_for == "github-pull-request"' - then: ${event.pull_request.head.ref} - else: - $if: 'tasks_for == "github-push"' - then: - # Strip ref branch prefix - $if: 'event.ref[0:11] == "refs/heads/"' - then: ${event.ref[11:]} - else: ${event.ref} - else: ${event.release.target_commitish} - - head_rev: - $if: 'tasks_for == "github-pull-request"' - then: ${event.pull_request.head.sha} - else: - $if: 'tasks_for == "github-push"' - then: ${event.after} - else: ${event.release.tag_name} - - repository: - $if: 'tasks_for == "github-pull-request"' - then: ${event.pull_request.head.repo.html_url} - else: ${event.repository.html_url} - - channel: - $if: 'tasks_for == "github-push"' - then: - $if: 'event.ref in ["refs/heads/testing", "refs/heads/production"]' - then: ${event.ref[11:]} - else: "dev" - else: "dev" - - taskboot_image: "mozilla/taskboot:0.4.1" - - provisionerId: "proj-engwf" - - workerType: - $if: 'taskcluster_root_url == "https://firefox-ci-tc.services.mozilla.com"' - then: linux-gw-gcp - else: generic-worker-ubuntu-24-04 - in: - $if: '(tasks_for == "github-push" && (head_branch == "main" || head_branch == "production" || head_branch == "testing")) || (tasks_for == "github-pull-request" && event["action"] in ["opened", "reopened", "synchronize"])' - then: - $flatten: - $match: - # Run only on firefoxci Taskcluster - 'taskcluster_root_url == "https://firefox-ci-tc.services.mozilla.com"': - - taskId: { $eval: as_slugid("build_dind") } - created: { $fromNow: "" } - deadline: { $fromNow: "1 hour" } - provisionerId: "${provisionerId}" - workerType: "${workerType}" - payload: - maxRunTime: 3600 - image: "${taskboot_image}" - env: - GIT_REPOSITORY: ${repository} - GIT_REVISION: ${head_rev} - command: - - taskboot - - build - - --image - - mozilla-conduit/reviewer-selector - - --tag - - "${channel}" - - --tag - - "${head_rev}" - - --write - - /reviewer-selector.tar - - docker/Dockerfile - artifacts: - public/reviewer-selector.tar.zst: - expires: { $fromNow: "6 months" } - path: /reviewer-selector.tar.zst - type: file - scopes: - - 'assume:repo:github.com/${event.pull_request.base.repo.full_name}:${tasks_for[7:]}' - routes: - $if: 'tasks_for == "github-pull-request"' - then: - - "index.project.engwf.production.reviewer-selector-pr.revision.${head_rev}" - - "index.project.engwf.production.reviewer-selector-pr.branch.${head_branch}" - else: - - "index.project.engwf.production.reviewer-selector.revision.${head_rev}" - - "index.project.engwf.production.reviewer-selector.branch.${head_branch}" - metadata: - name: Reviewer selector docker in docker build - description: Build docker image of the reviewer selector, using a remote docker daemon - owner: omehani@mozilla.com - source: https://github.com/mozilla-conduit/reviewer-selector + # NOTE: support for actions in ci-admin requires that the `tasks` property be an array *before* JSON-e rendering + # takes place. + - $let: + trustDomain: taskgraph + ownerEmail: + $switch: + 'tasks_for == "github-push"': '${event.pusher.email}' + 'tasks_for == "github-release"': 'release+taskgraph-ci@mozilla.com' + 'tasks_for[:19] == "github-pull-request"': '${event.pull_request.user.login}@users.noreply.github.com' + 'tasks_for in ["cron", "action", "pr-action"]': '${tasks_for}@noreply.mozilla.org' + baseRepoUrl: + $switch: + 'tasks_for[:19] == "github-pull-request"': '${event.pull_request.base.repo.html_url}' + 'tasks_for in ["cron", "action"]': '${repository.url}' + 'tasks_for == "pr-action"': '${repository.base_url}' + $default: '${event.repository.html_url}' + repoUrl: + $switch: + 'tasks_for[:19] == "github-pull-request"': '${event.pull_request.head.repo.html_url}' + 'tasks_for in ["cron", "action", "pr-action"]': '${repository.url}' + $default: '${event.repository.html_url}' + project: + $switch: + 'tasks_for in ["github-push", "github-release"]': '${event.repository.name}' + 'tasks_for[:19] == "github-pull-request"': '${event.pull_request.base.repo.name}' + 'tasks_for in ["cron", "action", "pr-action"]': '${repository.project}' + head_branch: + $switch: + 'tasks_for[:19] == "github-pull-request"': ${event.pull_request.head.ref} + 'tasks_for == "github-push"': ${event.ref} + 'tasks_for == "github-release"': '${event.release.target_commitish}' + 'tasks_for in ["cron", "action", "pr-action"]': '${push.branch}' + base_ref: + $switch: + 'tasks_for[:19] == "github-pull-request"': ${event.pull_request.base.ref} + # event.base_ref is barely documented[1]. Testing showed it's only + # defined when creating a new branch. It's null when pushing to an + # existing branch + # + # [1] https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#push + 'tasks_for == "github-push" && event.base_ref': ${event.base_ref} + 'tasks_for == "github-push" && !(event.base_ref)': ${event.ref} + 'tasks_for == "github-release"': '' + 'tasks_for in ["cron", "action"]': '${push.branch}' + 'tasks_for == "pr-action"': '${push.base_branch}' + head_ref: + $switch: + 'tasks_for[:19] == "github-pull-request"': ${event.pull_request.head.ref} + 'tasks_for == "github-push"': ${event.ref} + 'tasks_for in ["cron", "action", "pr-action"]': '${push.branch}' + 'tasks_for == "github-release"': ${event.release.tag_name} + base_sha: + $switch: + 'tasks_for == "github-push"': '${event.before}' + 'tasks_for == "github-release"': '${event.release.target_commitish}' + 'tasks_for[:19] == "github-pull-request"': '${event.pull_request.base.sha}' + 'tasks_for in ["cron", "action", "pr-action"]': '${push.revision}' + head_sha: + $switch: + 'tasks_for == "github-push"': '${event.after}' + 'tasks_for[:19] == "github-pull-request"': '${event.pull_request.head.sha}' + 'tasks_for in ["cron", "action", "pr-action"]': '${push.revision}' + 'tasks_for == "github-release"': '${event.release.tag_name}' + ownTaskId: + $switch: + '"github" in tasks_for': {$eval: as_slugid("decision_task")} + 'tasks_for in ["cron", "action", "pr-action"]': '${ownTaskId}' + pullRequestAction: + $switch: + 'tasks_for[:19] == "github-pull-request"': ${event.action} + $default: 'UNDEFINED' + releaseAction: + $if: 'tasks_for == "github-release"' + then: ${event.action} + else: 'UNDEFINED' + isPullRequest: + $eval: 'tasks_for[:19] == "github-pull-request"' + in: + $if: > + tasks_for in ["action", "pr-action", "cron"] + || (tasks_for == "github-release" && releaseAction == "published") + || (tasks_for == "github-push" && head_branch == "refs/heads/main") + || (isPullRequest && pullRequestAction in ["opened", "reopened", "synchronize"]) + then: + $let: + level: + $if: 'tasks_for in ["github-release", "github-push", "cron", "action"] && repoUrl == "https://github.com/taskcluster/taskgraph"' + then: 3 + else: 1 + short_head_ref: + $if: 'head_ref[:10] == "refs/tags/"' + then: {$eval: 'head_ref[10:]'} + else: + $if: 'head_ref[:11] == "refs/heads/"' + then: {$eval: 'head_ref[11:]'} + else: ${head_ref} + in: + taskId: {$if: 'tasks_for != "action" && tasks_for != "pr-action"', then: '${ownTaskId}'} + taskGroupId: + $if: 'tasks_for == "action" || tasks_for == "pr-action"' + then: + '${action.taskGroupId}' + else: + '${ownTaskId}' # same as taskId; this is how automation identifies a decision task + schedulerId: '${trustDomain}-level-${level}' + + created: {$fromNow: ''} + deadline: {$fromNow: '1 day'} + expires: {$fromNow: '1 year 1 second'} # 1 second so artifacts expire first + metadata: + $merge: + - owner: "${ownerEmail}" + source: "${repoUrl}/raw/${head_sha}/.taskcluster.yml" + - $switch: + 'tasks_for in ["github-push", "github-release"] || isPullRequest': + name: "Decision Task" + description: 'The task that creates all of the other tasks in the task graph' + 'tasks_for == "action"': + name: "Action: ${action.title}" + description: | + ${action.description} + + Action triggered by clientID `${clientId}` + 'tasks_for == "pr-action"': + name: "PR action: ${action.title}" + description: | + ${action.description} + + PR action triggered by clientID `${clientId}` + $default: + name: "Decision Task for cron job ${cron.job_name}" + description: 'Created by a [cron task](https://firefox-ci-tc.services.mozilla.com/tasks/${cron.task_id})' + + provisionerId: "${trustDomain}-${level}" + workerType: "decision" + + tags: + $switch: + 'tasks_for == "github-push" || isPullRequest': + createdForUser: "${ownerEmail}" + kind: decision-task + 'tasks_for == "action" || tasks_for == "pr-action"': + createdForUser: '${ownerEmail}' + kind: 'action-callback' + 'tasks_for == "cron"': + kind: cron-task + + routes: + $flatten: + - checks + - {$if: '!isPullRequest && tasks_for != "pr-action"', then: ["tc-treeherder.v2.${project}.${head_sha}"], else: []} + - $switch: + 'tasks_for == "github-push"': + - "index.${trustDomain}.v2.${project}.latest.taskgraph.decision" + - "index.${trustDomain}.v2.${project}.revision.${head_sha}.taskgraph.decision" + 'tasks_for == "action"': + - "index.${trustDomain}.v2.${project}.revision.${head_sha}.taskgraph.actions.${ownTaskId}" + 'tasks_for == "cron"': + - "index.${trustDomain}.v2.${project}.latest.taskgraph.decision-${cron.job_name}" + - "index.${trustDomain}.v2.${project}.revision.${head_sha}.taskgraph.decision-${cron.job_name}" + # list each cron task on this revision, so actions can find them + - 'index.${trustDomain}.v2.${project}.revision.${head_sha}.cron.${ownTaskId}' + $default: [] + + scopes: + $switch: + 'tasks_for == "github-push"': + - 'assume:repo:${repoUrl[8:]}:branch:${short_head_ref}' + 'tasks_for == "github-release"': + - 'assume:repo:${repoUrl[8:]}:release:${releaseAction}' + 'isPullRequest': + - 'assume:repo:github.com/${event.pull_request.base.repo.full_name}:${tasks_for[7:]}' + 'tasks_for == "action"': + - 'assume:repo:${repoUrl[8:]}:action:${action.action_perm}' + 'tasks_for == "pr-action"': + - 'assume:repo:${baseRepoUrl[8:]}:pr-action:${action.action_perm}' + $default: + - 'assume:repo:${repoUrl[8:]}:cron:${cron.job_name}' + + dependencies: [] + requires: all-completed + + priority: + # Most times, there is plenty of worker capacity so everything runs + # quickly, but sometimes a storm of action tasks lands. Then we + # want, from highest to lowest: + # - cron tasks (time-sensitive) (low) + # - decision tasks (minimize user-visible delay) (very-low) + # - action tasks (avoid interfering with the other two) (lowest) + # SCM levels all use different workerTypes, so there is no need for priority + # between levels; "low" is the highest priority available at all levels, and + # nothing runs at any higher priority on these workerTypes. + $if: "tasks_for == 'cron'" + then: low + else: + $if: 'tasks_for == "github-push" || isPullRequest' + then: very-low + else: lowest # tasks_for == 'action' + retries: 5 + + payload: + env: + # run-task uses these to check out the source; the inputs + # to `mach taskgraph decision` are all on the command line. + $merge: + - TASKGRAPH_BASE_REPOSITORY: '${baseRepoUrl}' + TASKGRAPH_BASE_REF: '${base_ref}' + TASKGRAPH_BASE_REV: '${base_sha}' + TASKGRAPH_HEAD_REPOSITORY: '${repoUrl}' + TASKGRAPH_HEAD_REF: '${head_ref}' + TASKGRAPH_HEAD_REV: '${head_sha}' + TASKGRAPH_REPOSITORY_TYPE: git + REPOSITORIES: {$json: {taskgraph: Taskgraph}} + - $if: 'isPullRequest' + then: + TASKGRAPH_PULL_REQUEST_NUMBER: '${event.pull_request.number}' + - $if: 'tasks_for == "action" || tasks_for == "pr-action"' + then: + ACTION_TASK_GROUP_ID: '${action.taskGroupId}' # taskGroupId of the target task + ACTION_TASK_ID: {$json: {$eval: 'taskId'}} # taskId of the target task (JSON-encoded) + ACTION_INPUT: {$json: {$eval: 'input'}} + ACTION_CALLBACK: '${action.cb_name}' + + cache: + "${trustDomain}-level-${level}-checkouts-sparse-v2": /builds/worker/checkouts + + features: + taskclusterProxy: true + chainOfTrust: true + + image: mozillareleases/taskgraph:decision-latest + + maxRunTime: 1800 + + command: + - run-task + - '--taskgraph-checkout=/builds/worker/checkouts/src' + - '--' + - bash + - -cx + - $let: + extraArgs: + $if: 'tasks_for == "cron"' + then: '${cron.quoted_args}' + else: + $if: 'tasks_for == "github-pull-request"' + then: '--allow-parameter-override' + else: '' + in: + $if: 'tasks_for == "action" || tasks_for == "pr-action"' + then: > + cd /builds/worker/checkouts/src && + ln -s /builds/worker/artifacts artifacts && + pip3 install --user --break-system-packages . && + taskgraph action-callback + else: > + cd /builds/worker/checkouts/src && + ln -s /builds/worker/artifacts artifacts && + pip3 install --user --break-system-packages . && + taskgraph decision + --verbose + --pushlog-id='0' + --pushdate='0' + --project='${project}' + --owner='${ownerEmail}' + --level='${level}' + --repository-type=git + --tasks-for='${tasks_for}' + --base-repository='${baseRepoUrl}' + --base-ref='${base_ref}' + --base-rev='${base_sha}' + --head-repository='${repoUrl}' + --head-ref='${head_ref}' + --head-rev='${head_sha}' + ${extraArgs} + + artifacts: + 'public': + type: 'directory' + path: '/builds/worker/artifacts' + expires: {$fromNow: '1 year'} + 'public/docker-contexts': + type: 'directory' + path: '/builds/worker/checkouts/src/docker-contexts' + # This needs to be at least the deadline of the + # decision task + the docker-image task deadlines. + # It is set to a week to allow for some time for + # debugging, but they are not useful long-term. + expires: {$fromNow: '7 day'} + + extra: + $merge: + - treeherder: + $merge: + - machine: + platform: gecko-decision + - $switch: + 'tasks_for in ["github-push", "github-release"] || isPullRequest': + symbol: D + 'tasks_for == "action" || tasks_for == "pr-action"': + groupName: 'action-callback' + groupSymbol: AC + symbol: "${action.symbol}" + $default: + groupSymbol: cron + symbol: "${cron.job_symbol}" + - $if: 'tasks_for == "action" || tasks_for == "pr-action"' + then: + parent: '${action.taskGroupId}' + action: + name: '${action.name}' + context: + taskGroupId: '${action.taskGroupId}' + taskId: {$eval: 'taskId'} + input: {$eval: 'input'} + clientId: {$eval: 'clientId'} + - $if: 'tasks_for == "cron"' + then: + cron: {$json: {$eval: 'cron'}} + - tasks_for: '${tasks_for}' From 4418b35344c950003a964734efa3057dd00cdc98 Mon Sep 17 00:00:00 2001 From: Olivier Mehani Date: Thu, 23 Apr 2026 17:37:44 +1000 Subject: [PATCH 2/5] build: use taskboot to build docker image (bug 2028701) With inspiration from code-review-bot's setup [0].w [0] https://github.com/mozilla/code-review/blob/1ba8b62e5a40ed211e5fd6eea9cdbc9bf6d0b752/.taskcluster.yml --- .taskcluster.yml | 83 ++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 45 deletions(-) diff --git a/.taskcluster.yml b/.taskcluster.yml index dbc15a8..214dd1f 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -87,6 +87,28 @@ tasks: else: 'UNDEFINED' isPullRequest: $eval: 'tasks_for[:19] == "github-pull-request"' + + taskboot_image: "mozilla/taskboot:0.4.5" + + channel: + $if: 'tasks_for == "github-push"' + then: + $if: 'event.ref in ["refs/heads/main"]' + then: prod + else: + $if: 'event.ref in ["refs/heads/stage"]' + then: ${event.ref[11:]} + else: "dev" + else: "dev" + + head_rev: + $if: 'tasks_for == "github-pull-request"' + then: ${event.pull_request.head.sha} + else: + $if: 'tasks_for == "github-push"' + then: ${event.after} + else: ${event.release.tag_name} + in: $if: > tasks_for in ["action", "pr-action", "cron"] @@ -240,57 +262,28 @@ tasks: taskclusterProxy: true chainOfTrust: true - image: mozillareleases/taskgraph:decision-latest + image: "${taskboot_image}" maxRunTime: 1800 command: - - run-task - - '--taskgraph-checkout=/builds/worker/checkouts/src' - - '--' - - bash - - -cx - - $let: - extraArgs: - $if: 'tasks_for == "cron"' - then: '${cron.quoted_args}' - else: - $if: 'tasks_for == "github-pull-request"' - then: '--allow-parameter-override' - else: '' - in: - $if: 'tasks_for == "action" || tasks_for == "pr-action"' - then: > - cd /builds/worker/checkouts/src && - ln -s /builds/worker/artifacts artifacts && - pip3 install --user --break-system-packages . && - taskgraph action-callback - else: > - cd /builds/worker/checkouts/src && - ln -s /builds/worker/artifacts artifacts && - pip3 install --user --break-system-packages . && - taskgraph decision - --verbose - --pushlog-id='0' - --pushdate='0' - --project='${project}' - --owner='${ownerEmail}' - --level='${level}' - --repository-type=git - --tasks-for='${tasks_for}' - --base-repository='${baseRepoUrl}' - --base-ref='${base_ref}' - --base-rev='${base_sha}' - --head-repository='${repoUrl}' - --head-ref='${head_ref}' - --head-rev='${head_sha}' - ${extraArgs} + - taskboot + - build + - --image + - mozilla-conduit/reviewer-selector + - --tag + - "${channel}" + - --tag + - "${head_rev}" + - --write + - /reviewer-selector.tar + - docker/Dockerfile artifacts: - 'public': - type: 'directory' - path: '/builds/worker/artifacts' - expires: {$fromNow: '1 year'} + 'public/reviewer-selector.tar.zst': + expires: { $fromNow: "6 months" } + path: /reviewer-selector.tar.zst + type: file 'public/docker-contexts': type: 'directory' path: '/builds/worker/checkouts/src/docker-contexts' From 146d7de1dc8deafcdd8d0077ed446b2423a630c6 Mon Sep 17 00:00:00 2001 From: Olivier Mehani Date: Thu, 23 Apr 2026 18:00:50 +1000 Subject: [PATCH 3/5] build: remove some taskgraph references --- .taskcluster.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.taskcluster.yml b/.taskcluster.yml index 214dd1f..4791872 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -13,11 +13,11 @@ tasks: # NOTE: support for actions in ci-admin requires that the `tasks` property be an array *before* JSON-e rendering # takes place. - $let: - trustDomain: taskgraph + trustDomain: mozilla ownerEmail: $switch: 'tasks_for == "github-push"': '${event.pusher.email}' - 'tasks_for == "github-release"': 'release+taskgraph-ci@mozilla.com' + 'tasks_for == "github-release"': 'omehani@mozilla.com' 'tasks_for[:19] == "github-pull-request"': '${event.pull_request.user.login}@users.noreply.github.com' 'tasks_for in ["cron", "action", "pr-action"]': '${tasks_for}@noreply.mozilla.org' baseRepoUrl: @@ -117,10 +117,7 @@ tasks: || (isPullRequest && pullRequestAction in ["opened", "reopened", "synchronize"]) then: $let: - level: - $if: 'tasks_for in ["github-release", "github-push", "cron", "action"] && repoUrl == "https://github.com/taskcluster/taskgraph"' - then: 3 - else: 1 + level: 3 short_head_ref: $if: 'head_ref[:10] == "refs/tags/"' then: {$eval: 'head_ref[10:]'} From aea3f96b126a21827bfac1c5ca5bb8edfbcc4bd0 Mon Sep 17 00:00:00 2001 From: Olivier Mehani Date: Thu, 7 May 2026 16:17:34 +1000 Subject: [PATCH 4/5] bump test --- test | 1 + 1 file changed, 1 insertion(+) create mode 100644 test diff --git a/test b/test new file mode 100644 index 0000000..02b1438 --- /dev/null +++ b/test @@ -0,0 +1 @@ +991a9b8c-1e9c-4960-a759-847d3914509a From 1674eaf133b01dcce49782355d1e226f8e3f0c55 Mon Sep 17 00:00:00 2001 From: Olivier Mehani Date: Thu, 7 May 2026 17:22:16 +1000 Subject: [PATCH 5/5] drop default level for a test --- .taskcluster.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.taskcluster.yml b/.taskcluster.yml index 4791872..4be564c 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -117,7 +117,7 @@ tasks: || (isPullRequest && pullRequestAction in ["opened", "reopened", "synchronize"]) then: $let: - level: 3 + level: 1 short_head_ref: $if: 'head_ref[:10] == "refs/tags/"' then: {$eval: 'head_ref[10:]'}