Skip to content

ci(base-image): push prebuilt multi-arch openlock-base to ghcr (bd openlock-awo)#48

Merged
vessux merged 1 commit into
mainfrom
feat/base-image-ghcr-push
May 29, 2026
Merged

ci(base-image): push prebuilt multi-arch openlock-base to ghcr (bd openlock-awo)#48
vessux merged 1 commit into
mainfrom
feat/base-image-ghcr-push

Conversation

@vessux
Copy link
Copy Markdown
Owner

@vessux vessux commented May 29, 2026

What

Adds the CI workflow that builds the multi-arch (amd64+arm64) openlock-base image and pushes it to ghcr.io/vessux/openlock-base:<hash> — completing bd openlock-awo (prebuilt core images via registry-pull).

Why this is small

The host side already shipped with the 8op slim restructure (#47):

  • src/sandbox/ensure-base.ts already does imageExists → tryPull → build against the GHCR tag.
  • base.Containerfile's header already documents "CI computes the same hash and pushes to that exact tag."
  • 8op also added the openlock --print-base-tag CLI flag (with a test) specifically so CI can compute the matching tag.

The only missing piece was the push. This PR is one YAML file.

How the tag stays in sync (the one correctness constraint)

CI computes the tag via the exact same code path as the hostbun run src/cli.ts --print-base-tagsha256(base.Containerfile)[0..12] — rather than re-hashing the file in bash, so it's immune to any Bun text-import byte normalization drift. Locally this prints ghcr.io/vessux/openlock-base:c00459a7735d.

Design decisions (confirmed with maintainer)

  • Trigger: release tags only (v*.*.*) + manual dispatch. A released binary embeds a frozen base.Containerfile, so building on the tag guarantees that release's base hash exists. Separate workflow (not folded into release.yml) to scope packages: write and isolate failure — a slow base build never blocks the binary release.
  • Multi-arch: QEMU single job. setup-qemu-action + buildx --platform linux/amd64,linux/arm64 --push. The arm64 leg is emulated (~10-15 min) but runs only on the rare release where base.Containerfile changed — an idempotency check (buildx imagetools inspect) skips the build entirely when the tag is already in ghcr.
  • provenance: false — matches the fork-binary trust model (no attestation) and keeps the pushed manifest a clean per-arch index that podman resolves reliably.

Local build remains first-class for offline/air-gapped users — this is a cold-start perf win, not a hard dependency.

⚠️ One-time manual step after first successful push

The first push creates a private ghcr package. Flip ghcr.io/vessux/openlock-base to public (GitHub → Packages → Package settings) so end users' unauthenticated podman pull works.

Verification

  • bun run src/cli.ts --print-base-tag → valid ghcr ref ✅
  • bun test src/cli/print-base-tag.test.ts → 1 pass ✅
  • YAML parses (js-yaml); 9 steps, triggers [push, workflow_dispatch], perms contents:read packages:write
  • Full suite: 587 pass / 0 fail; typecheck + knip clean; lint warning is pre-existing on main ✅
  • Real end-to-end verification happens on the next release tag push (CI cannot be exercised pre-merge).

…enlock-awo)

Adds the CI half of registry-pull for the base sandbox image. The host
side (ensure-base.ts: imageExists -> tryPull -> build) and the
`openlock --print-base-tag` affordance already shipped with the 8op slim
restructure; this is the missing push.

On a v*.*.* release tag (or manual dispatch) the workflow computes the
base tag via the SAME code path as the host (`openlock --print-base-tag`
-> sha256(base.Containerfile)[0..12]), skips if the tag already exists in
ghcr, then builds amd64+arm64 via buildx+QEMU and pushes the multi-arch
manifest to ghcr.io/vessux/openlock-base:<hash>. provenance disabled to
match the fork-binary trust model and keep podman arch-selection clean.

A fresh install then pulls the base instead of running the slow
apt/node/uv build; local build stays the offline/air-gapped fallback.
@vessux vessux merged commit f53cb14 into main May 29, 2026
5 checks passed
@vessux vessux deleted the feat/base-image-ghcr-push branch May 29, 2026 14:13
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