REPO_POLICIES.md: "make test must complete in under 20 seconds. Add a
30-second timeout in the Makefile." EXISTING_REPO_CHECKLIST.md restates it as
"make test has a 30-second timeout".
Neither script/test nor script/lint has any timeout. Both are bare hugo --minify invocations. The build currently takes about 16 ms, so the 20-second
budget is met with five orders of magnitude to spare — but there is no guard,
so a hang (a pathological template loop, a wedged filesystem, a future remote
Hugo module fetch) blocks the gate and CI indefinitely instead of failing.
Fix
Wrap the build in timeout 30 in both scripts. The timeout binary is in
coreutils and is present in the alpine build image; confirm it is available in script/bootstrap's install set on all four supported package managers, or
guard its use if it is not universally present.
Keep the guard in the scripts rather than the Makefile. The policy text says
"in the Makefile", but in this repo the Makefile targets are thin shims by
design and every implementation lives in script/ — putting logic in the
Makefile would break the scripts-to-rule-them-all pattern the policy mandates
elsewhere. The scripts are also what the Dockerfile and pre-commit hook
actually invoke, so a Makefile-level guard would not cover those paths. Note
this reasoning in the PR body.
Definition of done
script/test and script/lint both bound their Hugo invocation to 30
seconds.
A timeout exits non-zero with a message that makes the cause obvious — a
bare 124 exit code is not good enough.
timeout availability is verified in the Docker build environment; if script/bootstrap needs to install coreutils on any of the four supported
package managers, it does so.
make test, make lint, and make check all still pass and still complete
in well under 20 seconds.
script/cibuild succeeds.
TODO.md updated in the same commit.
No sensible Hugo equivalent — explicitly not applicable
go test -timeout 30s -race -cover ./... — the canonical Makefile
snippet for this rule is Go-specific. -timeout is a go test flag, -race needs a compiled binary with race instrumentation, and -cover needs
Go source. Only the wall-clock bound transfers, via timeout(1).
The conditional verbose rerun pattern (<cmd> || { echo "--- Rerunning with -v ---"; <cmd> -v; exit 1; }) — do not implement this here. It
presupposes a test runner with a quiet/verbose pair. hugo --minify has no
such pair; the nearest analogue is re-running with --logLevel debug, which
would double the build on every failure for marginal extra signal, and Hugo
already prints the failing template and line on error. Adding it would be
cargo-culting the Go pattern into a place it does not fit.
Ref: REPO_POLICIES.md — "Docker builds must complete in under 5 minutes",
"make test must complete in under 20 seconds. Add a 30-second timeout".
## Problem
`REPO_POLICIES.md`: "`make test` must complete in under 20 seconds. Add a
30-second timeout in the Makefile." `EXISTING_REPO_CHECKLIST.md` restates it as
"`make test` has a 30-second timeout".
Neither `script/test` nor `script/lint` has any timeout. Both are bare `hugo
--minify` invocations. The build currently takes about 16 ms, so the 20-second
budget is met with five orders of magnitude to spare — but there is no guard,
so a hang (a pathological template loop, a wedged filesystem, a future remote
Hugo module fetch) blocks the gate and CI indefinitely instead of failing.
## Fix
Wrap the build in `timeout 30` in both scripts. The `timeout` binary is in
coreutils and is present in the alpine build image; confirm it is available in
`script/bootstrap`'s install set on all four supported package managers, or
guard its use if it is not universally present.
Keep the guard in the scripts rather than the `Makefile`. The policy text says
"in the Makefile", but in this repo the Makefile targets are thin shims by
design and every implementation lives in `script/` — putting logic in the
Makefile would break the scripts-to-rule-them-all pattern the policy mandates
elsewhere. The scripts are also what the `Dockerfile` and pre-commit hook
actually invoke, so a Makefile-level guard would not cover those paths. Note
this reasoning in the PR body.
## Definition of done
1. `script/test` and `script/lint` both bound their Hugo invocation to 30
seconds.
2. A timeout exits non-zero with a message that makes the cause obvious — a
bare `124` exit code is not good enough.
3. `timeout` availability is verified in the Docker build environment; if
`script/bootstrap` needs to install coreutils on any of the four supported
package managers, it does so.
4. `make test`, `make lint`, and `make check` all still pass and still complete
in well under 20 seconds.
5. `script/cibuild` succeeds.
6. `TODO.md` updated in the same commit.
## No sensible Hugo equivalent — explicitly not applicable
- **`go test -timeout 30s -race -cover ./...`** — the canonical Makefile
snippet for this rule is Go-specific. `-timeout` is a `go test` flag,
`-race` needs a compiled binary with race instrumentation, and `-cover` needs
Go source. Only the wall-clock bound transfers, via `timeout(1)`.
- **The conditional verbose rerun pattern** (`<cmd> || { echo "--- Rerunning
with -v ---"; <cmd> -v; exit 1; }`) — do **not** implement this here. It
presupposes a test runner with a quiet/verbose pair. `hugo --minify` has no
such pair; the nearest analogue is re-running with `--logLevel debug`, which
would double the build on every failure for marginal extra signal, and Hugo
already prints the failing template and line on error. Adding it would be
cargo-culting the Go pattern into a place it does not fit.
Ref: `REPO_POLICIES.md` — "Docker builds must complete in under 5 minutes",
"`make test` must complete in under 20 seconds. Add a 30-second timeout".
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
REPO_POLICIES.md: "make testmust complete in under 20 seconds. Add a30-second timeout in the Makefile."
EXISTING_REPO_CHECKLIST.mdrestates it as"
make testhas a 30-second timeout".Neither
script/testnorscript/linthas any timeout. Both are barehugo --minifyinvocations. The build currently takes about 16 ms, so the 20-secondbudget is met with five orders of magnitude to spare — but there is no guard,
so a hang (a pathological template loop, a wedged filesystem, a future remote
Hugo module fetch) blocks the gate and CI indefinitely instead of failing.
Fix
Wrap the build in
timeout 30in both scripts. Thetimeoutbinary is incoreutils and is present in the alpine build image; confirm it is available in
script/bootstrap's install set on all four supported package managers, orguard its use if it is not universally present.
Keep the guard in the scripts rather than the
Makefile. The policy text says"in the Makefile", but in this repo the Makefile targets are thin shims by
design and every implementation lives in
script/— putting logic in theMakefile would break the scripts-to-rule-them-all pattern the policy mandates
elsewhere. The scripts are also what the
Dockerfileand pre-commit hookactually invoke, so a Makefile-level guard would not cover those paths. Note
this reasoning in the PR body.
Definition of done
script/testandscript/lintboth bound their Hugo invocation to 30seconds.
bare
124exit code is not good enough.timeoutavailability is verified in the Docker build environment; ifscript/bootstrapneeds to install coreutils on any of the four supportedpackage managers, it does so.
make test,make lint, andmake checkall still pass and still completein well under 20 seconds.
script/cibuildsucceeds.TODO.mdupdated in the same commit.No sensible Hugo equivalent — explicitly not applicable
go test -timeout 30s -race -cover ./...— the canonical Makefilesnippet for this rule is Go-specific.
-timeoutis ago testflag,-raceneeds a compiled binary with race instrumentation, and-coverneedsGo source. Only the wall-clock bound transfers, via
timeout(1).<cmd> || { echo "--- Rerunning with -v ---"; <cmd> -v; exit 1; }) — do not implement this here. Itpresupposes a test runner with a quiet/verbose pair.
hugo --minifyhas nosuch pair; the nearest analogue is re-running with
--logLevel debug, whichwould double the build on every failure for marginal extra signal, and Hugo
already prints the failing template and line on error. Adding it would be
cargo-culting the Go pattern into a place it does not fit.
Ref:
REPO_POLICIES.md— "Docker builds must complete in under 5 minutes","
make testmust complete in under 20 seconds. Add a 30-second timeout".