Adopt the scripts-to-rule-them-all layout and the canonical Docker gates
check / check (push) Successful in 1m3s

script/ holds the entrypoints and the Makefile targets shim to them.
Linting and testing are phases of the Dockerfile, built alone by
script/lint and script/test with a fresh CACHEBUST value and cache
mounts for Go's build cache and golangci-lint's; the build stage
depends on both, and the runtime stage ships the binary and the source
without .git. Formatting stays on the host in script/fmt and
script/fmt-check (gofmt and the prettier pinned in yarn.lock).
script/cibuild bootstraps, runs script/check and builds the tagged
image, and the Gitea workflow calls it. script/precommit refuses a
commit whose go.mod or go.sum is not tidy.

cgo stays off, so the test phase runs on the alpine Go image without
-race; that is the one departure from the canonical Go Dockerfile.

Re-vendored from the prompts repository's next branch: REPO_POLICIES.md
(2026-11-04), .golangci.yml (byte-identical, so the local
exhaustruct_v5 addition is gone now that canonical carries it),
.gitea/workflows/check.yml, .editorconfig, .gitignore and .dockerignore,
the last two followed by this repository's own entries. AGENTS.md holds
the repository-specific guidance for agents. The README gains the
Entrypoints section and describes the new gates.
This commit is contained in:
2026-11-04 07:31:59 -08:00
parent 538eca9f5d
commit 7feb212d04
22 changed files with 1492 additions and 447 deletions
+57 -21
View File
@@ -217,38 +217,74 @@ added because a tool is wanted, not because a package exists.
### Build, test, and CI
The `Makefile` is the single entry point: `make test` (30-second timeout, quiet
unless something fails), `make lint`, `make fmt` and `make fmt-check` (gofmt for
Go, prettier for markdown), `make check` for all three, `make build`,
`make install`, `make docker`, `make hooks`, `make tidy`, and `make setup` to
install the pinned prettier.
The gates live in the `Dockerfile`, in the canonical Go layout that
`REPO_POLICIES.md` prescribes: a `lint` phase on the hash-pinned golangci-lint
image and a `test` phase on the Go image. `script/lint` and `script/test` each
build one phase alone, with a fresh `CACHEBUST` value so the check step runs on
every build instead of being served from Docker's cache, and write no image. The
build stage depends on both phases, so the image cannot be built unless they
pass. Go's build cache and golangci-lint's cache are mounted into the phases and
survive between builds. Formatting is the one check that runs on the host:
`script/fmt-check` runs gofmt and the prettier pinned in `yarn.lock`.
`script/check` runs all three. `script/cibuild`, which the Gitea workflow calls,
bootstraps, runs `script/check`, and then builds the tagged image with the
version from `git describe`.
`make lint` runs golangci-lint inside the same hash-pinned Docker image the CI
build uses, so local results match CI exactly, and first verifies
`.golangci.yml` against the linter's schema, because golangci-lint otherwise
ignores keys it does not know and silently runs with defaults. The `Dockerfile`
splits `make check` across stages: a lint stage and a markdown-check stage fail
fast in seconds, and the build stage, which runs the tests and compiles `sutil`,
depends on both. The runtime image carries the binary and the source it was
built from. Every external reference, from base images to the GitHub Action in
Every external reference, from base images to the GitHub Action in
`.gitea/workflows/check.yml`, is pinned by content hash with a version and date
comment. `.golangci.yml` is this repo's copy of the standard configuration, kept
in the v2 layout with `exhaustruct_v5` and the deprecated `gomodguard` disabled.
cgo stays off: the Makefile exports `CGO_ENABLED=0` for every build and test, so
binaries are static and no C toolchain is needed anywhere.
comment. `.golangci.yml` is byte-identical to the canonical copy in the
`prompts` repository and is never edited here; the lint phase pins the
golangci-lint release that the policy names. cgo stays off: the Makefile exports
`CGO_ENABLED=0`, binaries are static, and the test phase runs on the alpine Go
image without `-race`, which is this repository's one departure from the
canonical `Dockerfile`. The runtime image carries the binary and the source it
was built from.
Version tags are created by the author alone, when the author decides. Tooling,
contributors, and agents working in this repository do not propose, schedule, or
create tags.
## Entrypoints
This repository adheres to the
[Scripts to Rule Them All](https://github.com/github/scripts-to-rule-them-all)
standard: normalized scripts in `script/` are the entrypoints for the
development workflow, and the Makefile targets are thin shims that call them. We
provide:
- `script/bootstrap`: install everything the repository needs, idempotently:
make, git, go, and, because `yarn.lock` is present, node, yarn 1 and the
pinned prettier.
- `script/setup`: make a fresh clone ready for development by running
`script/bootstrap` and then `script/install-precommit`.
- `script/projectname`: print the project name, `x`, which `script/docker` and
`script/cibuild` use as the image tag.
- `script/test`: build the `test` phase of the `Dockerfile` with a new
`CACHEBUST` value, writing no image.
- `script/lint`: build the `lint` phase the same way.
- `script/fmt`: gofmt and prettier, writing files.
- `script/fmt-check`: the read-only twin of `script/fmt`.
- `script/check`: `script/test`, `script/lint`, then `script/fmt-check`. It
modifies nothing.
- `script/docker`: build the image tagged `x`, passing the version from
`git describe`.
- `script/cibuild`: what CI runs: `script/bootstrap`, `script/check`, then the
tagged image build.
- `script/precommit`: run by the pre-commit hook. It refuses a commit whose
`go.mod` or `go.sum` is not tidy, then runs `script/check`.
- `script/install-precommit`: install that hook; `make hooks` shims to it.
The Makefile adds four targets of its own: `make build`, `make install`,
`make tidy`, and `make clean`.
## Development
```sh
make setup # once: install the pinned prettier with yarn
make check # test + lint + fmt-check, exactly what CI gates on
make setup # once: bootstrap and install the pre-commit hook
make check # test, lint, fmt-check: what the hook and CI run
make fmt # gofmt and prettier, writes files
make hooks # install the pre-commit hook that runs make check
make docker # the full CI build
make build # build ./sutil on the host
make docker # build the image tagged x
```
## TODO