All checks were successful
check / check (push) Successful in 9s
script/lint runs the linter directly when it is already inside a container and otherwise builds Dockerfile.lint, so the linter never runs on a developer host. That closes three host-only mechanisms: the result cache golangci-lint keys on file content rather than location, which produced a confirmed false green and findings reported against other checkouts; the host-global $TMPDIR/golangci-lint.lock, which fails a run in a way no caller can distinguish from findings; and host/container version skew, which hid thirteen findings on one repo. Detection is on LINT_IN_CONTAINER=1, set by every Dockerfile, and on nothing else. The two directions are not symmetric: a false negative inside a container attempts a nested docker build, finds no daemon and fails loudly, while a false positive on a host silently lints there, which is the defect this issue exists to kill. /.dockerenv is therefore rejected even as a fallback -- measured absent inside BuildKit RUN steps and present on any host that is itself a container, so it fails in both directions and one of them is the dangerous one. Nothing else changes shape. The Dockerfile still runs make check, script/check still runs test, lint and fmt-check, script/cibuild is still a single docker build with CHECK_EPOCH and VERSION, and the Go multistage lint stage and its COPY --from=lint ordering dependency survive with ENV LINT_IN_CONTAINER=1 added. Dockerfile.lint is the standalone developer-host path and carries the same CHECK_EPOCH guard, with the ARG below the dependency layer so only the lint re-runs. The script/bootstrap golangci-lint install and the per-checkout GOLANGCI_LINT_CACHE/TMPDIR wrapper are deleted as superseded. Neither has a caller left. A JS repo's yarn install stays: the rule is that no lint verdict may come from a host invocation, not that no linter binary may exist there, and in a repo whose formatter is its linter the formatter necessarily runs on the host. golangci-lint config verify is kept, on measurement. Under the pinned v2.12.2 a bogus top-level key and a bogus key under linters.settings.lll both pass `golangci-lint run` with exit 0 and `0 issues` while config verify exits 3 and names them; an unknown linter name fails run and passes config verify. It needs no network: every case reproduced byte-identically under `docker run --network none`, in a container where `getent hosts golangci-lint.run` exits 2. Comment blocks were cut hard across every file this unit touches. .dockerignore drops from 67 comment lines to 28, script/cibuild from 17 to 12, script/docker from 18 to 12, and prompts/REPO_POLICIES.md from 1182 lines to 907. What remains says why a line is load-bearing; the discovery narratives are gone. config verify lives in script/lint's native branch rather than in a Dockerfile, so every path that lints inherits it: the lint stage of the main image, which is what CI runs, as well as Dockerfile.lint. Putting it in one Dockerfile is how the other path silently loses it.
35 lines
1.1 KiB
Bash
Executable File
35 lines
1.1 KiB
Bash
Executable File
#!/bin/sh
|
|
# script/lint: run the linter. Inside a container, run it directly;
|
|
# on a host, build Dockerfile.lint so it runs in one anyway. The linter
|
|
# is never run on a developer host, where a shared result cache, a
|
|
# host-global lock and a stale toolchain make its answer untrustworthy.
|
|
#
|
|
# LINT_IN_CONTAINER is set by this repo's Dockerfiles and is the ONLY
|
|
# accepted signal. Do not add a /.dockerenv fallback: it is absent
|
|
# inside BuildKit RUN steps and present on hosts that are themselves
|
|
# containers, so it both misses and false-positives — and a false
|
|
# positive silently restores host linting.
|
|
set -eu
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
|
|
main() {
|
|
cd "$ROOT"
|
|
|
|
if [ "${LINT_IN_CONTAINER:-}" = "1" ]; then
|
|
exec yarn run prettier --check '**/*.md' \
|
|
--tab-width 4 --prose-wrap always
|
|
fi
|
|
|
|
# Own line, and `$$` because busybox `date` drops %N silently.
|
|
# Without a fresh nonce the lint layer is cached and this exits 0
|
|
# having linted nothing.
|
|
epoch="$(date +%s%N)$$"
|
|
docker build \
|
|
--build-arg CHECK_EPOCH="$epoch" \
|
|
-f Dockerfile.lint \
|
|
.
|
|
}
|
|
|
|
main "$@"
|