Skip to content

ci: auto-mirror template image updates to registries#5739

Merged
avallete merged 6 commits into
developfrom
claude/dependabot-ci-merge-issue-qpog0k
Jun 30, 2026
Merged

ci: auto-mirror template image updates to registries#5739
avallete merged 6 commits into
developfrom
claude/dependabot-ci-merge-issue-qpog0k

Conversation

@avallete

@avallete avallete commented Jun 30, 2026

Copy link
Copy Markdown
Member

Automatically backfills the image mirror when the CLI template Dockerfile changes, so a dependabot image bump no longer leaves develop (and PRs rebased on it) failing the ghcr.io-pinned Start check with manifest unknown.

Background

The Start job in cli-go-ci.yml pins SUPABASE_INTERNAL_IMAGE_REGISTRY=ghcr.io, so it only goes green once a bumped tag exists on the mirror. Dependabot bumps the Dockerfile before the new tag is mirrored, and the mirror previously only ran via manual workflow_dispatch — so the bump merged red and every subsequent PR touching apps/cli-go/** inherited the same failure until someone mirrored by hand. This was the catch-22 already noted in cli-go-mirror.yml.

Changes

  • New workflow mirror-template-images.yml — runs on push to develop when apps/cli-go/pkg/config/templates/Dockerfile changes (plus workflow_dispatch). It detects any image tag missing from the mirror and backfills it by reusing the existing cli-go-mirror-image.yml reusable workflow. It runs on push rather than the PR on purpose: mirroring needs the AWS role + packages:write, which a dependabot-triggered pull_request run cannot be granted, and this avoids pull_request_target. The backfill runs as soon as the bump lands on develop, repopulating the mirror so develop and rebased PRs pass Start.

  • New script apps/cli/scripts/detect-unmirrored-images.ts — parses the template Dockerfile, checks each image against the mirror with docker buildx imagetools inspect, and writes the missing tags as JSON to $GITHUB_OUTPUT for the workflow matrix. The detection helpers (mirrorImageTarget, mirrorImageTargets, partitionUnmirroredImages) are exported and unit-tested; the executable entry is guarded by import.meta.main.

    • Checks every image, not just third-party ones, and an image counts as mirrored only when present on all mirror registries (public.ecr.aws and ghcr.io) — a tag on one but missing from the other is re-pushed. Anonymous imagetools inspect works for public ECR, so the detect job needs no AWS credentials.
    • Idempotent: once an image is on every registry it is skipped, so a re-run is a no-op.
  • detect-unmirrored-images.unit.test.ts — covers target derivation, the both-registries rule, de-duplication, and the idempotent re-run.

  • cli-go-mirror.yml — clarified that it is now the manual/bulk entry point; template bumps are mirrored automatically by the new workflow.

https://claude.ai/code/session_01DEeGQ3JAwQD1PGEENE13dc

claude added 5 commits June 30, 2026 11:38
The Start check pinned SUPABASE_INTERNAL_IMAGE_REGISTRY=ghcr.io, so a
dependabot image bump failed with "manifest unknown" until the new tag
was manually mirrored to ghcr.io — yet the PR still merged (Start is not
a required check), breaking Start on develop for every subsequent PR.

Two changes:

- Drop the ghcr.io override in the Start job so `start` uses the default
  registry fallback (public.ecr.aws -> ghcr.io -> upstream Docker Hub).
  A freshly bumped tag exists upstream immediately, so Start stays green
  while the mirror catches up.

- Add mirror-template-images.yml: whenever the templates Dockerfile
  changes, detect any tag missing from the ghcr.io mirror and backfill it
  via the existing cli-go-mirror-image reusable workflow. Runs on
  pull_request_target (guarded to same-repo branches) so it works on
  dependabot PRs, parses the Dockerfile statically without executing
  checked-out code, and only mirrors missing tags.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DEeGQ3JAwQD1PGEENE13dc
…_target

Avoid pull_request_target (privileged token + cloud creds exposed to PR
context). Dependabot pull_request runs can't be granted the AWS role /
packages:write needed to mirror anyway, and Start no longer needs the
mirror to be done before merge (it falls back to the upstream image), so
the backfill runs post-merge on push to develop — a trusted context —
and develop self-heals within a minute.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DEeGQ3JAwQD1PGEENE13dc
Revert the cli-go-ci.yml change so the Start job keeps validating against
ghcr.io. The post-merge mirror-template-images workflow repopulates
ghcr.io/ECR as soon as a bump lands on develop, so develop and PRs rebased
on it stop inheriting the manifest-unknown failure. Update the related
comments to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DEeGQ3JAwQD1PGEENE13dc
Replace the inline bash in mirror-template-images.yml with a Bun script
backed by a unit-tested module:

- src/shared/services/mirror-images.ts — mirrorImageTarget (mirrors Go's
  utils.GetRegistryImageUrl) and partitionUnmirroredImages, the idempotent
  core that splits images by mirror presence. Reuses the existing
  parseDockerfileServiceImages parser.
- scripts/detect-unmirrored-images.ts — thin CI entry that runs the docker
  inspect check and writes missing=<json> to GITHUB_OUTPUT.

Check every image, not just third-party ones: any image already on the
mirror is skipped, so a supabase/* image that is somehow absent is still
backfilled and a re-run is a no-op.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DEeGQ3JAwQD1PGEENE13dc
An image counts as mirrored only when present on ALL mirror registries
(public.ecr.aws and ghcr.io), not just one. The mirror pushes to both at
once, so a tag present on one but missing from the other is a partial
mirror that must be re-pushed. partitionUnmirroredImages now checks every
(image, registry) pair via mirrorImageTargets and flags an image as
missing if any registry lacks it. Anonymous imagetools inspect works for
public ECR, so the detect job needs no AWS credentials.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DEeGQ3JAwQD1PGEENE13dc
@avallete avallete requested a review from a team as a code owner June 30, 2026 14:03
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase/cli/supabase@70aa7ed62ce45347d1fedf16853da8afb95487ef

Preview package for commit 70aa7ed.

The mirror helpers were used only by the detect script and its test, so
keep them in scripts/detect-unmirrored-images.ts instead of a separate
src module. The executable entry is guarded by import.meta.main so the
exported helpers can be imported by the unit test without side effects.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DEeGQ3JAwQD1PGEENE13dc

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cc78a1da42

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/mirror-template-images.yml
@avallete avallete enabled auto-merge June 30, 2026 14:21
@avallete avallete added this pull request to the merge queue Jun 30, 2026
Merged via the queue into develop with commit 25a9aae Jun 30, 2026
40 of 41 checks passed
@avallete avallete deleted the claude/dependabot-ci-merge-issue-qpog0k branch June 30, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants