Files
lora.vegas/Dockerfile.lint
T
clawbot dc5e368d2b
check / check (push) Canceled after 0s
Make script/lint fail on any Hugo warning (closes #25)
The lint step in Dockerfile.lint now passes --panicOnWarning alongside
--printPathWarnings. Until now Hugo printed "Duplicate target paths"
when two pages wrote the same output file and still exited 0, so the
lint passed while one page was silently lost. The flag turns that
warning, and every other Hugo warning, into a failed lint.

script/test and the deploy build are unchanged. The comments in
Dockerfile.lint, script/lint and script/check, the README entry for
script/lint, and TODO.md now describe the stricter lint.

Model: opus-5-5
2026-10-21 15:06:16 +02:00

65 lines
3.3 KiB
Docker

# Lint-only image. `script/lint` builds this file and nothing else: the
# lint runs as a build step, so a successful build IS a clean lint.
#
# One stage, deliberately. A whole-file `docker build -f Dockerfile.lint .`
# builds only the file's LAST stage, and sibling stages off a shared base
# have no ordering edge between them, so a second stage sitting beside
# this one would be silently skipped by exactly the invocation the
# canonical org-wide `script/lint` uses -- a green that linted nothing,
# which is the failure mode this file exists to prevent. With a single
# stage there is nothing to skip and `script/lint` needs no `--target`.
# If a second check is ever added here it must be chained (`FROM lint AS
# ...`) or carry an explicit ordering edge, never left as a sibling.
#
# Only linting is containerised (owner ruling, 2026-08-10: "fmt and fmt
# check arent docker, just linting"). script/fmt and script/fmt-check run
# on the host, and the main Dockerfile runs the production build and the
# format check directly -- see the comment there.
#
# The lint is invoked directly below rather than through `make lint` or
# `script/lint`. That is not a style choice: `script/lint` IS this build,
# so calling it from inside would recurse into a docker build with no
# daemon.
#
# This repo's lint is a Hugo build that fails on any build error and on
# any Hugo warning. --printPathWarnings makes Hugo warn when two pages
# write the same output path, and --panicOnWarning turns that warning,
# and every other one, into a failed build. Only the lint is this strict:
# script/test and the deploy build stay plain `hugo --minify`.
# alpine 3.21, 2026-02-28
FROM alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
WORKDIR /src
# Keep these four instructions byte-identical to the main Dockerfile's,
# in the same order: Docker keys layers on the instruction chain, not on
# the file they live in, so an identical prefix means this build is a
# cache hit against the main image's layers. script/bootstrap compiles
# the pinned Hugo from source, which is by far the most expensive step
# here, and it must not be paid twice. The dependency layer is also
# deliberately above the ARG below, so it stays cached and only the lint
# step re-runs on every invocation.
COPY script/ script/
RUN script/bootstrap
COPY . .
# CHECK_EPOCH is a per-invocation nonce supplied by script/lint. Without
# it an unchanged tree serves the lint layer from cache: the lint never
# executes and the build still exits 0, which is precisely the false
# green this repo already fixed once in the main Dockerfile. Caching is
# explicitly waived for lint, so the value is expanded into the linted
# command as well as the guard -- two independent value-keyed
# invalidation points, so a cache miss never depends on BuildKit's
# treatment of an unreferenced ARG, and the epoch is visible in the build
# log. Declared with no default: a default is a constant, and a constant
# is a stable cache key. The guard makes a bare
# `docker build -f Dockerfile.lint .` fail loudly instead of silently
# reusing the empty (and therefore stable) cache key. Keep both
# references.
ARG CHECK_EPOCH
RUN [ -n "$CHECK_EPOCH" ] || exit 1
RUN echo "lint epoch: ${CHECK_EPOCH}" && \
hugo --minify --printPathWarnings --panicOnWarning