Re-vendor the canonical files from sneak/prompts at c55a0cb (closes #95)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
Every vendored file, REPO_POLICIES.md and every model script is the copy at sneak/prompts c55a0cb, with this repository's own entries kept after the canonical content. Lint and test are phases of the Dockerfile that write no image, built uncached. make test runs the suite under the race detector as nobody, because root reads the files the tests make unreadable. Dockerfile.lint, script/verify-lint-image-pin and make test-race are gone. Prettier runs on the host, from the node and yarn that script/bootstrap installs. golangci-lint v2.14.0 raises no findings. .claude/settings.json is deleted. Deviation: the set comes from c55a0cb on next rather than dd4027b, as the instructions on sneak/prompts#78 allow. Model: opus-5-5
This commit is contained in:
@@ -29,6 +29,17 @@
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- re-vendor the canonical files and model scripts from `sneak/prompts` `next` at
|
||||
`c55a0cb`: golangci-lint v2.14.0; lint and test are phases of the `Dockerfile`
|
||||
that write no image, and `make test` runs the suite under the race detector,
|
||||
so `Dockerfile.lint`, `script/verify-lint-image-pin` and `make test-race` are
|
||||
gone; every `docker build` in `script/` passes `--no-cache`; prettier runs on
|
||||
the host, from the node and yarn `script/bootstrap` installs, so the
|
||||
`prettier` and `markdown` stages are gone and the build stage installs `git`
|
||||
and `make` itself; a new push cancels the workflow's older run on the same
|
||||
branch, and a run stops after 20 minutes; `.claude/settings.json` is deleted
|
||||
(2026-10-08, https://git.eeqj.de/sneak/sfdupes/issues/95)
|
||||
|
||||
- `scan` records mtime to the nanosecond, as whole seconds in `mtime` plus
|
||||
`mtime_nsec`, and compares it at that resolution, so a same-size rewrite
|
||||
within the same second is re-hashed (2026-10-07,
|
||||
@@ -38,16 +49,22 @@
|
||||
`script/` and both Dockerfiles; §Workflow now branches from and merges to
|
||||
`next` (2026-10-04, https://git.eeqj.de/sneak/sfdupes/issues/49)
|
||||
|
||||
- `make test-race` runs the test suite under the race detector in a cgo-enabled
|
||||
- `make test-race` ran the test suite under the race detector in a cgo-enabled
|
||||
container, outside `make check` (2026-10-04,
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/18)
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/18). Since
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/95 `make test` itself runs the suite
|
||||
under the race detector, in the `Dockerfile`'s Debian-based `test` phase, and
|
||||
`make test-race` is gone
|
||||
|
||||
- a bare `docker build .` fails with a message naming `script/cibuild` and
|
||||
`script/docker` instead of serving the gates from cache (2026-10-04,
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/39)
|
||||
- a bare `docker build .` failed, naming `script/cibuild` and `script/docker`,
|
||||
rather than serve the gates from cache (2026-10-04,
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/39). Since
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/95 a bare build succeeds, as
|
||||
`REPO_POLICIES.md` requires, and may serve the gates from cache; the builds in
|
||||
`script/` pass `--no-cache`, so theirs always run
|
||||
|
||||
- `make fmt` and `make fmt-check` run prettier over all Markdown, in Docker, and
|
||||
CI checks it; all Markdown reformatted (2026-10-04,
|
||||
- `make fmt` and `make fmt-check` run prettier over all Markdown, and CI checks
|
||||
it; all Markdown reformatted (2026-10-04,
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/19)
|
||||
|
||||
- `script/lint` writes no image, so a run no longer leaves an untagged one
|
||||
@@ -90,9 +107,12 @@
|
||||
- README documents install, Docker, a daily cron scan and how to read and check
|
||||
the reports (2026-10-04, https://git.eeqj.de/sneak/sfdupes/issues/54)
|
||||
|
||||
- the `Dockerfile` build stage keeps the Go module cache out of `builder`'s home
|
||||
and copies the sources with `--chown`, so no `chown -R` walks them
|
||||
(2026-10-04, https://git.eeqj.de/sneak/sfdupes/issues/43)
|
||||
- the `Dockerfile` build stage kept the Go module cache out of `builder`'s home
|
||||
and copied the sources with `--chown`, so no `chown -R` walked them
|
||||
(2026-10-04, https://git.eeqj.de/sneak/sfdupes/issues/43). Since
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/95 there is no `builder` user and
|
||||
nothing changes owner: the build stage only compiles, as root, and the tests
|
||||
run as `nobody` in the `test` phase
|
||||
|
||||
- `--version` prints `sfdupes VERSION` to stdout; README documents it and
|
||||
`--help` (2026-10-04, https://git.eeqj.de/sneak/sfdupes/issues/15)
|
||||
@@ -172,32 +192,28 @@
|
||||
`ENV PATH=/home/builder/go/bin:$PATH` went with its `go install`.
|
||||
`script/verify-linter-pin` is retired; `script/verify-lint-image-pin`, a gate
|
||||
in both files, compares their two `FROM` lines and restates neither pin.
|
||||
Traps: an unchanged tree lets a lint build pass in under a second having run
|
||||
no linter, so every gate `RUN` references `ARG CHECK_EPOCH` (BuildKit hashes
|
||||
the expanded command) and `script/lint` passes `"$(date +%s)-$$"`, the PID
|
||||
because two runs land in the same second easily. Nothing inside an image build
|
||||
may shell out to docker, so the `Dockerfile` lint stage calls `golangci-lint`
|
||||
directly and the build stage runs `make test` and `make fmt-check` instead of
|
||||
`make check`, through `make` because the Makefile's `export CGO_ENABLED = 0`
|
||||
only reaches what it invokes. `COPY --from=lint /src/go.sum /dev/null`
|
||||
replaces the copied linter binary as the only edge making the build stage wait
|
||||
for lint; dropping it would end fail-fast linting under a still-green build.
|
||||
`golangci-lint config verify`, included per the ruling, validates from an
|
||||
embedded schema with no network call, but `go mod download` above the gates
|
||||
still needs the network on a cold cache. Verified: `make lint` green with no
|
||||
`golangci-lint` on `PATH`; two back-to-back `script/lint` runs on an untouched
|
||||
tree both ran the linter (27.7s and 28.7s in the lint step, `COPY . .`
|
||||
`CACHED` above); a planted unused variable failed `script/lint`, and failed
|
||||
`make docker` at `[lint 9/9]` with the build stage stopped at
|
||||
`[builder 3/12]`; the drift guard fails on a tag-only, a digest-only and an
|
||||
unreadable reference, naming both sides; under `--network none` config verify
|
||||
passes a valid config and rejects an invalid one; `make docker` green in 5m35s
|
||||
with all six gates run under one epoch (lint 37.6s, test 25.2s reporting
|
||||
`ok sneak.berlin/go/sfdupes 1.938s coverage: 88.5%`, not `(cached)`); in the
|
||||
builder image with the Go test cache off, `--user 0:0` still fails
|
||||
`TestScanHardlinkRunFailsTogether` where the unprivileged user passes. Noted
|
||||
for follow-up, not fixed here: `golangci-lint` warns that `gomodguard` is
|
||||
deprecated since v2.12.0 in favour of `gomodguard_v2`.
|
||||
Traps: nothing inside an image build may shell out to docker, so the
|
||||
`Dockerfile` lint stage calls `golangci-lint` directly and the build stage
|
||||
runs `make test` and `make fmt-check` instead of `make check`, through `make`
|
||||
because the Makefile's `export CGO_ENABLED = 0` only reaches what it invokes.
|
||||
`COPY --from=lint /src/go.sum /dev/null` replaces the copied linter binary as
|
||||
the only edge making the build stage wait for lint; dropping it would end
|
||||
fail-fast linting under a still-green build. `golangci-lint config verify`,
|
||||
included per the ruling, validates from an embedded schema with no network
|
||||
call, but `go mod download` above the gates still needs the network on a cold
|
||||
cache. Verified: `make lint` green with no `golangci-lint` on `PATH`; two
|
||||
back-to-back `script/lint` runs on an untouched tree both ran the linter
|
||||
(27.7s and 28.7s in the lint step, `COPY . .` `CACHED` above); a planted
|
||||
unused variable failed `script/lint`, and failed `make docker` at `[lint 9/9]`
|
||||
with the build stage stopped at `[builder 3/12]`; the drift guard fails on a
|
||||
tag-only, a digest-only and an unreadable reference, naming both sides; under
|
||||
`--network none` config verify passes a valid config and rejects an invalid
|
||||
one; `make docker` green in 5m35s with all six gates run (lint 37.6s, test
|
||||
25.2s reporting `ok sneak.berlin/go/sfdupes 1.938s coverage: 88.5%`, not
|
||||
`(cached)`); in the builder image with the Go test cache off, `--user 0:0`
|
||||
still fails `TestScanHardlinkRunFailsTogether` where the unprivileged user
|
||||
passes. Noted for follow-up, not fixed here: `golangci-lint` warns that
|
||||
`gomodguard` is deprecated since v2.12.0 in favour of `gomodguard_v2`.
|
||||
|
||||
- install the Docker build stage's prerequisites by running `script/bootstrap`
|
||||
instead of `apk add --no-cache make` inline (2026-08-09, branch
|
||||
@@ -210,43 +226,32 @@
|
||||
`script/verify-linter-pin`, run in the build stage before bootstrap, fails the
|
||||
build naming both versions unless that copied binary is the version
|
||||
`script/bootstrap` pins; a pin it cannot read is a hard failure, not a skip.
|
||||
`$GOPATH/bin` joins `PATH`, where bootstrap's `go install` lands. Everything
|
||||
added sits above `ARG CHECK_EPOCH`, and the `chown` and `USER builder` still
|
||||
precede `make check`. Verified: the guard fails the build with both versions
|
||||
named when the lint stage's linter is faked to another version, and passes an
|
||||
unmodified build; bootstrap runs clean under Alpine's `sh` and `apk`, finding
|
||||
the copied linter already at the pin; a second build served the bootstrap and
|
||||
dependency layers `CACHED` while both gates ran with a fresh epoch; a planted
|
||||
`unused` finding failed the build at the lint gate in 48.9s with the build
|
||||
stage's `make check` never starting; and the suite run in the image as
|
||||
`--user 0:0` fails `TestScanHardlinkRunFailsTogether`, so the drop to the
|
||||
unprivileged user is still needed. That last check needs the Go test cache
|
||||
off: as root it first reported `ok ... (cached)`, reusing the build-time
|
||||
result. Build times on a noisy shared host: 2m13s on an unchanged tree, 2m17s
|
||||
and 4m29s after a source change, 5m14s cold, which breaches the policy
|
||||
ceiling; `chown -R builder:builder /src /home/builder` walks the module cache
|
||||
and alone varied from 77s to 210s across those builds, and `main` measured
|
||||
5m03s cold with a 209s `chown`. Filed as
|
||||
`$GOPATH/bin` joins `PATH`, where bootstrap's `go install` lands. The `chown`
|
||||
and `USER builder` still precede `make check`. Verified: the guard fails the
|
||||
build with both versions named when the lint stage's linter is faked to
|
||||
another version, and passes an unmodified build; bootstrap runs clean under
|
||||
Alpine's `sh` and `apk`, finding the copied linter already at the pin; a
|
||||
second build served the bootstrap and dependency layers `CACHED` while both
|
||||
gates ran; a planted `unused` finding failed the build at the lint gate in
|
||||
48.9s with the build stage's `make check` never starting; and the suite run in
|
||||
the image as `--user 0:0` fails `TestScanHardlinkRunFailsTogether`, so the
|
||||
drop to the unprivileged user is still needed. That last check needs the Go
|
||||
test cache off: as root it first reported `ok ... (cached)`, reusing the
|
||||
build-time result. Build times on a noisy shared host: 2m13s on an unchanged
|
||||
tree, 2m17s and 4m29s after a source change, 5m14s cold, which breaches the
|
||||
policy ceiling; `chown -R builder:builder /src /home/builder` walks the module
|
||||
cache and alone varied from 77s to 210s across those builds, and `main`
|
||||
measured 5m03s cold with a 209s `chown`. Filed as
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/43
|
||||
- bust the Docker layer cache for the gate steps, so `script/cibuild` and
|
||||
`script/docker` cannot report a green they did not earn (2026-08-09, branch
|
||||
`cibuild-cache-bust`, closes https://git.eeqj.de/sneak/sfdupes/issues/32): the
|
||||
`Dockerfile` copies the tree before its gates, so on an unchanged tree Docker
|
||||
served them from cache and the build exited 0 having run nothing. Both scripts
|
||||
now pass `--build-arg CHECK_EPOCH="$(date +%s)"`. `ARG` is per stage and the
|
||||
gates span two stages, so it is declared in both; BuildKit hashes the expanded
|
||||
command, so each gate `RUN` echoes the epoch, which also logs it as evidence
|
||||
the layer ran. It sits below the dependency layers so they stay cached.
|
||||
Verified under `BUILDKIT_PROGRESS=plain`, each script run twice back to back
|
||||
on an unchanged tree: all three gates ran on all four runs with a fresh epoch
|
||||
(`script/cibuild` 78.8s then 61.1s; `script/docker` 61.1s then 53.4s), and
|
||||
thirteen steps were still served `CACHED`. With a planted `unused` finding the
|
||||
build failed at `make lint` in 36.1s and the build-stage `make check` never
|
||||
started. Run as root, the same image fails `TestScanHardlinkRunFailsTogether`,
|
||||
because root reads through the `chmod(0)` the test relies on, so the build
|
||||
stage must drop to the unprivileged `builder` user. Local fix only;
|
||||
propagating it to the canonical templates is
|
||||
https://git.eeqj.de/sneak/prompts/issues/26
|
||||
served them from cache and the build exited 0 having run nothing. Every
|
||||
`docker build` in `script/` now passes `--no-cache` instead
|
||||
(https://git.eeqj.de/sneak/sfdupes/issues/95). Run as root, the tests fail
|
||||
`TestScanHardlinkRunFailsTogether`, because root reads through the `chmod(0)`
|
||||
the test relies on, so they run as an unprivileged user
|
||||
- check the installed golangci-lint version in `script/bootstrap` instead of
|
||||
only its presence (2026-08-09, branch `bootstrap-version-check`, closes
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/24): the version lives only in
|
||||
@@ -402,6 +407,3 @@ Accepted divergences (no action):
|
||||
|
||||
- flat single-package layout with `.go` files in the repo root — fine for a
|
||||
small single-binary tool per the Go styleguide; the tracker audit agrees
|
||||
- `make test` runs without `-race` — the repo mandates `CGO_ENABLED=0` (pure-Go
|
||||
builds) and the race detector requires cgo, so the detector runs in a separate
|
||||
cgo-enabled container, `make test-race`, which is not part of `make check`
|
||||
|
||||
Reference in New Issue
Block a user