All checks were successful
check / check (push) Successful in 1m9s
Add a root Dockerfile.lint that carries the checks as build steps -- a `lint` stage running `hugo --minify --printPathWarnings` and a `fmt-check` stage running the prettier check -- and reduce script/lint and script/fmt-check to building their stage. A successful build is a clean check. There is no host path and deliberately no "am I already inside a container?" branch, which would be a host lint path in disguise. The two stages share a `base` whose first four instructions are byte-identical to the main Dockerfile's, so the expensive `RUN script/bootstrap` layer that compiles the pinned Hugo from source is a cache hit against the main image instead of a second build of the same thing. Resolve the resulting recursion by splitting the checks by where they run, not with an escape hatch. `make check` runs script/lint, so the main Dockerfile can no longer `RUN make check`: that would be docker-in-docker inside a bare Alpine with no docker client and no daemon socket, and script/cibuild is what CI runs on every push. The main Dockerfile therefore runs `make test`, the production build, and script/cibuild builds it and then calls script/lint and script/fmt-check. CI still covers the production build, lint and the format check, and it runs exactly what a developer runs. script/fmt stays on the host because it rewrites the working tree, which a container build cannot do. That makes it the authoritative copy of the prettier version, scope and flags that the fmt-check stage duplicates; both sides carry a keep-in-sync note. The duplication is forced: any `RUN script/fmt-check` inside the image is the recursion again. Caching is waived for the checks in the shape this repo already settled: `ARG CHECK_EPOCH` with no default, declared and guarded separately in each stage because ARG does not cross a FROM, with the value expanded into the checked command as well as the guard so invalidation does not rest on BuildKit's treatment of an unreferenced ARG. All four image-building entrypoints now generate and pass it -- script/cibuild, script/docker, script/lint, script/fmt-check. Verified: two consecutive script/lint runs on an unchanged tree both executed hugo for real, with script/bootstrap CACHED; a constant-epoch counterfactual restored the false green (exit 0, lint layer CACHED, no hugo output); an empty epoch failed closed on the guard; a broken template failed the lint stage and an unformatted README failed the fmt-check stage, both reverted and re-run clean; script/cibuild and `make check` are green with all three checks demonstrably executing.
28 lines
1.0 KiB
Bash
Executable File
28 lines
1.0 KiB
Bash
Executable File
#!/bin/sh
|
|
# script/fmt-check: check the formatting of this repo's markdown and
|
|
# CSS (read-only). Like script/lint, it runs only in Docker: it builds
|
|
# the `fmt-check` stage of Dockerfile.lint, where prettier runs as a
|
|
# build step. Leaving prettier to run on the host here would have left
|
|
# `make check` with a host lint path, which is the thing being removed.
|
|
#
|
|
# The version, scope and flags live in Dockerfile.lint and must stay in
|
|
# sync with script/fmt, which is the authoritative copy and stays on the
|
|
# host because it writes to the working tree.
|
|
#
|
|
# Dockerfile.lint requires the CHECK_EPOCH build argument, generated
|
|
# here exactly as script/cibuild generates it -- see that script for why
|
|
# the check layer must not be allowed to cache, and why the value is
|
|
# built in an assignment rather than inline.
|
|
set -eu
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
|
|
main() {
|
|
cd "$ROOT"
|
|
epoch="$(date +%s%N)$$"
|
|
docker build -f Dockerfile.lint --target fmt-check \
|
|
--build-arg CHECK_EPOCH="$epoch" .
|
|
}
|
|
|
|
main "$@"
|