feat(ci): publish release images to ECR with OCI provenance - #32
Merged
Conversation
Every push to main now also publishes the image to an immutable ECR repository, tagged sha-<commit> plus a source-ordered r<position>-<sha6> alias, with index-level OCI annotations (revision, source, commit author, committer, subject and timestamp). Delivery tooling discovers releases from those annotations instead of a floating tag. The GHCR publication is unchanged and stays the public distribution channel. The release job runs only on pushes to main and assumes its registry role through OIDC, so pull requests and tag builds never touch the release registry.
The release job no longer rebuilds the image. It copies the index the build job pushed to GHCR into the release repository by digest, adding the index-level OCI annotations during the copy, so the released artifact is always a CI build of the commit and never a divergent rebuild from mutable external inputs. Both registry writes are skip-if-present with digest read-back, so a rerun after a partial publish repairs the missing tag instead of failing on the immutable repository. A reused sha tag whose contents predate this run's build is kept and reported as a warning.
Z3r0Sum
marked this pull request as ready for review
September 1, 2026 14:44
webjunkie
approved these changes
Sep 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Every push to
mainnow also publishes the container image to an immutable ECR repository with the OCI provenance that PostHog's delivery tooling discovers releases from, so deployments can follow per-commit image identities instead of the floatinglatesttag. The GHCR publication is untouched and remains the public distribution channel.Held: do not merge until the release repository and its OIDC publish role exist and the
AWS_ECR_PUBLISH_IAM_ROLErepository variable is set; until then the new job fails on the first push tomain.Changes
releasejob promotes the image thebuildjob pushed to GHCR into ECR by digest, so the released artifact is always the build CI exercised, never a second build from mutable external inputs.docker buildx imagetools createcopies the platform manifests, layers and buildkit attestation manifests across registries (the Docker docs sentence that sources must live in the target registry is stale; buildx copies with referrers) and adds the index-level annotations during the copy. This depends on thephlowerGHCR package staying public: the copy pulls it anonymously.sha-<commit>plus a source-orderedr<first-parent position>-<sha6>alias. Each write is skip-if-present with digest read-back, so a rerun after a partial publish repairs the missing tag instead of failing on the immutable repository. If thebuildjob itself reran and produced a fresh GHCR digest, the earlier ECR copy of that commit is deliberately kept and a warning is emitted.org.opencontainers.image.*set (revision, source, and so on) plus commit author, committer, subject (capped at 160 characters) and UTC committer timestamp. These annotation keys are a contract shared with other PostHog services; do not rename them.id-token: writelives only on the release job, which never runs on pull requests or tag builds) and the AWS account id is masked in logs; the registry hostname comes from the ECR login step rather than the workflow source.buildjob (GHCR,latest, semver and short-sha tags) is unchanged apart from exposing its image digest as a job output.Rollback