build: re-vendor canonical files from prompts dd4027b (closes #257)
check / check (push) Canceled after 0s

The canonical files are fetched whole from sneak/prompts at dd4027b.
Kept after the canonical content: the livednstest deny entry in
.golangci.yml, /bin in .dockerignore, and this repo's own .gitignore
lines. The workflow keeps its concurrency block and
persist-credentials: false. Lint and test are phases of the Dockerfile
(golangci-lint v2.14.0; tests on the Debian Go 1.25.7 image with the
same flags); the build stage depends on both and stamps the version the
canonical way. Dockerfile.lint is gone; the prettier stages of
Dockerfile.fmt moved into the Dockerfile, so Markdown formatting still
runs in Docker. Every scripted docker build passes --no-cache;
script/cibuild bootstraps, runs script/check, then builds the image.
script/fmt-check absorbs fmt-check-go and fmt-check-markdown.

Model: opus-5-5
This commit is contained in:
2026-10-06 01:03:55 +00:00
parent d1060315b7
commit 9fb70396e9
22 changed files with 689 additions and 434 deletions
+33 -40
View File
@@ -656,48 +656,42 @@ provide:
- `script/setup` — make a fresh clone ready for development: bootstrap plus the
git pre-commit hook
- `script/projectname` — print the project name (used for the Docker image tag)
- `script/test` — run the test suite (race detector, coverage). Caching is
waived for testing, exactly as it is for linting: `-count=1` forces every
invocation to execute, because the suite queries live DNS and a cached pass
queries nothing. Failures are rerun with `-v` automatically, and the build
- `script/test` — run the test suite (race detector, coverage) by building the
`Dockerfile`'s test phase, which queries live DNS. `-count=1` keeps Go's test
result cache out. Failures are rerun with `-v` automatically, and the build
fails even if that rerun passes.
- `script/lint` — run golangci-lint, always inside Docker: it builds
`Dockerfile.lint`, which COPYs the repo into the digest-pinned `golangci-lint`
image and lints as a build step, so a successful build is a clean lint. The
linter is never installed or run on the host, and Docker is the only
prerequisite. Caching is waived for linting: the lint stage is forced to
execute on every run with `--no-cache-filter`, because a cached build lints
nothing.
- `script/lint` — run golangci-lint by building the `Dockerfile`'s lint phase,
on the digest-pinned `golangci-lint` image, so a successful build is a clean
lint. The linter is never installed or run on the host, and Docker is the only
prerequisite.
- `script/fmt` — format all code (gofmt -s, goimports) and all Markdown
(prettier). goimports runs with `go run` at a pinned commit, never from your
`PATH`. prettier runs inside Docker, built from `Dockerfile.fmt` on a
`PATH`. prettier runs inside Docker, in a stage of the `Dockerfile` on a
digest-pinned node image, at the version pinned by `package.json` and
`yarn.lock`; it is never installed on the host.
- `script/fmt-check` — check formatting (read-only) with the same tools, failing
on any file `script/fmt` would change. It runs the two scripts below.
- `script/fmt-check-go` — the gofmt and goimports half, on the host. The
`Dockerfile` lint stage runs it.
- `script/fmt-check-markdown` — the prettier half, inside Docker, forced to
execute on every run with `--no-cache-filter`
on any file `script/fmt` would change: gofmt and goimports on the host,
prettier inside Docker
- `script/check` — run test, lint, and fmt-check
- `script/docker` — build the Docker image tagged via `script/projectname`, with
`--no-cache-filter=lint,builder` so the lint stage and the builder stage,
which runs the tests, run on every invocation, and with the version from
`git describe` passed as `--build-arg VERSION`
- `script/cibuild` — CI entrypoint: `docker build` with
`--no-cache-filter=lint,builder`, so the lint stage and the builder stage,
which runs the tests, run on every invocation, because a cached build lints
nothing and queries no DNS; then `script/fmt-check-markdown`
the version from `git describe` passed as `--build-arg VERSION`
- `script/cibuild` — CI entrypoint: `script/bootstrap`, then `script/check`,
then the image build `script/docker` does, which runs the lint and test phases
again
- `script/precommit` — run by the git pre-commit hook; `go mod tidy` guard, then
`script/check`
- `script/install-precommit` — install the git pre-commit hook
Linting and testing are phases of the `Dockerfile`, and the image is built only
when both pass. Every `docker build` in `script/` passes `--no-cache`, because a
cached build lints nothing and queries no DNS.
## Building
```sh
make build # Build binary to bin/dnswatcher
make version # Print the version make build stamps
make test # Run tests with race detector
make test # Run tests with race detector in Docker (requires docker)
make lint # Run golangci-lint in Docker (requires docker)
make fmt # Format code and Markdown (requires docker)
make check # Run all checks (test, lint, fmt-check)
@@ -712,21 +706,20 @@ the environment, otherwise from `git describe --tags --always --dirty`, and
`dev` without git metadata. An empty `VERSION` counts as not given. The version
appears in the startup log and in the health check response.
The image takes it the same way, from the `.git` the build context carries, so a
plain `docker build .` of a clone stamps the commit it was built from; a clone
without tags stamps the short commit. A clone made with `--depth 1` carries at
most a tag on its own commit, so such a clone of an untagged commit stamps the
short commit. In a build from a directory, `.dockerignore` keeps out
`.git/config`, which `git describe` does not need and which can hold a
credential. Docker does not apply `.dockerignore` to a context sent as a tar
archive, as upaas sends it, so that context carries `.git/config` into the
build. It also keeps its files' owners, so git in the build trusts the checkout
whoever owns it. A non-empty `--build-arg VERSION=...` takes precedence;
`make docker` passes the version `git describe` gives on the host. The build
fails when the context carries `.git`, as a directory or as a file, and the
version comes out empty, `dev` or `unknown`. `.dockerignore` must list no
tracked file: git in the build would see it as deleted and mark the version
`-dirty`.
The image takes it from `git describe --tags --always` on the `.git` the build
context carries, so a plain `docker build .` of a clone stamps the commit it was
built from; a clone without tags stamps the short commit. A clone made with
`--depth 1` carries at most a tag on its own commit, so such a clone of an
untagged commit stamps the short commit. In a build from a directory,
`.dockerignore` keeps out `.git/config` and every submodule's git config, which
`git describe` does not need and which can hold a credential. Docker does not
apply `.dockerignore` to a context sent as a tar archive, as upaas sends it, so
that context carries `.git/config` into the build. It also keeps its files'
owners, so git in the build trusts the checkout whoever owns it. A non-empty
`--build-arg VERSION=...` takes precedence; `make docker` passes the version
`git describe` gives on the host. The build fails when the context carries
`.git`, as a directory or as a file, and the version comes out empty, `dev` or
`unknown`.
---