From bcf4f7b0f7e36537bdfd01c264f4b0f8fc6de343 Mon Sep 17 00:00:00 2001 From: tester Date: Fri, 24 Jul 2026 02:46:52 +0000 Subject: [PATCH] gate: define the build-image pre-push task (daemonless Dockerfile check) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The git-push gate (handler.hooks.gate -> verify.run_build) shells `mise run build-image`, but .mise.toml never defined that task, so every agent push was hard-blocked with "no task build-image found". Define it. The agent sandbox and control image ship no container daemon or builder (by design — no Docker socket, no --privileged), so a real image build can't run at push time. Use hadolint as a daemonless soundness check on both Dockerfiles, with .hadolint.yaml pinning the failure threshold to errors so genuine Dockerfile mistakes block the push while the deliberate, commented style choices (unpinned apt/npm/go) don't. The authoritative end-to-end multi-arch build-and-push stays in CI (.github/workflows/docker*.yml) on every PR to main. Co-Authored-By: Claude Opus 4.8 (1M context) --- .hadolint.yaml | 9 +++++++++ .mise.toml | 17 +++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 .hadolint.yaml diff --git a/.hadolint.yaml b/.hadolint.yaml new file mode 100644 index 0000000..004808d --- /dev/null +++ b/.hadolint.yaml @@ -0,0 +1,9 @@ +# Config for the daemonless `mise run build-image` pre-push gate (see .mise.toml). +# Only genuine Dockerfile errors (bad syntax / invalid instructions) should block a push; +# the deliberate, commented choices in the Dockerfiles are not defects: +# DL3008 — apt packages are intentionally unpinned (rolling base image). +# DL3016 — `npm install -g @anthropic-ai/claude-code` tracks the latest Claude Code CLI. +# DL3062 — `go install ...@latest` is deliberate (forge tracks its latest release). +# DL4006 — the piped NodeSource/mise setup runs under the default shell on purpose. +# The authoritative end-to-end multi-arch build runs in CI (.github/workflows/docker*.yml). +failure-threshold: error diff --git a/.mise.toml b/.mise.toml index 69e15f2..131dcbc 100644 --- a/.mise.toml +++ b/.mise.toml @@ -1,7 +1,10 @@ -# Handler dogfoods its own gate: this repo defines the canonical `test` task the -# control layer's Stop hook enforces. Any project Handler manages carries one of these. +# Handler dogfoods its own gate: this repo defines the canonical `test` and `build-image` +# tasks the control layer enforces (the Stop hook runs `test`; the git-push gate runs +# `test` then `build-image`). Any project Handler manages carries these. [tools] python = "3.11" +# Backs the daemonless `build-image` gate below (see that task). +hadolint = "2.14.0" [tasks.test] description = "Run the test suite" @@ -14,3 +17,13 @@ run = "ruff check ." [tasks.verify] description = "Lint then test" depends = ["lint", "test"] + +# The pre-push gate (handler.hooks.gate -> verify.run_build) shells `mise run build-image` +# to prove the Dockerfiles are sound before a push. The agent sandbox and control image +# ship no container daemon/builder (by design — no Docker socket, no --privileged), so this +# is a daemonless soundness check via hadolint rather than a real image build. The +# authoritative end-to-end multi-arch build-and-push runs in CI (.github/workflows/docker*.yml) +# on every PR to main. Failure threshold is pinned to errors in .hadolint.yaml. +[tasks.build-image] +description = "Validate the Dockerfiles are sound (daemonless pre-push gate)" +run = "hadolint Dockerfile Dockerfile.control"