Skip to content

image(zig): add a master variant tracking Zig's master branch - #389

Draft
nozaq wants to merge 21 commits into
mainfrom
claude/nightly-image-variants-nnsgck
Draft

image(zig): add a master variant tracking Zig's master branch#389
nozaq wants to merge 21 commits into
mainfrom
claude/nightly-image-variants-nnsgck

Conversation

@nozaq

@nozaq nozaq commented Sep 1, 2026

Copy link
Copy Markdown
Member

Publishes zig:master / zig:master-trixie, built from Zig's master branch, and adds the weekly job that keeps the pinned build current.

Zig is the one image here whose users have a real reason to follow an unreleased toolchain: it is pre-1.0, breaking language changes land on master, and tagged releases are months apart.

What changes

File Change
zig/build.yaml One new variant, master-trixie, tagged master-trixie and master
zig/Dockerfile Master builds are fetched from ziglang.org/builds; releases keep the mirror-first path unchanged
scripts/update-zig-master.sh New. Resolves the published master build and its matching ZLS build, writes both into build.yaml
.github/workflows/update-zig-master.yml New. Runs the script weekly and opens a pull request when the pin moves
README.md, zig/README.md, AGENTS.md Docs; the tag table was regenerated with update-readme.sh

Everything else — build-config.sh, publish-image.yml, release.yml, build-checks.yml, trivy.yml, attest-check.yml, changed-images.sh, .devcontainer/sandbox-zig — is untouched. The variant declares the same build args as the existing ones, so it flows through the matrix, tag, scan and attestation machinery exactly like a release variant.

Trust model

Unchanged. Upstream signs master builds with the same minisign keys the release variants already verify against, and the existing trusted-comment check (which asserts the signature names the requested file) applies as-is. This was verified against the committed keys before writing the code: both the master Zig tarball and the ZLS build the API pairs with it carry a valid .minisig under zig/zig-minisign.pub and zig/zls-minisign.pub.

Only the download source differs: the community mirrors carry tagged releases only, so a master build comes from ziglang.org/builds directly, and the mirror list is skipped for it.

Why a weekly pin instead of a nightly build

Renovate cannot track this variant: master builds carry no tag, and the ZLS build compatible with a given master is served by the zigtools release worker API rather than published as a release. The alternative to resolving versions at build time is resolving them into a reviewed commit, which is what this does — so the published master build stays auditable from git, from the provenance attestation's build args, and from the dated tag, with no new record-keeping.

It also makes the bump pull request the gate: build-checks.yml builds the resolved master on both architectures before it can be merged, so a broken upstream master fails a pull request instead of a nightly release, and zig:master stays on the last build that worked.

The freshness cost is small, because upstream is the bottleneck. Measured on 2026-09-01: master takes ~10 commits/day, but the build published as master was 23 commits behind HEAD and signed ~41 hours after the commit it was built from, so upstream publishes roughly once a day and lags a day or two. ZLS lags further — the build the API pairs with today's master was produced three months earlier.

A weekly bump also costs nothing extra downstream: release.yml already guarantees a rebuild every Monday, so the image(zig): commit does not add release runs.

Verification

  • shellcheck over every *.sh, hadolint on zig/Dockerfile, actionlint on the new workflow (only the pre-existing ubuntu-slim label warning, which every workflow here produces).
  • update-zig-master.sh run end to end against the live endpoints: resolves the current master, reports unchanged when the pin already matches, and restores the file byte-for-byte from a deliberately stale pin — comments and blank lines intact.
  • The sandbox build-arg check from build-checks.yml replicated locally: passes for the new variant.
  • The Dockerfile's source selection simulated for both a master and a release version: the master path resolves tarball and signature from ziglang.org/builds, the release path still falls back to ziglang.org/download/<version> when a mirror is unreachable.

The image itself was not built locally (no Docker daemon in this environment); the build checks on this pull request cover it.


Generated by Claude Code

Zig is pre-1.0 and its master branch is where breaking language changes
land, so a dev container that follows master is worth publishing. Upstream
signs master builds with the same minisign key the release variants already
verify against, so the trust model is unchanged: only the source of the
tarball differs, since the community mirrors carry tagged releases only.

Renovate cannot keep the variant current — master builds carry no tag, and
the ZLS build that matches one is served by an API rather than published as
a release — so update-zig-master.sh resolves both versions and a weekly
workflow proposes them as a pull request. The pin therefore lands as a
reviewed commit like every other version here, and build-checks.yml builds
the resolved master before it can reach the registry: a master that fails
the checks stays unmerged, leaving zig:master on the last build that worked.

Only trixie is built, and the tags carry none of the stability promises the
release tags do; both are documented in the image README.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each script already documents itself in its header comment, so the list
here only had to be kept in sync with them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The per-file listing had to be kept in sync with the tree it described, and
the files it named document themselves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each script documents itself in its header comment, so that listing was
the one that only added a second place to keep in sync.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The shared script now on main covers this workflow too. The branch becomes
the fixed housekeeper/update-zig-master rather than one named after the
version, since the script restarts a branch whose pull request is gone, and
the version moves to the pull request body: the branch is reused, so an open
pull request picks up a newer build as another commit and a title naming one
version would go stale.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@nozaq
nozaq force-pushed the claude/nightly-image-variants-nnsgck branch from ea495eb to db37228 Compare September 2, 2026 09:40
nozaq and others added 7 commits September 2, 2026 21:40
The reason Renovate cannot track these versions belongs to
update-zig-master.sh, which the header now points at.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
update-zig-master.yml explained its own slot in a comment, which said
nothing about the slots it was avoiding. The table names all six, so the
next scheduled workflow can be placed by reading one list, and the header
comment goes with it: what the workflow does is its name and the script it
calls, and the pull request as the gate is now stated once for every
automation that moves a version.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The mirrors serve master builds, not just releases, so skipping them left a
master build on one host with wget -t 1: a single timeout from ziglang.org
during the no-cache release build would fail the publish, and every build
spent ziglang.org's bandwidth, which is what the mirror list exists to
avoid. Only the canonical fallback differs per channel now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The publish jobs are independent, but the matrix defaulted to fail-fast, so
a variant that cannot be built cancelled every sibling publish in flight and
create-tag never ran. The zig master variant makes that reachable: it is
rebuilt from scratch every release, from an upstream that can prune the
build or regress, and taking the day's release for every other image with it
is not a cost that variant is worth.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both sibling housekeeper workflows run on changes to themselves and to the
script they call; this one only ran on its cron, so an edit to the yq
queries, the awk rewrite or the heredoc would first be exercised by a
scheduled run. The steps that write anything stay skipped on pull requests,
as in trivyignore-cleanup.yml, leaving the resolution itself as what the
check covers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The script skips creation when a pull request is already open on the
branch, but kept committing onto it, so a pull request left open through a
second run described the commits it opened with rather than the ones it
carries. The zig master pull request makes that concrete — its body tabulates
the versions in the diff — but the file list update-material.yml puts in its
body drifts the same way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The master builds are on the mirrors like any release, so the download path
is the one already described.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

2 participants