diff --git a/Makefile b/Makefile index 31ae122..4465966 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: bootstrap setup test lint fmt fmt-check check docker hooks serve +.PHONY: bootstrap setup test lint fmt fmt-check check docker cibuild precommit hooks serve bootstrap: @script/bootstrap @@ -24,6 +24,12 @@ check: docker: @script/docker +cibuild: + @script/cibuild + +precommit: + @script/precommit + hooks: @script/install-precommit diff --git a/README.md b/README.md index 0d45073..c147478 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,21 @@ provide: - `script/cibuild` — the CI build: `script/lint` first, for fail-fast feedback, then the main image, which runs the non-lint checks - `script/install-precommit` — install the git pre-commit hook that runs - `script/check` + `script/precommit` + +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 check`, `make docker`, `make cibuild` — with one exception: +`script/install-precommit` is `make hooks`. `script/precommit`, which is what +the installed hook runs, is `make precommit`. Prefer the make targets; the +`Makefile` lists the operations you are expected to run. + +`make cibuild` is the slowest target: it is the only one that runs two container +builds, the lint image first and then the main image. The two share the +`script/bootstrap` layer byte-for-byte, so the pinned-Hugo compile described +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. `script/lint` has no host path and no "already inside a container?" branch, so diff --git a/TODO.md b/TODO.md index 2c2dfc8..c57fd1c 100644 --- a/TODO.md +++ b/TODO.md @@ -20,22 +20,52 @@ 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 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 -the edge defaults to — unverified in production until the next deploy. The lint -now runs inside a container and nowhere else: `script/lint` is a build of +the edge defaults to, and confirmed live in production on both hostnames. The +lint 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 -and stays on the host. +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" +rule is satisfiable for the CI build as well as for the everyday checks. # Next Step -Add the missing `cibuild` and `precommit` shims to the `Makefile`, so that every -documented entrypoint has a make target and the documented "always use make -targets" rule is actually satisfiable -(https://git.eeqj.de/sneak/lora.vegas/issues/34). Done when `make cibuild` and -`make precommit` exist, are declared `.PHONY`, and the README Entrypoints -section matches. +Make the prettier scope's exclusion of dot-directories explicit instead of +leaning on `.gitignore` (https://git.eeqj.de/sneak/lora.vegas/issues/33). # Completed Steps +- 2026-08-10: added the `cibuild` and `precommit` targets to the `Makefile` + (https://git.eeqj.de/sneak/lora.vegas/issues/34). Both scripts already + existed, were already documented, and are the two entrypoints a contributor is + most likely to be told to run — the CI build and what the pre-commit hook runs + — yet neither had a make target, so the standing rule to use make targets + rather than the underlying tool could not be followed for either. It bit + reviewers twice, most recently on + https://git.eeqj.de/sneak/lora.vegas/pulls/32, and it bit hardest for the + build: since https://git.eeqj.de/sneak/lora.vegas/issues/30 a bare + `docker build .` fails closed on the `CHECK_EPOCH` guard, so `script/cibuild` + is one of only three supported ways to build an image and was the only one + without a target. The two targets are thin shims in the existing style and + change nothing about what the scripts do. `.PHONY` was already complete and + now lists both. `README.md`'s Entrypoints section gained the script-to-target + mapping, including the two names that do not match — + `script/install-precommit` is `make hooks`, and `script/precommit` is + `make precommit` — plus a note that `make cibuild` is the slowest target + because it is the only one that runs two container builds, while still taking + seconds once the shared `script/bootstrap` layer is cached. The section's + pre-existing `script/install-precommit` bullet, which claimed the installed + hook runs `script/check`, now says `script/precommit`, which is what the + script actually writes into `.git/hooks/pre-commit`. The stale Future Step + asking for post-deploy confirmation of `static/_headers` is dropped here: it + was confirmed live on both hostnames + (https://git.eeqj.de/sneak/lora.vegas/issues/14). Verified that `make cibuild` + earns its green rather than replaying a warm cache: one invocation ran both + 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 (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 @@ -283,8 +313,6 @@ section matches. Startable work first. Everything under "Blocked" waits on somebody or something outside this repo, so nothing there may be picked up as the Next Step. -- Make the prettier scope's exclusion of dot-directories explicit instead of - leaning on `.gitignore` (https://git.eeqj.de/sneak/lora.vegas/issues/33) - Fix the README's SSH-only clone URL, and add the two entrypoints the Entrypoints section omits, `script/precommit` and `script/projectname` (https://git.eeqj.de/sneak/lora.vegas/issues/36) @@ -314,17 +342,6 @@ 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`; only the owner can remove them (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`. Both are owner calls: neither can be walked back inside the max-age window, and `includeSubDomains` binds hostnames this repo does not control