5 Commits
Author SHA1 Message Date
clawbot b3508a4361 Fetch history and tags in the canonical workflow (closes #110)
check / check (push) Successful in 24s
The policy said a repository whose version comes from git tags needs `fetch-depth: 0` on its CI checkout, because the checkout action clones shallow with no tags; every repository's version comes from `git describe --tags --always`, but the canonical `.gitea/workflows/check.yml` did not set it, so CI stamped a bare short commit id where a local build of a tagged repository stamps the tag. The checkout step now sets `fetch-depth: 0` with a one-line comment, and the workflow bullet of `prompts/REPO_POLICIES.md` and both checklists name it beside `persist-credentials: false` and the `concurrency` block, as part of what the workflow does.

Unverified: a live run, which waits on the shared runner.

Model: opus-5-5
2026-10-06 08:15:41 +02:00
clawbot 8fe0709414 Refresh apt package lists once in script/bootstrap (closes #115)
check / check (push) Canceled after 0s
`pkg_install` in the canonical `script/bootstrap` ran `apt-get install` with no `apt-get update` before it. The Gitea runner image starts with empty package lists, so a repository's own `pkg_install` of anything the image lacks, Go included, failed with "Unable to locate package". The apt branch now refreshes the lists once, before the first install of a run, in the same `$SUDO env DEBIAN_FRONTEND=noninteractive` form, and skips the refresh on later calls. nix, brew and apk are unchanged. Repositories that refresh in their own section, or changed their copy, drop that at their next re-vendor.

Model: opus-5-5
2026-10-06 07:31:21 +02:00
clawbot 01954b6946 Say that a build from a linked worktree needs the version passed in (closes #111)
check / check (push) Canceled after 0s
A plain `docker build .` from a checkout whose `.git` is a file (a linked worktree, or a repository checked out as a submodule) stops at the version check of the canonical `Dockerfile` example: that file points to a git directory outside the build context, so `git describe` prints nothing. The check is right to refuse an empty version; what was missing is what to do. `prompts/REPO_POLICIES.md` and both checklists now say such a build is given its version with `--build-arg VERSION=...`, as `script/docker` and `script/cibuild` already do. The check itself is unchanged.

Model: opus-5-5
2026-10-06 06:33:19 +02:00
clawbot 6aac45857a Cancel replaced CI runs and drop the checkout token (closes #107)
check / check (push) Canceled after 0s
The canonical `.gitea/workflows/check.yml` lacked two settings `dnswatcher` had added, so a byte-identical re-vendor removed them. A `concurrency` block grouped by workflow and branch, with `cancel-in-progress: true`, makes a new push cancel the older run on the same branch and leaves every other branch's runs alone; on 2026-10-02 45 stale runs had queued on the one shared runner. `persist-credentials: false` on the checkout step keeps the job's token out of `.git/config`; `script/cibuild` needs no token. Each has a one-line comment, and the policy's workflow bullet and both checklists describe the file as it now is.

Unverified: the two live checks, which wait on the shared runner.

Model: opus-5-5
2026-10-06 05:52:57 +02:00
clawbot f5c4bb6e2c Disable canonicalheader in the canonical .golangci.yml (closes #105)
check / check (push) Successful in 28s
In golangci-lint v2.14.0, `canonicalheader` misses findings at random in a package that also calls `ResponseWriter.Header()`: on the same tree, repeated runs sometimes reported a non-canonical header key and sometimes reported nothing. So one commit could fail lint on one run and pass on the next, in every Go repository that vendors this file. Reproduced with the pinned image and the canonical config.

The canonical `.golangci.yml` now disables it, with a comment saying it comes back once a pinned golangci-lint release fixes it. New `.golangci.yml` sha256: `e49052a1418127b54b20cea530dfd3cc6ddfc126a9fd27fd570ccca1a3f18bc7`.

Model: opus-5-5
2026-10-06 05:15:41 +02:00
7 changed files with 96 additions and 12 deletions
+9
View File
@@ -1,9 +1,18 @@
name: check
on: [push]
# Free the shared runner: a new push cancels only the same branch's older run.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check:
runs-on: ubuntu-latest
steps:
# actions/checkout v4.2.2, 2026-02-22
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
# script/cibuild needs no token, so none is left in .git/config.
with:
persist-credentials: false
# All history and tags, so git describe finds the version tag.
fetch-depth: 0
- run: script/cibuild
+2
View File
@@ -25,6 +25,8 @@ linters:
# silenced by disabling that name, not by enabling the successor.
- wsl # Deprecated, replaced by wsl_v5
- gomodguard # Deprecated, replaced by gomodguard_v2
# Misses findings at random in v2.14.0; back once a pinned release fixes it
- canonicalheader
settings:
lll:
line-length: 88
+33
View File
@@ -21,6 +21,39 @@ fmt-check, and commit.
# Completed Steps
- 2026-10-06: The canonical `.gitea/workflows/check.yml` now sets
`fetch-depth: 0` on its checkout step (issue 110), so CI fetches the history
and tags that `git describe --tags --always` needs, and a tagged repository
stamps the same version in CI as in a local build. `REPO_POLICIES.md` and both
checklists name `fetch-depth: 0` among what the workflow does, next to
`persist-credentials: false` and the `concurrency` block, instead of asking
each tagged repository to add it. Not yet tried on the shared runner, which is
out of disk space. Repositories pick this up on their next re-vendor.
- 2026-10-06: The canonical `script/bootstrap` now runs `apt-get update` once,
before the first `apt-get install` of a run (issue 115). The Gitea runner
image starts with empty package lists, so installing anything it lacks, such
as Go, failed with `Unable to locate package`. A repository's own section no
longer needs a refresh of its own; `sneak/bsfirehose` and `sneak/dnswatcher`
drop theirs at their next re-vendor.
- 2026-10-06: `REPO_POLICIES.md` and both checklists now say that a checkout
whose `.git` is a file, a linked worktree or a repository checked out as a
submodule, is the exception to a plain `docker build .` succeeding (issue
111): that file points to a git directory outside the build context, so the
build cannot read the version and the version check in the canonical
`Dockerfile` stops it. Such a build is given its version with
`--build-arg VERSION=...`, as `script/docker` and `script/cibuild` already do.
The check itself is unchanged.
- 2026-10-06: The canonical `.gitea/workflows/check.yml` now has a `concurrency`
block, so a new push cancels the older run on the same branch and no other,
and its checkout step sets `persist-credentials: false`, so the job's token is
not left in `.git/config` (issue 107). `REPO_POLICIES.md` and both checklists
describe the workflow as it now is. Not yet tried on the shared runner, which
is out of disk space. Repositories pick this up on their next re-vendor.
- 2026-10-06: The canonical `.golangci.yml` now disables `canonicalheader`
(issue 105). In golangci-lint v2.14.0 it misses findings at random in a
package that also calls `ResponseWriter.Header()`, so the same tree can fail
lint on one run and pass on the next. It comes back once a pinned
golangci-lint release fixes it.
- 2026-10-06: The canonical `.gitignore` and `.editorconfig` now each end with a
comment saying the repository's own entries go below it and a re-vendor keeps
them (issue 103, which took in issue 104), as `.dockerignore`'s header already
+13 -5
View File
@@ -91,12 +91,20 @@ with your task.
version still comes out empty, `dev` or `unknown`. A plain
`docker build .` with no build arguments must succeed; a Dockerfile that
refuses an empty build argument drops that refusal and keeps the argument.
`script/docker` and `script/cibuild` pass the version they compute on the
host; it takes precedence. A tag-derived version additionally needs
`fetch-depth: 0` on the CI checkout step, which clones shallow and fetches
no tags by default.
A checkout whose `.git` is a file (a linked worktree, or a repository
checked out as a submodule) is the exception: that file points to a git
directory outside the build context, so the build cannot read the version
and a plain `docker build .` fails; pass the version with
`--build-arg VERSION=...`. `script/docker` and `script/cibuild` already
pass the version they compute on the host; it takes precedence. The
canonical `.gitea/workflows/check.yml` sets `fetch-depth: 0` on its
checkout step, which otherwise clones shallow and fetches no tags, so a CI
build finds the tag too.
- [ ] Gitea Actions workflow in `.gitea/workflows/` runs `script/cibuild` on
push — reference
push, checks out with `persist-credentials: false` and with
`fetch-depth: 0` (which fetches the tags `git describe` needs), and
carries the `concurrency` block that lets a new push cancel only the same
branch's older run — reference
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitea/workflows/check.yml`
- [ ] Language-specific config:
- [ ] Go: `go.mod`, `go.sum`, `.golangci.yml` (fetch from
+10 -1
View File
@@ -97,6 +97,12 @@ Template files can be fetched from:
version still comes out empty, `dev` or `unknown`. A plain
`docker build .` with no build arguments must succeed; a Dockerfile that
refuses an empty build argument drops that refusal and keeps the argument.
A checkout whose `.git` is a file (a linked worktree, or a repository
checked out as a submodule) is the exception: that file points to a git
directory outside the build context, so the build cannot read the version
and a plain `docker build .` fails; pass the version with
`--build-arg VERSION=...`, as `script/docker` and `script/cibuild` already
do.
- The Dockerfile carries a `lint` phase and a `test` phase, each invoking
its tool directly rather than through `make` or `script/`, and the final
stage carries a `COPY --from=` of a harmless file from each so the image
@@ -106,7 +112,10 @@ Template files can be fetched from:
- Non-server: the final stage brings up the dev environment
- Image pinned by sha256 hash with version/date comment
- [ ] Gitea Actions workflow at `.gitea/workflows/check.yml` that runs
`script/cibuild` on push — reference
`script/cibuild` on push, checks out with `persist-credentials: false` and
with `fetch-depth: 0` (which fetches the tags `git describe` needs), and
carries the `concurrency` block that lets a new push cancel only the same
branch's older run — reference
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitea/workflows/check.yml`
- [ ] Language-specific:
- [ ] Go: `go mod init sneak.berlin/go/<name>`, `.golangci.yml` (fetch from
+20 -5
View File
@@ -281,11 +281,26 @@ style conventions are in separate documents:
`.git` and the version still comes out empty, `dev` or `unknown`. A plain
`docker build .` with no build arguments must succeed; a Dockerfile that
refuses an empty build argument drops that refusal and keeps the argument.
A checkout whose `.git` is a file (a linked worktree, or a repository
checked out as a submodule) is the exception: that file points to a git
directory outside the build context, so the build cannot read the version
and a plain `docker build .` fails; pass the version with
`--build-arg VERSION=...`, as `script/docker` and `script/cibuild` already
do.
- Every repo should have a Gitea Actions workflow (`.gitea/workflows/`) that
runs `script/cibuild` on push, and checks out the repo as its only other step.
That script bootstraps, runs the gate phases, and then builds the image, so a
successful run means every check passed; a bare `docker build .` does not
runs `script/cibuild` on push, and checks out the repo as its only other step,
with `persist-credentials: false`: `script/cibuild` needs no token, and
without it the checkout leaves the job's token in `.git/config` for every
later step. The checkout step also sets `fetch-depth: 0`, which fetches the
tags `git describe` needs: by default it clones shallow with no tags, and a
tagged repository's CI build would stamp a bare short commit id. The
workflow's `concurrency` block groups runs by workflow and branch
(`${{ github.workflow }}-${{ github.ref }}`) with `cancel-in-progress: true`,
so a new push cancels the older run on the same branch, queued or running, and
no other: runs for replaced commits do not hold up the shared runner.
`script/cibuild` bootstraps, runs the gate phases, and then builds the image,
so a successful run means every check passed; a bare `docker build .` does not
carry the same guarantee, because its gate phases may come from the cache. The
image build is uncached and so runs the gate phases a second time. That is the
price of the rule above, and it is worth paying: the image that ships is built
@@ -460,8 +475,8 @@ style conventions are in separate documents:
there because `ARG` is stage-scoped; passing `VERSION` to a repo whose
Dockerfile declares no such `ARG` is ignored and costs nothing, which is why
the scripts stay byte-identical. One consequence for CI: the standard
checkout action clones shallow and fetches no tags, so a repo that embeds a
tag-derived version must set `fetch-depth: 0` on its checkout step.
checkout action clones shallow and fetches no tags, so the canonical
`.gitea/workflows/check.yml` sets `fetch-depth: 0` on its checkout step.
- **Verify `.dockerignore` by enumerating the image, not by reading the
patterns.** Plant files at the root _and_ at least two directories deep, build
+9 -1
View File
@@ -19,6 +19,7 @@ YARN_VERSION="1.22.22"
PKGMGR=""
SUDO=""
APT_UPDATED=""
detect_pkgmgr() {
[ -n "$PKGMGR" ] && return 0
@@ -47,7 +48,14 @@ pkg_install() {
detect_pkgmgr
case "$PKGMGR" in
nix) nix-env -iA "nixpkgs.$1" ;;
apt) $SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y "$2" ;;
apt)
# Package lists may be empty (fresh images); refresh once per run.
if [ -z "$APT_UPDATED" ]; then
$SUDO env DEBIAN_FRONTEND=noninteractive apt-get update
APT_UPDATED=1
fi
$SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y "$2"
;;
brew) brew install "$3" ;;
apk) apk add --no-cache "$4" ;;
esac