25b6c0a9de790273c0e5a5eb3f49e36a9a4485d1
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
25b6c0a9de |
Run the lint inside Docker via Dockerfile.lint (closes #38)
check / check (push) Successful in 1m23s
Add a root Dockerfile.lint that runs `hugo --minify --printPathWarnings`
as a build step, so a successful build IS a clean lint, and reduce
script/lint to building that file. There is no host lint path and
deliberately no "am I already inside a container?" branch, which would
be a host lint path in disguise.
The containerisation boundary is lint only, per the owner ruling on the
issue: formatting is not a lint, so script/fmt and script/fmt-check stay
on the host, unchanged in version, scope and flags. That also removes
the forced duplication of prettier's settings between a script and a
Dockerfile, and with it the keep-in-sync notes that duplication needed.
Dockerfile.lint has exactly one stage on purpose. A whole-file
`docker build -f Dockerfile.lint .` builds only the file's last stage,
and sibling stages off a shared base carry no ordering edge, so a second
stage beside the lint would be silently skipped by exactly the
invocation the canonical org-wide script/lint uses -- a green that
linted nothing, which the per-stage CHECK_EPOCH guard cannot catch
because the stage that did run satisfies it. With one stage there is
nothing to skip and script/lint needs no --target. A comment in the file
says that any second check added here must be chained or carry an
explicit ordering edge, never left as a sibling.
Its first four instructions are byte-identical to the main Dockerfile's
and in the same order, so the expensive `RUN script/bootstrap` layer
that compiles the pinned Hugo from source is shared between the two
images rather than paid twice.
Resolve the recursion by direction, not detection. `make check` calls
script/lint, and script/lint is now a `docker build`, so `RUN make
check` in an image would attempt a docker build inside a build step
where there is no daemon. The main Dockerfile therefore runs the
individual non-lint checks -- script/test and script/fmt-check, as
separate RUN lines under the CHECK_EPOCH guard -- matching the canonical
shape, and only the lint is absent from it. script/cibuild runs
script/lint first, for fail-fast feedback: on a runner with no cached
bootstrap layer a lint failure should not wait behind a Hugo build from
source. CI coverage is therefore unchanged, and it runs the same scripts
a developer runs.
Caching is waived for the lint in the shape this repo already settled:
ARG CHECK_EPOCH with no default, guarded with
`[ -n "$CHECK_EPOCH" ] || exit 1`, and the value expanded into the
linted command as well as the guard, so invalidation never rests on
BuildKit's treatment of an unreferenced ARG. Every image-building
entrypoint generates and passes it -- script/cibuild, script/docker,
script/lint -- each as a whole assignment rather than inline, for the
`set -e` reason script/cibuild documents.
script/lint builds with `--output type=cacheonly`: the build is run for
its exit status, not for an image, and because the lint layer is
cache-busted on every invocation an exporting build leaves one dangling
image per lint run. On a host shared with other work that accumulates.
The build cache is unaffected, so script/bootstrap still hits, and
failures still propagate.
Two divergences from REPO_POLICIES.md, stated rather than buried:
- REPO_POLICIES.md:92, "all Dockerfiles must run `make check`". That
rule and "every lint run happens in Docker" cannot both hold once
`make check` contains the lint.
- REPO_POLICIES.md:102-168, which requires a separate lint stage whose
result the build stage depends on through
`COPY --from=lint /src/go.sum /dev/null`, on the stated grounds that
without the edge "the build stage would not wait for lint to finish
and a lint failure might not fail the overall build". No such edge
exists here: the lint is its own file and its own build, sequenced
by script/cibuild rather than by BuildKit. Both sections are
superseded upstream by 12e8db8 in sneak/prompts, which deletes the
Go multistage lint stage and its ordering trick for the same reason
-- that stage ran `make lint`, which is now a docker build.
Verified: two consecutive script/lint runs on an unchanged tree both
executed hugo for real, distinct epochs echoed, script/bootstrap CACHED,
second run 0.85s; a whole-file `docker build -f Dockerfile.lint .` with
the argument and no --target ran the lint for real; a bare build with no
argument failed closed on the guard; a planted template error failed the
lint with hugo's own render error and made script/cibuild exit non-zero
in 0.6s with the main image build never starting; a planted over-long
line failed the host script/fmt-check; both reverted and re-run clean;
`make check`, script/docker and script/cibuild all green with every
check layer observed executing rather than served from cache, and the
bootstrap layer CACHED in both images. The deploy path is byte-identical
to main: .gitea/, script/bootstrap, script/test and .dockerignore are
untouched.
|
||
|
|
407b0a0d79 |
Add the MIT LICENSE and state it in the README (closes #10)
check / check (push) Successful in 11s
The repo had no LICENSE, which REPO_POLICIES.md lists as a mandatory
minimum file, and the README's License section said "Content is provided
as-is for community use." That granted nothing explicitly and matched no
committed file.
The repo is public, verified on the Gitea API rather than assumed, so
the standing policy applies: MIT on any public repo lacking a license.
LICENSE is byte-identical to the canonical sneak/homoicon copy (same git
blob,
|
||
|
|
5f998c6e70 |
Add a Cloudflare Pages _headers file with security headers (closes #14)
check / check (push) Successful in 9s
Hugo copies static/ verbatim into public/, so static/_headers lands at the deploy output root, which is where Pages reads it from. This is the first root-level static/ in the repo; Hugo unions it with the theme's static/ per path rather than shadowing it, and the built tree confirms that: public/css/style.css and public/index.html are byte-identical to the previous build and the static file count goes from 1 to 2. The live "before" was measured rather than assumed. Cloudflare already sends X-Content-Type-Options and Referrer-Policy by default, so those two lines are restatements; the substance is Strict-Transport-Security, Content-Security-Policy, X-Frame-Options and Permissions-Policy, none of which the site sends today. Every value is checked against the built page, which loads nothing: no script, img, link, iframe, form or media element, no style= and no on*= attribute. It has exactly one inline <style> block, filled by readFile in baseof.html. So default-src 'none' with style-src 'unsafe-inline' is both achievable and tight, and 'unsafe-inline' is required by, and only by, that deliberate inlining. There is no script-src allowance because there are no scripts. X-Frame-Options: DENY and frame-ancestors 'none' agree. HSTS carries neither preload nor includeSubDomains. www.lora.vegas is the only other name in DNS and it is served by this same Pages project, so this file sets HSTS on its responses directly; includeSubDomains would instead bind every future subdomain for a year, with no way to walk it back inside the max-age window without also dropping the apex protection. Verified in a headless Chrome against a local server that parses the committed _headers and applies it as real response headers: zero CSP violations, the inlined stylesheet parses to 17 rules with the computed body padding, tagline colour and link colour all coming from the theme CSS, framing from another origin refused by frame-ancestors, and all five named outbound links still navigating with status 200. Whether Pages actually parses the file cannot be verified from here. Pages silently ignores a malformed _headers, so the green build proves nothing about it; that check belongs after the next deploy and must be made on Strict-Transport-Security or Content-Security-Policy, since X-Content-Type-Options would pass either way. It has to be run against both lora.vegas and www.lora.vegas: dropping includeSubDomains rests on www being served by this same Pages project, which was established from identical response bodies rather than from the Cloudflare dashboard. |
||
|
|
bcb90e74b4 |
Run script/lint from script/check (closes #9)
check / check (push) Successful in 14s
script/check ran only fmt-check then test, so script/lint was never invoked anywhere in the gate: make check shims to script/check, the Dockerfile runs make check, script/cibuild builds the Dockerfile, and the pre-commit hook calls script/check. The script was dead code that the README advertised as part of the gate. It now runs test, lint, fmt-check in the canonical order. script/lint is hugo --minify --printPathWarnings, which reports render-target collisions that the plain hugo --minify in script/test does not; that signal was being discarded. The gate still modifies no tracked files. script/test and script/lint both write to public/, which is gitignored and was already written by script/test before this change. Corrects the two documents that enumerated the old two-step gate: the README Entrypoints line for script/check, and the Dockerfile header comment above the RUN make check that executes it. |