Skip to content

ci(preview): build + push :pr-<N>-<sha> GHCR image on every PR#211

Merged
mastermanas805 merged 1 commit into
masterfrom
feat/preview-env-pr-image-retag
May 30, 2026
Merged

ci(preview): build + push :pr-<N>-<sha> GHCR image on every PR#211
mastermanas805 merged 1 commit into
masterfrom
feat/preview-env-pr-image-retag

Conversation

@mastermanas805

Copy link
Copy Markdown
Member

Summary

Phase 1b companion to InstaNode-dev/infra#45. The infra repo's preview-create workflow pulls ghcr.io/instanode-dev/instant-api:pr-<N>-<sha> when it provisions a per-PR namespace; this workflow is what produces that tag.

  • Fires on pull_request open/sync/reopen (paths-ignore mirrors deploy.yml).
  • Mirrors deploy.yml's sibling-checkout (common/ + proto/ via REPO_ACCESS_TOKEN), same Dockerfile, same buildx invocation, same GHCR_PUSH_TOKEN PAT auth.
  • Tags only :pr-<N>-<sha>. Never touches :latest or :master-* — prod tag namespace stays reserved.
  • Skips the test gate — ci.yml already runs tests on PRs. This is purely "package the binary so a preview env can pull it".

Soft-fail surface

If GHCR_PUSH_TOKEN is unset on api repo: workflow soft-warns + exits 0. The infra preview-create then soft-fails downstream on its 240s rollout timeout (image never appears in GHCR → ImagePullBackOff → neutral check).

Security

  • Every github.event.pull_request.* value assigned to env: and shape-validated (numeric PR 1-99999, hex SHA 7-40 chars) before any shell use, matching preview-dispatch.yml's posture from ci(preview): dispatch preview-env create/teardown to infra on PR events #210.
  • ref: \${{ github.event.pull_request.head.sha }} in checkout is an immutable SHA, not a ref name — can't be injection-abused.

Coverage block (rule 17)

Symptom:        infra preview-create wants :pr-<N>-<sha> tag, no
                workflow produces it.
Enumeration:    rg -F ':pr-' .github/workflows/
Sites found:    0 (no workflow currently tags pr-*)
Sites touched:  1 (new preview-image-build.yml)
Coverage test:  yamllint + python yaml.safe_load_all pass on the new
                workflow. Manual: build pattern is a 1:1 clone of
                deploy.yml's image-build step, only the tag pattern +
                trigger differ — diff-review shows no other deviation.
Live verified:  N/A until merged + a PR triggers it; image presence
                will be visible at
                https://github.com/InstaNode-dev/instant-api/pkgs/container/instant-api
                under the :pr-* tag list.

Test plan

  • yamllint clean
  • CI validate (golangci-lint / typos / etc.) unaffected — workflow file only
  • On merge: a follow-up PR's preview-image-build job pushes ghcr.io/instanode-dev/instant-api:pr-<N>-<sha> to GHCR
  • infra preview-create (once operator-activated) can pull that image and roll out the api Deployment

🤖 Generated with Claude Code

Phase 1b companion to infra PR (Layer-3 ephemeral preview envs). The
infra repo's preview-create workflow pulls
`ghcr.io/instanode-dev/instant-api:pr-<N>-<sha>` when it provisions
the per-PR namespace; this workflow is what produces that tag.

Why a sibling workflow rather than a tag-add on deploy.yml: deploy.yml
fires on push to master only. PR builds need a parallel pipeline. The
test gate stays on ci.yml (already runs on PRs); this workflow is purely
"package the binary so a preview env can pull it" — no duplicated test
load.

Posture
- Same sibling-checkout pattern as deploy.yml (common/ + proto/ via
  REPO_ACCESS_TOKEN, same Dockerfile, same buildx invocation).
- Same GHCR_PUSH_TOKEN PAT auth (per-job GITHUB_TOKEN cannot push to
  the org-owned package, per deploy.yml's documented constraint).
- Tags only :pr-<N>-<sha>. Never touches :latest or :master-* — the
  prod tag namespace stays reserved for deploy.yml + pin-prod-images.
- Soft-fails (warn-only) if GHCR_PUSH_TOKEN is unset. The infra
  preview-create soft-fails downstream on rollout timeout in that case.
- paths-ignore matches deploy.yml (no preview image for docs-only PRs).
- Concurrency cancel-in-progress: rapid push pattern doesn't double-build.

Security
- Every github.event.pull_request.* value assigned to env: and
  shape-validated (numeric PR, hex SHA) before shell use, matching
  preview-dispatch.yml's posture.
- `ref:` uses head.sha (an immutable SHA, not a ref name) — can't be
  injection-abused.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 merged commit db10a0e into master May 30, 2026
18 checks passed
@mastermanas805 mastermanas805 deleted the feat/preview-env-pr-image-retag branch May 30, 2026 20:49
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.

1 participant