Compare commits
1
Commits
next
..
341c8afd76
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
341c8afd76 |
+4
-7
@@ -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
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user