Skip to content

ci: merge devcontainer-check into build-checks#227

Merged
nozaq merged 3 commits into
mainfrom
claude/devcontainer-build-check-merge-e39gji
Jul 25, 2026
Merged

ci: merge devcontainer-check into build-checks#227
nozaq merged 3 commits into
mainfrom
claude/devcontainer-build-check-merge-e39gji

Conversation

@nozaq

@nozaq nozaq commented Jul 25, 2026

Copy link
Copy Markdown
Member

Folds devcontainer-check.yml into build-checks.yml, and builds each sandbox dev container from the job that already builds its image instead of from scratch.

Motivation

Since #214 moved the Dev Container Feature tests into build-checks.yml and decolint into lint.yml, and #224 narrowed build-checks.yml to the changed images, devcontainer-check.yml was left building every sandbox on every */Dockerfile or */smoke-test.sh change, with no change detection of its own, and rebuilding each image a second time from scratch on its own runner.

A change under node/ now builds one sandbox instead of ten, as a step in a job that has already built that image.

Changes

  • Build the sandbox dev container in check-base and check-image rather than in a separate job, on both architectures as with the Feature tests next to it. Read build args exports the arguments the build step used, so the Dev Container CLI resolves the same Dockerfile, context and arguments and reuses those layers. Context matches because the CLI defaults build.context to the Dockerfile's parent directory (getDockerContextPath returns parentURI(getDockerfilePath(...))), which is what docker/build-push-action is given.
  • Read the sandbox build args from the environment through ${localEnv:...}, with no defaults, matching feature-debian. That drops the pinned copy of every build arg from the sandbox configurations, leaving build.yaml as their only source, and with it the Renovate rules that kept the two in sync.
  • Stop repeating the smoke tests in the sandbox step. With identical arguments the image is the one the previous step already smoke-tested, so the step asserts only what the configuration adds on top of it: that the CLI applies remoteUser.
  • Delete devcontainer-check.yml. Its path filters (*/Dockerfile, */smoke-test.sh) were already covered by build-checks.yml; .devcontainer/sandbox-** is added there.
  • Stop ignoring .devcontainer/sandbox- in changed-images.sh, and map each sandbox directory to its image the same way the Feature configurations are already mapped.
  • Add a Verify sandbox configurations step to setup: every image must have a sandbox, and each sandbox must declare exactly the build args of its image. Neither is tied to a changed image, and a mismatch would leave an argument resolving to the empty string rather than fail outright.
  • Document in AGENTS.md how to export the arguments when opening a sandbox by hand.

Trade-off

Opening a sandbox now requires exporting the build args first; without them the build fails on an empty argument. This is the feature-debian trade-off applied to the sandboxes: a missing value fails rather than silently selecting a different version. Defaults were considered and rejected — the CLI splits the substitution on every colon (variable.split(':') in evaluateSingleVariable, default taken from args[1]), so a Debian digest default would be truncated to trixie-20260725@sha256, and keeping pinned values would also require reworking the devcontainer.json patterns in renovate.jsonc.

Verification

No Docker daemon was available, so the sandbox steps need a CI run to confirm. The thing to watch on the first run is whether the Dev Container CLI build actually hits the buildx cache from the build step. If it does not, those jobs get slower rather than faster, since the work is now serial within a job instead of parallel across jobs.

Checked locally:

  • changed-images.sh selection for a sandbox-only change, .md exclusion, debian/smoke-test.sh (cross-image), a Feature configuration change, and the repository-wide catch-all.
  • The Verify sandbox configurations guard, on the current tree and on three seeded failures: an orphan sandbox directory, a sandbox missing an argument, and a build arg removed from build.yaml. All three exit non-zero with a diff naming the file.
  • Every image uses the same build_args keys across all of its variants, so one sandbox configuration covers each image's whole matrix.
  • build-checks.yml YAML parse and step order; renovate.jsonc and all ten sandbox configurations parse; bash -n on changed-images.sh.

base_matrix and matrix generation could not be reproduced locally because the available yq is the Python implementation, but that code path is unchanged.

claude added 3 commits July 25, 2026 11:54
The sandbox dev containers were built by their own workflow, which rebuilt
all of them whenever any Dockerfile or smoke test changed. Move that job
into build-checks.yml so it is driven by the same change detection as the
image builds: a change under node/ now builds only the node sandbox.

changed-images.sh no longer ignores .devcontainer/sandbox-, and maps each
sandbox directory to its image the same way it already maps the Feature
configurations. A setup step asserts the sandbox directories and the image
list still match, since the matrix is derived from the image list and would
otherwise skip a sandbox that belongs to no image.

The sandbox jobs keep building through the Dev Container CLI rather than
reusing the images the other jobs load locally. Reusing them requires the
same build args, and the only channel for those is ${localEnv:...} in the
sandbox configurations, which cannot carry the pinned Debian digest: the
CLI splits the default value on every colon, so the digest would be
truncated. Wrapping the values would also break the devcontainer.json
patterns in renovate.jsonc.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01US45nXX1mwPpp6SKM9jMea
Replaces the standalone check-sandbox job, which rebuilt each image a second
time from scratch on its own runner, with a step in the jobs that already
build those images.

The sandbox configurations now read their build args from the environment
through ${localEnv:...}. check-base and check-image export the arguments
they just built with, so the Dev Container CLI resolves the same Dockerfile,
context and arguments and reuses the layers the build step produced. The
smoke tests are no longer repeated there: the image is the one the previous
step already tested, so the step asserts only what the configuration adds on
top of it, that the CLI applies remoteUser.

No default is given for any argument, matching feature-debian: a missing
value fails the build instead of silently selecting a different version.
This removes the pinned copy of every build arg from the sandbox
configurations, leaving build.yaml as their only source, and with it the
Renovate rules that kept the two in sync.

The setup guard now also checks that each sandbox declares exactly the build
args of its image, since a mismatch would leave an argument empty rather
than fail outright. AGENTS.md documents how to export the arguments when
opening a sandbox by hand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01US45nXX1mwPpp6SKM9jMea
The step reuses the layers the build step in the same job produced, so it
costs about the same on either runner. Dropping the amd64 restriction also
matches the Dev Container Feature tests next to it, which have always run on
both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01US45nXX1mwPpp6SKM9jMea
@nozaq
nozaq merged commit b4a158b into main Jul 25, 2026
104 of 109 checks passed
@nozaq
nozaq deleted the claude/devcontainer-build-check-merge-e39gji branch July 25, 2026 13:06
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