From 8ea6dbaf0df7bd4658c74f3e6ab2e672b52161d4 Mon Sep 17 00:00:00 2001 From: Daniel Sutton Date: Mon, 8 Jun 2026 12:51:05 +0100 Subject: [PATCH 1/6] ci: allow forks to override published container image namespace The publish workflows hardcoded ghcr.io/triggerdotdev/... as the image destination, so a fork building on push-to-main would attempt to push to (and attest) the upstream packages. Derive the webapp image repo from github.repository (overridable via the WEBAPP_IMAGE_REPO variable) and read the worker namespace from the IMAGE_REGISTRY variable, both defaulting to the current values so upstream behaviour is unchanged. --- .github/workflows/publish-webapp.yml | 17 +++++++++++++---- .github/workflows/publish-worker-v4.yml | 6 +++++- .github/workflows/publish-worker.yml | 5 ++++- .github/workflows/publish.yml | 2 +- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-webapp.yml b/.github/workflows/publish-webapp.yml index 399ed321b90..cdf6d8215c4 100644 --- a/.github/workflows/publish-webapp.yml +++ b/.github/workflows/publish-webapp.yml @@ -21,6 +21,9 @@ on: short_sha: description: Short commit SHA of the published build value: ${{ jobs.publish.outputs.short_sha }} + image_repo: + description: The image repository the build was published to (without tag) + value: ${{ jobs.publish.outputs.image_repo }} secrets: SENTRY_AUTH_TOKEN: required: false @@ -33,6 +36,7 @@ jobs: outputs: version: ${{ steps.get_tag.outputs.tag }} short_sha: ${{ steps.get_commit.outputs.sha_short }} + image_repo: ${{ steps.set_tags.outputs.image_repo }} steps: - name: 🏭 Setup Depot CLI uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.7.1 @@ -57,17 +61,22 @@ jobs: - name: 📛 Set the tags id: set_tags run: | - ref_without_tag=ghcr.io/triggerdotdev/trigger.dev - image_tags=$ref_without_tag:${STEPS_GET_TAG_OUTPUTS_TAG} + # The image repo defaults to ghcr.io//, so a fork publishes + # to its own package automatically with no extra config. Set the + # WEBAPP_IMAGE_REPO repository variable to override it with any + # registry/path. + image_tags=$REF_WITHOUT_TAG:${STEPS_GET_TAG_OUTPUTS_TAG} # when pushing the mutable main tag, also push an immutable-by-convention # full-commit-sha tag so a commit can be resolved to a specific digest if [[ "${STEPS_GET_TAG_OUTPUTS_TAG}" == "main" ]]; then - image_tags=$image_tags,$ref_without_tag:${GITHUB_SHA} + image_tags=$image_tags,$REF_WITHOUT_TAG:${GITHUB_SHA} fi echo "image_tags=${image_tags}" >> "$GITHUB_OUTPUT" + echo "image_repo=${REF_WITHOUT_TAG}" >> "$GITHUB_OUTPUT" env: + REF_WITHOUT_TAG: ${{ vars.WEBAPP_IMAGE_REPO || format('ghcr.io/{0}', github.repository) }} STEPS_GET_TAG_OUTPUTS_TAG: ${{ steps.get_tag.outputs.tag }} STEPS_GET_TAG_OUTPUTS_IS_SEMVER: ${{ steps.get_tag.outputs.is_semver }} @@ -122,6 +131,6 @@ jobs: continue-on-error: true uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0 with: - subject-name: ghcr.io/triggerdotdev/trigger.dev + subject-name: ${{ steps.set_tags.outputs.image_repo }} subject-digest: ${{ steps.build_push.outputs.digest }} push-to-registry: true diff --git a/.github/workflows/publish-worker-v4.yml b/.github/workflows/publish-worker-v4.yml index ea2a49e7511..fb3aac2eee1 100644 --- a/.github/workflows/publish-worker-v4.yml +++ b/.github/workflows/publish-worker-v4.yml @@ -65,11 +65,15 @@ jobs: - name: 📛 Set tags to push id: set_tags run: | - ref_without_tag=ghcr.io/triggerdotdev/${STEPS_GET_REPOSITORY_OUTPUTS_REPO} + # Defaults to the public namespace. Set the IMAGE_REGISTRY repository + # variable to publish under a different namespace (e.g. in a fork) + # instead of the default packages. + ref_without_tag=${IMAGE_REGISTRY}/${STEPS_GET_REPOSITORY_OUTPUTS_REPO} image_tags=$ref_without_tag:${STEPS_GET_TAG_OUTPUTS_TAG} echo "image_tags=${image_tags}" >> "$GITHUB_OUTPUT" env: + IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY || 'ghcr.io/triggerdotdev' }} STEPS_GET_REPOSITORY_OUTPUTS_REPO: ${{ steps.get_repository.outputs.repo }} STEPS_GET_TAG_OUTPUTS_TAG: ${{ steps.get_tag.outputs.tag }} STEPS_GET_TAG_OUTPUTS_IS_SEMVER: ${{ steps.get_tag.outputs.is_semver }} diff --git a/.github/workflows/publish-worker.yml b/.github/workflows/publish-worker.yml index 55c13455e20..772f5386ab5 100644 --- a/.github/workflows/publish-worker.yml +++ b/.github/workflows/publish-worker.yml @@ -83,7 +83,10 @@ jobs: docker tag infra_image "$REGISTRY/$REPOSITORY:$IMAGE_TAG" docker push "$REGISTRY/$REPOSITORY:$IMAGE_TAG" env: - REGISTRY: ghcr.io/triggerdotdev + # Defaults to the public namespace. Set the IMAGE_REGISTRY repository + # variable to publish worker images under a different namespace (e.g. + # in a fork) instead of the default packages. + REGISTRY: ${{ vars.IMAGE_REGISTRY || 'ghcr.io/triggerdotdev' }} REPOSITORY: ${{ steps.get_repository.outputs.repo }} IMAGE_TAG: ${{ steps.get_tag.outputs.tag }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 64b0f11ea0a..d1e5b5a706e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -106,4 +106,4 @@ jobs: packages: read # pull the just-published image from GHCR uses: ./.github/workflows/trivy-image-webapp.yml with: - image-ref: ghcr.io/triggerdotdev/trigger.dev:${{ needs.publish-webapp.outputs.version }} + image-ref: ${{ needs.publish-webapp.outputs.image_repo }}:${{ needs.publish-webapp.outputs.version }} From 7645e6d02d86b9f713e4dceb49f3f21fafeb33ce Mon Sep 17 00:00:00 2001 From: Daniel Sutton Date: Mon, 8 Jun 2026 13:36:29 +0100 Subject: [PATCH 2/6] ci: make worker image defaults fork-aware Mirror the webapp's fork-friendly default in the worker publish workflows: default the image namespace to ghcr.io/ instead of the hardcoded ghcr.io/triggerdotdev. Upstream resolves byte-identically (owner is triggerdotdev), while forks now publish worker images to their own namespace with no IMAGE_REGISTRY config, matching publish-webapp.yml. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/publish-worker-v4.yml | 8 ++++---- .github/workflows/publish-worker.yml | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/publish-worker-v4.yml b/.github/workflows/publish-worker-v4.yml index fb3aac2eee1..a3ba34c1dd6 100644 --- a/.github/workflows/publish-worker-v4.yml +++ b/.github/workflows/publish-worker-v4.yml @@ -65,15 +65,15 @@ jobs: - name: 📛 Set tags to push id: set_tags run: | - # Defaults to the public namespace. Set the IMAGE_REGISTRY repository - # variable to publish under a different namespace (e.g. in a fork) - # instead of the default packages. + # Defaults to ghcr.io/, so a fork publishes to its own namespace + # automatically. Set the IMAGE_REGISTRY repository variable to publish + # under a different ghcr.io namespace instead. ref_without_tag=${IMAGE_REGISTRY}/${STEPS_GET_REPOSITORY_OUTPUTS_REPO} image_tags=$ref_without_tag:${STEPS_GET_TAG_OUTPUTS_TAG} echo "image_tags=${image_tags}" >> "$GITHUB_OUTPUT" env: - IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY || 'ghcr.io/triggerdotdev' }} + IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} STEPS_GET_REPOSITORY_OUTPUTS_REPO: ${{ steps.get_repository.outputs.repo }} STEPS_GET_TAG_OUTPUTS_TAG: ${{ steps.get_tag.outputs.tag }} STEPS_GET_TAG_OUTPUTS_IS_SEMVER: ${{ steps.get_tag.outputs.is_semver }} diff --git a/.github/workflows/publish-worker.yml b/.github/workflows/publish-worker.yml index 772f5386ab5..a080ee69c4b 100644 --- a/.github/workflows/publish-worker.yml +++ b/.github/workflows/publish-worker.yml @@ -83,10 +83,10 @@ jobs: docker tag infra_image "$REGISTRY/$REPOSITORY:$IMAGE_TAG" docker push "$REGISTRY/$REPOSITORY:$IMAGE_TAG" env: - # Defaults to the public namespace. Set the IMAGE_REGISTRY repository - # variable to publish worker images under a different namespace (e.g. - # in a fork) instead of the default packages. - REGISTRY: ${{ vars.IMAGE_REGISTRY || 'ghcr.io/triggerdotdev' }} + # Defaults to ghcr.io/, so a fork publishes worker images to its + # own namespace automatically. Set the IMAGE_REGISTRY repository variable + # to publish under a different ghcr.io namespace instead. + REGISTRY: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} REPOSITORY: ${{ steps.get_repository.outputs.repo }} IMAGE_TAG: ${{ steps.get_tag.outputs.tag }} From 271521703fce9e1e3ae16a8dd1f7ded17a7627ea Mon Sep 17 00:00:00 2001 From: Daniel Sutton Date: Mon, 8 Jun 2026 14:09:55 +0100 Subject: [PATCH 3/6] ci: resolve image registry once in parent workflow Per review feedback, resolve the target container registry namespace a single time in publish.yml (the orchestration workflow) and pass it down to every publish job as an image_registry input, rather than each child workflow independently computing the default. This also unifies on one override variable: webapp and workers now both key off IMAGE_REGISTRY (a namespace, e.g. ghcr.io/), with the webapp image living at /. The separate WEBAPP_IMAGE_REPO variable is dropped, removing the prior asymmetry between a full-path override for the webapp and a namespace override for workers. Children keep the vars.IMAGE_REGISTRY || ghcr.io/ fallback so the worker workflows still resolve correctly on their direct push triggers. Upstream defaults are byte-identical (owner is triggerdotdev). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/publish-webapp.yml | 15 ++++++++++----- .github/workflows/publish-worker-v4.yml | 13 +++++++++---- .github/workflows/publish-worker.yml | 13 +++++++++---- .github/workflows/publish.yml | 25 ++++++++++++++++++++++--- 4 files changed, 50 insertions(+), 16 deletions(-) diff --git a/.github/workflows/publish-webapp.yml b/.github/workflows/publish-webapp.yml index cdf6d8215c4..07f64865193 100644 --- a/.github/workflows/publish-webapp.yml +++ b/.github/workflows/publish-webapp.yml @@ -14,6 +14,11 @@ on: type: string required: false default: "" + image_registry: + description: The registry namespace to publish under (e.g. ghcr.io/) + type: string + required: false + default: "" outputs: version: description: The published image tag @@ -61,10 +66,10 @@ jobs: - name: 📛 Set the tags id: set_tags run: | - # The image repo defaults to ghcr.io//, so a fork publishes - # to its own package automatically with no extra config. Set the - # WEBAPP_IMAGE_REPO repository variable to override it with any - # registry/path. + # The registry namespace is resolved by the caller (defaulting to + # ghcr.io/, overridable via the IMAGE_REGISTRY repository + # variable); the webapp image lives at /. A fork + # therefore publishes to its own package automatically. image_tags=$REF_WITHOUT_TAG:${STEPS_GET_TAG_OUTPUTS_TAG} # when pushing the mutable main tag, also push an immutable-by-convention @@ -76,7 +81,7 @@ jobs: echo "image_tags=${image_tags}" >> "$GITHUB_OUTPUT" echo "image_repo=${REF_WITHOUT_TAG}" >> "$GITHUB_OUTPUT" env: - REF_WITHOUT_TAG: ${{ vars.WEBAPP_IMAGE_REPO || format('ghcr.io/{0}', github.repository) }} + REF_WITHOUT_TAG: ${{ format('{0}/{1}', inputs.image_registry || vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner), github.event.repository.name) }} STEPS_GET_TAG_OUTPUTS_TAG: ${{ steps.get_tag.outputs.tag }} STEPS_GET_TAG_OUTPUTS_IS_SEMVER: ${{ steps.get_tag.outputs.is_semver }} diff --git a/.github/workflows/publish-worker-v4.yml b/.github/workflows/publish-worker-v4.yml index a3ba34c1dd6..85ca903a8d6 100644 --- a/.github/workflows/publish-worker-v4.yml +++ b/.github/workflows/publish-worker-v4.yml @@ -8,6 +8,11 @@ on: type: string required: false default: "" + image_registry: + description: The registry namespace to publish under (e.g. ghcr.io/) + type: string + required: false + default: "" push: tags: - "re2-test-*" @@ -65,15 +70,15 @@ jobs: - name: 📛 Set tags to push id: set_tags run: | - # Defaults to ghcr.io/, so a fork publishes to its own namespace - # automatically. Set the IMAGE_REGISTRY repository variable to publish - # under a different ghcr.io namespace instead. + # Resolved by the caller when invoked from publish.yml; falls back to the + # IMAGE_REGISTRY repository variable (or ghcr.io/) for the direct + # push triggers above, so a fork publishes to its own namespace. ref_without_tag=${IMAGE_REGISTRY}/${STEPS_GET_REPOSITORY_OUTPUTS_REPO} image_tags=$ref_without_tag:${STEPS_GET_TAG_OUTPUTS_TAG} echo "image_tags=${image_tags}" >> "$GITHUB_OUTPUT" env: - IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} + IMAGE_REGISTRY: ${{ inputs.image_registry || vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} STEPS_GET_REPOSITORY_OUTPUTS_REPO: ${{ steps.get_repository.outputs.repo }} STEPS_GET_TAG_OUTPUTS_TAG: ${{ steps.get_tag.outputs.tag }} STEPS_GET_TAG_OUTPUTS_IS_SEMVER: ${{ steps.get_tag.outputs.is_semver }} diff --git a/.github/workflows/publish-worker.yml b/.github/workflows/publish-worker.yml index a080ee69c4b..f443e5dab1e 100644 --- a/.github/workflows/publish-worker.yml +++ b/.github/workflows/publish-worker.yml @@ -8,6 +8,11 @@ on: type: string required: false default: "" + image_registry: + description: The registry namespace to publish under (e.g. ghcr.io/) + type: string + required: false + default: "" secrets: DOCKERHUB_USERNAME: required: false @@ -83,10 +88,10 @@ jobs: docker tag infra_image "$REGISTRY/$REPOSITORY:$IMAGE_TAG" docker push "$REGISTRY/$REPOSITORY:$IMAGE_TAG" env: - # Defaults to ghcr.io/, so a fork publishes worker images to its - # own namespace automatically. Set the IMAGE_REGISTRY repository variable - # to publish under a different ghcr.io namespace instead. - REGISTRY: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} + # Resolved by the caller when invoked from publish.yml; falls back to the + # IMAGE_REGISTRY repository variable (or ghcr.io/) for the direct + # push triggers above, so a fork publishes to its own namespace. + REGISTRY: ${{ inputs.image_registry || vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} REPOSITORY: ${{ steps.get_repository.outputs.repo }} IMAGE_TAG: ${{ steps.get_tag.outputs.tag }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d1e5b5a706e..ba46b3db430 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -53,6 +53,22 @@ env: AWS_REGION: us-east-1 jobs: + # Resolve the target container registry namespace once and pass it down to every + # publish job. Defaults to ghcr.io/, so a fork publishes to its own + # namespace automatically; set the IMAGE_REGISTRY repository variable to override. + resolve-registry: + runs-on: ubuntu-latest + outputs: + registry: ${{ steps.resolve.outputs.registry }} + steps: + - name: 🧭 Resolve target registry + id: resolve + env: + IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY }} + DEFAULT_REGISTRY: ghcr.io/${{ github.repository_owner }} + run: | + echo "registry=${IMAGE_REGISTRY:-$DEFAULT_REGISTRY}" >> "$GITHUB_OUTPUT" + typecheck: uses: ./.github/workflows/typecheck.yml @@ -63,7 +79,7 @@ jobs: DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} publish-webapp: - needs: [typecheck] + needs: [typecheck, resolve-registry] permissions: contents: read packages: write @@ -74,9 +90,10 @@ jobs: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} with: image_tag: ${{ inputs.image_tag }} + image_registry: ${{ needs.resolve-registry.outputs.registry }} publish-worker: - needs: [typecheck] + needs: [typecheck, resolve-registry] permissions: contents: read packages: write @@ -86,9 +103,10 @@ jobs: DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} with: image_tag: ${{ inputs.image_tag }} + image_registry: ${{ needs.resolve-registry.outputs.registry }} publish-worker-v4: - needs: [typecheck] + needs: [typecheck, resolve-registry] permissions: contents: read packages: write @@ -96,6 +114,7 @@ jobs: uses: ./.github/workflows/publish-worker-v4.yml with: image_tag: ${{ inputs.image_tag }} + image_registry: ${{ needs.resolve-registry.outputs.registry }} # OS-level CVE scan of the image just published above. Report-only (writes to # the run summary); runs alongside the worker publishes and never blocks them. From beb539181bf5673827dcefd45f17bdc9f645b106 Mon Sep 17 00:00:00 2001 From: Daniel Sutton Date: Mon, 8 Jun 2026 16:37:09 +0100 Subject: [PATCH 4/6] ci: resolve registry inline instead of a dedicated job Drop the resolve-registry job to avoid its runner startup cost. GitHub doesn't expose the env context to a reusable workflow's with: block, so inline the resolution expression directly in each publish job's image_registry input instead. Behavior and upstream defaults unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/publish.yml | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ba46b3db430..71f41d3da67 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -53,22 +53,6 @@ env: AWS_REGION: us-east-1 jobs: - # Resolve the target container registry namespace once and pass it down to every - # publish job. Defaults to ghcr.io/, so a fork publishes to its own - # namespace automatically; set the IMAGE_REGISTRY repository variable to override. - resolve-registry: - runs-on: ubuntu-latest - outputs: - registry: ${{ steps.resolve.outputs.registry }} - steps: - - name: 🧭 Resolve target registry - id: resolve - env: - IMAGE_REGISTRY: ${{ vars.IMAGE_REGISTRY }} - DEFAULT_REGISTRY: ghcr.io/${{ github.repository_owner }} - run: | - echo "registry=${IMAGE_REGISTRY:-$DEFAULT_REGISTRY}" >> "$GITHUB_OUTPUT" - typecheck: uses: ./.github/workflows/typecheck.yml @@ -79,7 +63,7 @@ jobs: DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} publish-webapp: - needs: [typecheck, resolve-registry] + needs: [typecheck] permissions: contents: read packages: write @@ -90,10 +74,13 @@ jobs: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} with: image_tag: ${{ inputs.image_tag }} - image_registry: ${{ needs.resolve-registry.outputs.registry }} + # Target registry namespace, resolved once here and passed to every publish + # job. Defaults to ghcr.io/ so a fork publishes to its own namespace; + # set the IMAGE_REGISTRY repository variable to override. + image_registry: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} publish-worker: - needs: [typecheck, resolve-registry] + needs: [typecheck] permissions: contents: read packages: write @@ -103,10 +90,10 @@ jobs: DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} with: image_tag: ${{ inputs.image_tag }} - image_registry: ${{ needs.resolve-registry.outputs.registry }} + image_registry: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} publish-worker-v4: - needs: [typecheck, resolve-registry] + needs: [typecheck] permissions: contents: read packages: write @@ -114,7 +101,7 @@ jobs: uses: ./.github/workflows/publish-worker-v4.yml with: image_tag: ${{ inputs.image_tag }} - image_registry: ${{ needs.resolve-registry.outputs.registry }} + image_registry: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} # OS-level CVE scan of the image just published above. Report-only (writes to # the run summary); runs alongside the worker publishes and never blocks them. From c564e9d264d3ea0e1a634b889bd93c17fbbc3443 Mon Sep 17 00:00:00 2001 From: Daniel Sutton Date: Mon, 8 Jun 2026 16:42:15 +0100 Subject: [PATCH 5/6] ci: DRY the registry expression with a YAML anchor Define the registry-resolution expression once on publish-webapp via a YAML anchor (&image_registry) and reuse it in the worker jobs via aliases (*image_registry). GitHub Actions has supported YAML anchors since 2025-09-18, so this gives a single source of truth without the runner startup cost of a dedicated resolve job. Resolved value is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/publish.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 71f41d3da67..901c0c59e95 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -74,10 +74,10 @@ jobs: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} with: image_tag: ${{ inputs.image_tag }} - # Target registry namespace, resolved once here and passed to every publish - # job. Defaults to ghcr.io/ so a fork publishes to its own namespace; - # set the IMAGE_REGISTRY repository variable to override. - image_registry: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} + # Target registry namespace, defined once here (via a YAML anchor) and reused + # by every publish job. Defaults to ghcr.io/ so a fork publishes to its + # own namespace; set the IMAGE_REGISTRY repository variable to override. + image_registry: &image_registry ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} publish-worker: needs: [typecheck] @@ -90,7 +90,7 @@ jobs: DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} with: image_tag: ${{ inputs.image_tag }} - image_registry: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} + image_registry: *image_registry publish-worker-v4: needs: [typecheck] @@ -101,7 +101,7 @@ jobs: uses: ./.github/workflows/publish-worker-v4.yml with: image_tag: ${{ inputs.image_tag }} - image_registry: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} + image_registry: *image_registry # OS-level CVE scan of the image just published above. Report-only (writes to # the run summary); runs alongside the worker publishes and never blocks them. From f4f343457e993d90863f8fdb910df17079c43dd1 Mon Sep 17 00:00:00 2001 From: Daniel Sutton Date: Mon, 8 Jun 2026 16:55:29 +0100 Subject: [PATCH 6/6] ci: inline the registry expression in each publish job Drop the YAML anchor in favor of writing the registry-resolution expression explicitly in all three publish jobs. No job, no anchor, no runner startup; the expression is identical across the three. Resolved value unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/publish.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 901c0c59e95..8b5677a9231 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -74,10 +74,9 @@ jobs: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} with: image_tag: ${{ inputs.image_tag }} - # Target registry namespace, defined once here (via a YAML anchor) and reused - # by every publish job. Defaults to ghcr.io/ so a fork publishes to its - # own namespace; set the IMAGE_REGISTRY repository variable to override. - image_registry: &image_registry ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} + # Target registry namespace. Defaults to ghcr.io/ so a fork publishes + # to its own namespace; set the IMAGE_REGISTRY repository variable to override. + image_registry: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} publish-worker: needs: [typecheck] @@ -90,7 +89,7 @@ jobs: DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} with: image_tag: ${{ inputs.image_tag }} - image_registry: *image_registry + image_registry: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} publish-worker-v4: needs: [typecheck] @@ -101,7 +100,7 @@ jobs: uses: ./.github/workflows/publish-worker-v4.yml with: image_tag: ${{ inputs.image_tag }} - image_registry: *image_registry + image_registry: ${{ vars.IMAGE_REGISTRY || format('ghcr.io/{0}', github.repository_owner) }} # OS-level CVE scan of the image just published above. Report-only (writes to # the run summary); runs alongside the worker publishes and never blocks them.