Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2acb657a44 |
@@ -46,9 +46,8 @@
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/12)
|
||||
|
||||
- cut the narration from `TODO.md` Completed Steps and from the comments in
|
||||
`script/`, `Dockerfile` and `Dockerfile.lint` (gone since
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/95); §Workflow now branches from and
|
||||
merges to `next` (2026-10-04, https://git.eeqj.de/sneak/sfdupes/issues/49)
|
||||
`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` ran the test suite under the race detector in a cgo-enabled
|
||||
container, outside `make check` (2026-10-04,
|
||||
@@ -177,45 +176,82 @@
|
||||
|
||||
- fix the lint-image pin comments and `FROM` form in `Dockerfile` and
|
||||
`Dockerfile.lint` (2026-08-10, branch `next`, closes
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/25): both pins became the policy
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/25): both pins are now the policy
|
||||
`# image:vX.Y.Z, YYYY-MM-DD` comment over a bare `FROM image@sha256:...`,
|
||||
without the false `(Debian-based)` note or the tag. Since
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/95 the `Dockerfile`'s `lint` phase
|
||||
holds the only golangci-lint pin, in that form, so `Dockerfile.lint` and
|
||||
`script/verify-lint-image-pin`, which compared the two pins, are gone.
|
||||
without the false `(Debian-based)` note or the tag; digest unchanged.
|
||||
`script/verify-lint-image-pin` still matches the tagless form, and a tag on
|
||||
one side only is caught as a plain mismatch.
|
||||
|
||||
- run all linting in Docker via `Dockerfile.lint` and `script/lint` (2026-08-10,
|
||||
branch `next`, closes https://git.eeqj.de/sneak/sfdupes/issues/46): per the
|
||||
owner ruling the linter is never installed on a host, and
|
||||
`golangci-lint config verify` runs before `golangci-lint run`.
|
||||
`script/bootstrap` stopped installing or pinning the linter, and
|
||||
`script/verify-linter-pin` was retired. Since
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/95 both commands run in the
|
||||
`Dockerfile`'s `lint` phase, which `script/lint` builds alone and the build
|
||||
stage depends on through `COPY --from=lint /src/go.sum /dev/null`;
|
||||
`Dockerfile.lint` and `script/verify-lint-image-pin` are gone. Nothing inside
|
||||
an image build may run docker, so the phase calls `golangci-lint` directly.
|
||||
owner ruling the linter is never installed on a host. `Dockerfile.lint` copies
|
||||
the repo into the digest-pinned `golangci/golangci-lint:v2.12.2` image and
|
||||
runs `golangci-lint config verify` and `golangci-lint run` as build steps;
|
||||
`script/lint` builds it. `script/bootstrap` no longer installs or pins the
|
||||
linter, and warns rather than fails when `docker` is absent;
|
||||
`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: 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
|
||||
`dockerfile-bootstrap`, closes https://git.eeqj.de/sneak/sfdupes/issues/42),
|
||||
with `script/verify-linter-pin` failing the build unless the linter copied
|
||||
from the lint stage was the version `script/bootstrap` pinned. Builds then
|
||||
took up to 5m14s cold, mostly in a `chown -R` of the module cache, filed as
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/43. Since
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/95 the build stage installs `git` and
|
||||
`make` with `apk add --no-cache` and only compiles; the `lint` and `test`
|
||||
phases are the gates
|
||||
`dockerfile-bootstrap`, closes https://git.eeqj.de/sneak/sfdupes/issues/42):
|
||||
the stage copies `script/` plus `go.mod`/`go.sum` and runs `script/bootstrap`,
|
||||
which ends in `go mod download`, so the separate call to it is gone.
|
||||
`COPY --from=lint /usr/bin/golangci-lint` stays and moves above the bootstrap
|
||||
layer: it is the only edge making this stage depend on the lint stage, so
|
||||
deleting it would end fail-fast linting silently. A new
|
||||
`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. 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. The fix was
|
||||
a `CHECK_EPOCH` build argument; since
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/95 every `docker build` in `script/`
|
||||
passes `--no-cache` instead. Run as root, the tests fail
|
||||
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 the `test` phase runs them as `nobody`
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user