Pin server images by digest and cache CI builds (Phase 0) - #340
Open
sibson wants to merge 2 commits into
Open
Conversation
Pins tests/servers/Dockerfile's debian:bookworm-slim base to a resolved sha256 digest so Tier 1 gold files stay reproducible, adds tests/servers/versions.md as the single table of every version pin (base image, distro server packages, LIBVNCSERVER_VERSION, UltraVNC's Chocolatey package, Tier 2 runner images), and switches the `servers` CI job to build via docker/setup-buildx-action + docker/bake-action with the GitHub Actions cache backend ahead of a build-less `docker compose up --wait`, so an unchanged Dockerfile hits cache instead of rebuilding on every run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VfqHjnFvPM6g1RspPk4uBo
sibson
force-pushed
the
claude/phase0-pin-server-images
branch
from
August 13, 2026 23:27
763757d to
bba7a8d
Compare
…ibility-plan.md The full explanation already lives in the plan doc; the inline comment only needs the pointer.
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.
What changed
This is PR 2 of the Phase 0 stack. It was branched from
claude/server-testing-plan-vl69ll(PR 1, #339); by the time this PR was opened, #339 had already merged tomainand GitHub deleted that branch, so this targetsmaindirectly — the diff is identical to what it would have been against the old base (git diff 34d61f3 68820ed— PR 1's branch tip vs.mainpost-merge — is empty).Covers the plan's "one source of version truth" and "stop paying the image build tax" follow-ups from
docs/server-compatibility-plan.md:Pin the Tier 1 base image by digest.
tests/servers/Dockerfile'sFROM debian:bookworm-slimnow pins@sha256:abd67ffcfa541b485a3dff59865ab629aa048a6c613e639d36e7456b0b229241, resolved live against Docker Hub's registry API (not invented — see verification below). It's the onlyFROMintests/servers/**; the two TigerVNC services and x11vnc all build from this one pinned base via multi-stage targets. Digest pinning matters for reproducible gold files: the plan's "Tier 1 gold files are deterministic" acceptance criterion depends on the fleet actually being byte-identical across runs, which a floatingbookworm-slimtag doesn't guarantee (Debian point releases move it).tests/servers/versions.md— the single source-of-version-truth table the plan calls for: base image digest, the distro packages each image installs (tigervnc-standalone-server/tigervnc-tools/x11vnc/xvfb/etc.),LIBVNCSERVER_VERSIONfromlibvncserver.mk, the UltraVNC Chocolatey package, and the Tier 2windows-latest/macos-latestrunner images. Each row says exactly where the pin lives and how to bump it, plus a documented recipe for resolving a fresh digest without a local Docker daemon (registry HTTP API v2 + a Docker Hub anonymous token) — useful in sandboxes wheredocker manifest inspectisn't available.Cache the
serversjob's image build. GitHub-hosted runners start every job with an empty Docker layer cache, soup -d --build --waitrebuilt from scratch every run (~35s of the ~70s total, per the Tier 1 spike notes). Landed the smallest change I could verify end-to-end:docker/setup-buildx-action+docker/bake-action(which reads build targets straight out ofdocker-compose.yml, so there's still exactly one image definition) withcache-from=type=gha/cache-to=type=gha,mode=max,load: true, followed by a build-lessdocker compose up -d --wait. I validated the bake target parsing and the--setcache-option syntax locally against a real (temporarily-started) Docker daemon (docker buildx bake -f tests/servers/docker-compose.yml --set '*.cache-from=type=gha' --set '*.cache-to=type=gha,mode=max' --print) and confirmed it produces the expected three-target bake plan with cache options applied to all of them — I did not have GitHub's Actions cache backend available locally to prove an actual cache hit, but the mechanics (compose→bake target resolution, cache flag plumbing) are confirmed correct.docs/server-compatibility-plan.md— added a factual note under Tier 1 follow-ups recording that digest pinning and build caching are done, and pointing attests/servers/versions.md. No restructuring.Verification
flake8 --count --statistics vncdotool tests— clean (0).make test(python -m unittest discover tests/unit) — 67 tests pass in a clean venv built fromrequirements-dev.txt. (The sandbox's system Python had a stalecryptography/rust-bindings panic unrelated to this change; a fresh venv confirms it's an environment artifact, not a regression.).github/workflows/*.ymlconfirmed viayaml.safe_load.auth.docker.iotoken +registry-1.docker.iomanifest HEAD) and got backdocker-content-digest: sha256:abd67ffcfa541b485a3dff59865ab629aa048a6c613e639d36e7456b0b229241forlibrary/debian:bookworm-slim.docker compose -f tests/servers/docker-compose.yml build. The pinned digest resolved correctly andFROMsucceeded (buildx confirmed the manifest and began pulling layers); the build then failed pulling an image blob fromproduction.cloudfront.docker.com, which this sandbox's egress policy doesn't allow (only the registry API host is reachable, not the CDN that serves blob bytes). That's a sandbox network-policy limitation, not a problem with the digest or the Dockerfile — reported here rather than worked around, per the task instructions. A normal CI runner or a developer machine with ordinary Docker Hub access will pull the pinned digest fine.Scope note
Per instructions,
tests/functional/**is untouched — that's the scenarios-framework PR later in this stack.Generated by Claude Code