Re-sync script/docker and script/cibuild with the model scripts (closes #265)
check / check (push) Failing after 2s

script/docker and script/cibuild are again byte-identical to the shared model
scripts. Both compute the version on the host with git describe, pass it as the
VERSION build arg and build with --no-cache; script/cibuild runs
script/bootstrap and script/check first. The CI build now stamps a real version
instead of unknown.

make build compiles with -trimpath and -s -w, as the model Dockerfile does.
script/version stays: the Makefile and the Dockerfile still use it.

The README describes both scripts as they now are.

Model: opus-5-5
This commit is contained in:
2026-10-05 23:28:36 +00:00
parent 46fe7baed0
commit ea40b31e50
4 changed files with 62 additions and 29 deletions
+4 -1
View File
@@ -48,8 +48,11 @@ fmt-check:
check: check:
@script/check @script/check
# -trimpath keeps the build directory out of the binary, so two builds of one
# commit match wherever they ran; -s -w drop the symbol table and debug info,
# which panics and stack traces do not use.
build: assets build: assets
go build -ldflags '$(strip -X main.version=$(VERSION) $(GO_LDFLAGS))' -o bin/webhooker ./cmd/webhooker go build -trimpath -ldflags '$(strip -s -w -X main.version=$(VERSION) $(GO_LDFLAGS))' -o bin/webhooker ./cmd/webhooker
run: build run: build
./bin/webhooker ./bin/webhooker
+26 -15
View File
@@ -1095,7 +1095,8 @@ field), in the UI footer, and in the startup log line (`msg=starting`,
The value is stamped in at build time by the linker; it is not read from a file The value is stamped in at build time by the linker; it is not read from a file
at runtime, so it identifies the build itself. at runtime, so it identifies the build itself.
`script/version` produces the value and both build paths use it: `script/version` produces the value for `make build`, from
`git describe --tags --always --dirty`:
| Build | What it reports | | Build | What it reports |
| ----------------------- | --------------------------------------------------- | | ----------------------- | --------------------------------------------------- |
@@ -1118,7 +1119,8 @@ https://git.eeqj.de/sneak/upaas/issues/274. git in the build reads the checkout
whoever owns its files, since a context sent as a tar archive keeps the sender's whoever owns its files, since a context sent as a tar archive keeps the sender's
owners and git otherwise refuses a checkout owned by another user. A `VERSION` owners and git otherwise refuses a checkout owned by another user. A `VERSION`
build arg (`--build-arg VERSION=...`) takes precedence; `script/docker` (and so build arg (`--build-arg VERSION=...`) takes precedence; `script/docker` (and so
`make docker`) passes the one `script/version` resolves on the host. The image `make docker`) and `script/cibuild` always pass one, from the same
`git describe` run on the host, or `unknown` when that gives nothing. The image
build fails if its context carries `.git` and the version still comes out build fails if its context carries `.git` and the version still comes out
`unknown`, which means git is missing from the build or could not read the `unknown`, which means git is missing from the build or could not read the
checkout. checkout.
@@ -1134,8 +1136,9 @@ to a commit.
`""`, and resolves the way an absent one does. `""`, and resolves the way an absent one does.
Nothing that varies between two builds of the same commit is stamped — no Nothing that varies between two builds of the same commit is stamped — no
timestamp, no hostname, no builder identity — so two builds of one commit still timestamp, no hostname, no builder identity — and `make build` compiles with
produce a byte-identical binary. `-trimpath`, which keeps the build directory out of the binary, so two builds of
one commit still produce a byte-identical binary wherever they ran.
### Backups contain secrets ### Backups contain secrets
@@ -1240,10 +1243,13 @@ We provide:
- `script/check` — run test, lint, fmt-check, and css-check - `script/check` — run test, lint, fmt-check, and css-check
- `script/version` — output the version to stamp into the binary (see - `script/version` — output the version to stamp into the binary (see
[Version stamping](#version-stamping)) [Version stamping](#version-stamping))
- `script/docker` — build the Docker image tagged via `script/projectname`, - `script/docker` — build the Docker image tagged via `script/projectname`, with
passing `script/version`'s output in as the `VERSION` build arg `--no-cache` so no check is replayed from cache, passing the version
- `script/cibuild` — CI entrypoint: `docker build .` (the Dockerfile runs the `git describe --tags --always --dirty` gives on the host (`unknown` if none)
checks, so a green build implies a green repo) in as the `VERSION` build arg
- `script/cibuild` — CI entrypoint: run `script/bootstrap` and `script/check` on
the host, then build the image exactly as `script/docker` does (the Dockerfile
runs the checks again, so a green build implies a green repo)
- `script/ci-mark-superseded` — CI helper: mark the commits whose run a newer - `script/ci-mark-superseded` — CI helper: mark the commits whose run a newer
push cancelled (see [CI gate honesty](#ci-gate-honesty)) push cancelled (see [CI gate honesty](#ci-gate-honesty))
- `script/precommit` — pre-commit checks (`go mod tidy` guard, then - `script/precommit` — pre-commit checks (`go mod tidy` guard, then
@@ -1251,6 +1257,11 @@ We provide:
- `script/install-precommit` — install the git pre-commit hook that runs - `script/install-precommit` — install the git pre-commit hook that runs
`script/precommit` `script/precommit`
`script/docker` and `script/cibuild` are byte-identical copies of the shared
model scripts at
`https://git.eeqj.de/sneak/prompts/raw/branch/main/script/<name>`. A change to
either is made there and copied here, never made here alone.
## Third-party browser assets ## Third-party browser assets
The web UI serves one third-party script, Alpine.js, in its CSP build: the npm The web UI serves one third-party script, Alpine.js, in its CSP build: the npm
@@ -3439,13 +3450,13 @@ The lint and builder stages use Debian rather than Alpine because
not compile against musl. Only the final binary is statically linked, which is not compile against musl. Only the final binary is statically linked, which is
what lets it run on the Alpine runtime image. what lets it run on the Alpine runtime image.
`script/cibuild` — `docker build .` — is the CI gate: the checks run inside the `script/cibuild` is the CI gate: it runs `script/check`, then builds the image
image, so a build that succeeds is a repo that is formatted, linted, tested and with `--no-cache`, and the checks run again inside the image, so a build that
compiled, with a current stylesheet. `script/lint` also uses Docker succeeds is a repo that is formatted, linted, tested and compiled, with a
(`Dockerfile.lint` and the `js-lint` stage, see Linting above), so `make lint` current stylesheet. `script/lint` also uses Docker (`Dockerfile.lint` and the
and `make check` run the same pinned linter versions the gate does; of the steps `js-lint` stage, see Linting above), so `make lint` and `make check` run the
`make check` runs, only `script/test` and the `gofmt` check in same pinned linter versions the gate does; of the steps `make check` runs, only
`script/fmt-check` run on the host. `script/test` and the `gofmt` check in `script/fmt-check` run on the host.
#### CI gate honesty #### CI gate honesty
+20 -6
View File
@@ -1,15 +1,29 @@
#!/bin/sh #!/bin/sh
# script/cibuild: run the CI build. The Dockerfile runs the checks (the # script/cibuild: run the CI build. It bootstraps first: a CI runner
# gofmt check, golangci-lint, the stylesheet check, ESLint, the Markdown # checks out and runs this and nothing else, and script/fmt-check runs
# check, make test), so a successful build implies a green repo. Generic: # the formatter on the host, which a pristine checkout cannot do.
# needs no adaptation. The Gitea workflow runs this on push. # --no-cache for the same reason as script/docker: the gate phases the
# final stage depends on are RUN steps, and a cached one is a check that
# did not run.
set -eu set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
main() { main() {
cd "$ROOT" cd "$ROOT"
docker build . "$SCRIPT_DIR/bootstrap"
"$SCRIPT_DIR/check"
# Own line: a failing command substitution inside an argument does
# not trip `set -e`, so the inline form degrades silently to an
# empty constant. VERSION is computed here because .dockerignore
# excludes .git, so `git describe` in a build stage yields an empty
# version without failing.
version="$(git describe --tags --always --dirty 2>/dev/null || true)"
[ -n "$version" ] || version="unknown"
docker build --no-cache \
--build-arg VERSION="$version" \
-t "$("$SCRIPT_DIR/projectname")" .
} }
main "$@" main "$@"
+12 -7
View File
@@ -1,10 +1,8 @@
#!/bin/sh #!/bin/sh
# script/docker: build the Docker image tagged with the project name. # script/docker: build the Docker image tagged with the project name.
# The tag comes from script/projectname. # Identical in all repos; the tag comes from script/projectname.
# # --no-cache because the gate phases the final stage depends on are RUN
# The version script/version resolves here goes in as the VERSION build # steps, and a cached one is a check that did not run.
# arg, which takes precedence over what the build would derive from the
# .git in its context.
set -eu set -eu
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
@@ -12,8 +10,15 @@ ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
main() { main() {
cd "$ROOT" cd "$ROOT"
docker build \ # Own line: a failing command substitution inside an argument does
--build-arg VERSION="$("$SCRIPT_DIR/version")" \ # not trip `set -e`, so the inline form degrades silently to an
# empty constant. VERSION is computed here because .dockerignore
# excludes .git, so `git describe` in a build stage yields an empty
# version without failing.
version="$(git describe --tags --always --dirty 2>/dev/null || true)"
[ -n "$version" ] || version="unknown"
docker build --no-cache \
--build-arg VERSION="$version" \
-t "$("$SCRIPT_DIR/projectname")" . -t "$("$SCRIPT_DIR/projectname")" .
} }