Compare commits

..
1 Commits
Author SHA1 Message Date
clawbot 341c8afd76 Add Makefile shims for cibuild and precommit (closes #34)
check / check (push) Successful in 19s
script/cibuild and script/precommit both existed and were already the
documented CI and pre-commit entrypoints, but neither had a Makefile
target, so the standing rule to drive the repo through make targets
rather than the underlying tool could not be followed for either.

It matters most for the build. A bare `docker build .` fails closed on
the CHECK_EPOCH guard by design, so script/cibuild is one of only three
supported ways to build an image here, and it was the only one of the
three without a target while `make docker` had one.

The two targets are thin shims in the same style as every other target
and change nothing about what the scripts do. .PHONY was already
complete for the targets that existed and now lists both new ones.

README.md's Entrypoints section gains the script-to-target mapping so
the two documents agree, including the two names that do not match:
script/install-precommit is `make hooks`, and script/precommit is
`make precommit`. It also warns that `make cibuild` runs two container
builds and costs minutes, so nobody types it expecting the runtime the
other make targets have.
2026-08-10 13:40:07 +00:00
5 changed files with 47 additions and 53 deletions
+4 -7
View File
@@ -21,11 +21,9 @@
# so calling it from inside would recurse into a docker build with no # so calling it from inside would recurse into a docker build with no
# daemon. # daemon.
# #
# This repo's lint is a Hugo build that fails on any build error and on # This repo's lint is a clean Hugo build that surfaces broken internal
# any Hugo warning. --printPathWarnings makes Hugo warn when two pages # links and template path problems: `hugo` fails on build errors and
# write the same output path, and --panicOnWarning turns that warning, # --printPathWarnings reports render-target collisions.
# 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 # alpine 3.21, 2026-02-28
FROM alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709 FROM alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709
@@ -60,5 +58,4 @@ COPY . .
# references. # references.
ARG CHECK_EPOCH ARG CHECK_EPOCH
RUN [ -n "$CHECK_EPOCH" ] || exit 1 RUN [ -n "$CHECK_EPOCH" ] || exit 1
RUN echo "lint epoch: ${CHECK_EPOCH}" && \ RUN echo "lint epoch: ${CHECK_EPOCH}" && hugo --minify --printPathWarnings
hugo --minify --printPathWarnings --panicOnWarning
+8 -12
View File
@@ -66,10 +66,9 @@ provide:
git pre-commit hook git pre-commit hook
- `script/test` — the correctness check: a clean `hugo --minify` production - `script/test` — the correctness check: a clean `hugo --minify` production
build build
- `script/lint` — a Hugo build that fails on any Hugo warning, including two - `script/lint` — a clean build that surfaces broken links and path collisions,
pages that write the same output path, run inside Docker: it builds run inside Docker: it builds `Dockerfile.lint`, where the lint is a build
`Dockerfile.lint`, where the lint is a build step, so a successful build is a step, so a successful build is a clean lint
clean lint
- `script/fmt` — format every markdown and CSS file in the repo with prettier; - `script/fmt` — format every markdown and CSS file in the repo with prettier;
the exclusions live in `.prettierignore` with the reason for each the exclusions live in `.prettierignore` with the reason for each
- `script/fmt-check` — check that formatting (read-only) - `script/fmt-check` — check that formatting (read-only)
@@ -79,21 +78,18 @@ provide:
- `script/cibuild` — the CI build: `script/lint` first, for fail-fast feedback, - `script/cibuild` — the CI build: `script/lint` first, for fail-fast feedback,
then the main image, which runs the non-lint checks then the main image, which runs the non-lint checks
- `script/install-precommit` — install the git pre-commit hook that runs - `script/install-precommit` — install the git pre-commit hook that runs
`script/precommit` `script/check`
Each of those has a Makefile shim of the same name — `make bootstrap`, Each of those has a Makefile shim of the same name — `make bootstrap`,
`make setup`, `make test`, `make lint`, `make fmt`, `make fmt-check`, `make setup`, `make test`, `make lint`, `make fmt`, `make fmt-check`,
`make check`, `make docker`, `make cibuild` — with one exception: `make check`, `make docker`, `make cibuild` — with one exception:
`script/install-precommit` is `make hooks`. `script/precommit`, which is what `script/install-precommit` is `make hooks`. `script/precommit`, which is what
the installed hook runs, is `make precommit`. Prefer the make targets; the the installed hook runs, is `make precommit`. Prefer the make targets; the
`Makefile` lists the operations you are expected to run. `Makefile` is the authoritative list of what this repo can do.
`make cibuild` is the slowest target: it is the only one that runs two container `make cibuild` is the slow one. It runs two container builds rather than
builds, the lint image first and then the main image. The two share the anything on the host, so budget minutes, not the seconds a `make`-shaped command
`script/bootstrap` layer byte-for-byte, so the pinned-Hugo compile described usually implies. That is the cost of the CI build, not a sign of a problem.
above is paid once per machine rather than twice, and once that layer is cached
a full `make cibuild` takes seconds. That is the cost of the CI build, not a
sign of a problem.
Every lint run for this repo happens inside a container, and only the lint does. Every lint run for this repo happens inside a container, and only the lint does.
`script/lint` has no host path and no "already inside a container?" branch, so `script/lint` has no host path and no "already inside a container?" branch, so
+27 -25
View File
@@ -20,8 +20,8 @@ wrangler CLI install, an exact version), and the Hugo that builds the published
site is a deliberate pinned version rather than whatever the base image's site is a deliberate pinned version rather than whatever the base image's
package repo serves. The site now ships a Cloudflare Pages `_headers` file, so package repo serves. The site now ships a Cloudflare Pages `_headers` file, so
its response security headers are declared in the repo instead of being whatever its response security headers are declared in the repo instead of being whatever
the edge defaults to, and confirmed live in production on both hostnames. The the edge defaults to — unverified in production until the next deploy. The lint
lint now runs inside a container and nowhere else: `script/lint` is a build of now runs inside a container and nowhere else: `script/lint` is a build of
`Dockerfile.lint`, with no host path to fall back to. Formatting is not a lint `Dockerfile.lint`, with no host path to fall back to. Formatting is not a lint
and stays on the host. Every entrypoint the README documents now has a and stays on the host. Every entrypoint the README documents now has a
`Makefile` target, so the org-wide "use make targets, never the underlying tool" `Makefile` target, so the org-wide "use make targets, never the underlying tool"
@@ -34,13 +34,6 @@ leaning on `.gitignore` (https://git.eeqj.de/sneak/lora.vegas/issues/33).
# Completed Steps # Completed Steps
- 2026-10-21: made `script/lint` fail when two pages write the same output path
(https://git.eeqj.de/sneak/lora.vegas/issues/25). `Dockerfile.lint` now runs
`hugo --minify --printPathWarnings --panicOnWarning`. `--printPathWarnings`
makes Hugo warn about the collision, and `--panicOnWarning` turns that warning
and every other Hugo warning into a failed lint; until now the warning was
printed and the lint still exited 0. `script/test` and the deploy build stay
plain `hugo --minify`
- 2026-08-10: added the `cibuild` and `precommit` targets to the `Makefile` - 2026-08-10: added the `cibuild` and `precommit` targets to the `Makefile`
(https://git.eeqj.de/sneak/lora.vegas/issues/34). Both scripts already (https://git.eeqj.de/sneak/lora.vegas/issues/34). Both scripts already
existed, were already documented, and are the two entrypoints a contributor is existed, were already documented, and are the two entrypoints a contributor is
@@ -57,22 +50,16 @@ leaning on `.gitignore` (https://git.eeqj.de/sneak/lora.vegas/issues/33).
now lists both. `README.md`'s Entrypoints section gained the script-to-target now lists both. `README.md`'s Entrypoints section gained the script-to-target
mapping, including the two names that do not match — mapping, including the two names that do not match —
`script/install-precommit` is `make hooks`, and `script/precommit` is `script/install-precommit` is `make hooks`, and `script/precommit` is
`make precommit` — plus a note that `make cibuild` is the slowest target `make precommit` — plus a warning that `make cibuild` costs minutes because it
because it is the only one that runs two container builds, while still taking is two container builds, so nobody types it expecting a `make`-shaped runtime.
seconds once the shared `script/bootstrap` layer is cached. The section's Verified that `make cibuild` earns its green rather than replaying a warm
pre-existing `script/install-precommit` bullet, which claimed the installed cache: one invocation ran both builds for real in sequence, each with its own
hook runs `script/check`, now says `script/precommit`, which is what the distinct `CHECK_EPOCH`, with `RUN script/bootstrap` `CACHED` above and no
script actually writes into `.git/hooks/pre-commit`. The stale Future Step check layer cached below it — the `Dockerfile.lint` build echoed its epoch and
asking for post-deploy confirmation of `static/_headers` is dropped here: it printed hugo's own build table, then the main image build echoed a different
was confirmed live on both hostnames epoch, ran `script/test` for the production build and `script/fmt-check` for
(https://git.eeqj.de/sneak/lora.vegas/issues/14). Verified that `make cibuild` the formatting check. `make precommit` passes on a clean tree, and
earns its green rather than replaying a warm cache: one invocation ran both `make check` passes
builds for real in sequence, each with its own distinct `CHECK_EPOCH`, with
`RUN script/bootstrap` `CACHED` above and no check layer cached below it — the
`Dockerfile.lint` build echoed its epoch and printed hugo's own build table,
then the main image build echoed a different epoch, ran `script/test` for the
production build and `script/fmt-check` for the formatting check.
`make precommit` passes on a clean tree, and `make check` passes
- 2026-08-10: moved the lint into Docker - 2026-08-10: moved the lint into Docker
(https://git.eeqj.de/sneak/lora.vegas/issues/38). A new root `Dockerfile.lint` (https://git.eeqj.de/sneak/lora.vegas/issues/38). A new root `Dockerfile.lint`
runs `hugo --minify --printPathWarnings` as a build step, so a successful runs `hugo --minify --printPathWarnings` as a build step, so a successful
@@ -335,6 +322,10 @@ outside this repo, so nothing there may be picked up as the Next Step.
## Blocked ## Blocked
- Decide whether `script/lint` should fail on render-target collisions rather
than only print them; `--printPathWarnings` exits 0 today, so the signal is
reported and not enforced. Owner call, since it changes what the gate rejects
(https://git.eeqj.de/sneak/lora.vegas/issues/25)
- Move the artifact actions in `.gitea/workflows/deploy.yml` to v4 once this - Move the artifact actions in `.gitea/workflows/deploy.yml` to v4 once this
Gitea Actions instance serves the v4 artifact protocol; they are pinned on the Gitea Actions instance serves the v4 artifact protocol; they are pinned on the
deprecated v3 line because v4 fails here deprecated v3 line because v4 fails here
@@ -345,6 +336,17 @@ outside this repo, so nothing there may be picked up as the Next Step.
- Delete the stale remote branches `feat/initial-site` and `security-audit`; - Delete the stale remote branches `feat/initial-site` and `security-audit`;
only the owner can remove them only the owner can remove them
(https://git.eeqj.de/sneak/lora.vegas/issues/15) (https://git.eeqj.de/sneak/lora.vegas/issues/15)
- After the next deploy, confirm the `_headers` file actually took effect, on
both `https://lora.vegas/` and `https://www.lora.vegas/`: `curl -sSI` against
each must show `strict-transport-security` or `content-security-policy`.
Cloudflare Pages silently ignores a malformed `_headers`, and checking
`x-content-type-options` would pass either way because the edge sends it
regardless. `www` has to be checked too and not just the apex: dropping
`includeSubDomains` rests on `www.lora.vegas` being served by this same Pages
project, which was established behaviourally from identical response bodies
rather than from the Cloudflare dashboard. If `www` turns out not to be
covered, the `includeSubDomains` decision has to be revisited
(https://git.eeqj.de/sneak/lora.vegas/issues/14)
- Decide the HSTS `includeSubDomains` and `preload` posture for `lora.vegas`. - Decide the HSTS `includeSubDomains` and `preload` posture for `lora.vegas`.
Both are owner calls: neither can be walked back inside the max-age window, Both are owner calls: neither can be walked back inside the max-age window,
and `includeSubDomains` binds hostnames this repo does not control and `includeSubDomains` binds hostnames this repo does not control
+1 -1
View File
@@ -2,7 +2,7 @@
# script/check: run all checks. Our own extension to # script/check: run all checks. Our own extension to
# scripts-to-rule-them-all. Must not modify any tracked files. Runs the # scripts-to-rule-them-all. Must not modify any tracked files. Runs the
# canonical order: the clean production build, then the lint build that # canonical order: the clean production build, then the lint build that
# fails on any Hugo warning, then the read-only formatting check. # reports path warnings, then the read-only formatting check.
# #
# The lint - and only the lint - runs inside Docker: it is a build of # The lint - and only the lint - runs inside Docker: it is a build of
# Dockerfile.lint, so this script needs a working docker daemon and has # Dockerfile.lint, so this script needs a working docker daemon and has
+7 -8
View File
@@ -1,13 +1,12 @@
#!/bin/sh #!/bin/sh
# script/lint: run the lint. This Hugo site has no dedicated linter, so # script/lint: run the lint. This Hugo site has no dedicated linter, so
# the lint is a Hugo build that fails on any build error and on any Hugo # the lint gate is a clean build that surfaces broken internal links and
# warning, including two pages that write the same output path. Where # template path problems -- but where it runs is not negotiable: every
# it runs is not negotiable. Every lint run happens inside a Docker # lint run happens inside a Docker container, so this script does
# container, so this script does nothing except build Dockerfile.lint. # nothing except build Dockerfile.lint. The lint is a build step there,
# The lint is a build step there, so a successful build is a clean lint. # so a successful build is a clean lint. There is deliberately no host
# There is deliberately no host fallback and no "already inside a # fallback and no "already inside a container?" branch: either would be
# container?" branch: either would be a host lint path wearing a # a host lint path wearing a disguise.
# disguise.
# #
# No --target: Dockerfile.lint has exactly one stage, so the whole-file # No --target: Dockerfile.lint has exactly one stage, so the whole-file
# build IS the lint. See that file for why a second, sibling stage would # build IS the lint. See that file for why a second, sibling stage would