1 Commits
Author SHA1 Message Date
sneak 22e6bda2bb Cancel replaced CI runs and drop the checkout token (closes #107)
check / check (push) Canceled after 0s
The canonical `.gitea/workflows/check.yml` gains a `concurrency` block grouped
by workflow and branch with `cancel-in-progress: true`, 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`;
`script/cibuild` needs none. Both come from `dnswatcher`, where a byte-identical
re-vendor would have removed them. The workflow bullet of
`prompts/REPO_POLICIES.md` and both checklists now describe the file as it is.

Model: opus-5-5
2026-10-06 01:35:43 +00:00
10 changed files with 33 additions and 129 deletions
-6
View File
@@ -10,9 +10,3 @@ insert_final_newline = true
[Makefile]
indent_style = tab
[*.go]
indent_style = tab
# This repository's own sections, such as one for another language it
# uses, go below this comment, and a re-vendor keeps them.
-2
View File
@@ -13,6 +13,4 @@ jobs:
# 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
+1 -5
View File
@@ -27,7 +27,7 @@ node_modules/
# Environment files. `*.env` covers bare `.env` and the `prod.env`
# convention. Only the templates `example.env` and `sample.env` are
# re-included below. A repository that commits any other template adds
# its own negation at the end of this file, for example `!.env.example`.
# its own negation after these lines, for example `!.env.example`.
*.[eE][nN][vV]
.[eE][nN][vV].*
.[eE][nN][vV][rR][cC]
@@ -45,7 +45,3 @@ node_modules/
[iI][dD]_[eE][cC][dD][sS][aA]_[sS][kK]
[iI][dD]_[eE][dD]25519
[iI][dD]_[eE][dD]25519_[sS][kK]
# This repository's own entries, such as its build outputs, go below
# this comment, and a re-vendor keeps them. Anchor a binary built at the
# root: `/myapp`, never `myapp`, which also ignores `cmd/myapp/`.
-2
View File
@@ -25,8 +25,6 @@ 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
-36
View File
@@ -21,48 +21,12 @@ 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
does. `.editorconfig` gains a `[*.go]` section with tabs, since `gofmt`
decides Go indentation everywhere. `REPO_POLICIES.md` and both checklists say
that each of these two files is the canonical content followed by the
repository's own entries, which a re-vendor keeps, and the Go styleguide puts
`*.log`, `*.out`, `*.test` and binaries among those entries. Common outputs
stay out of the canonical `.gitignore`; each repository lists its own.
- 2026-10-05: `script/cibuild`, `script/docker`, `script/lint` and `script/test`
now assign the image tag from `script/projectname` on its own line before the
`docker build` (issue 101), so `set -e` stops the script where
+3 -4
View File
@@ -1,6 +1,6 @@
---
title: Code Styleguide — Go
last_modified: 2026-10-06
last_modified: 2026-10-04
---
1. Try to hard wrap long lines at 77 characters or less.
@@ -148,9 +148,8 @@ last_modified: 2026-10-06
handle HTTP requests. Don't use methods or your top level functions as
handlers.
1. The repository's own entries at the end of `.gitignore`, which a re-vendor
keeps, ignore at least `*.log`, `*.out`, and `*.test` files, as well as any
binaries.
1. Provide a .gitignore file that ignores at least `*.log`, `*.out`, and
`*.test` files, as well as any binaries.
1. Constructors **must** be called `New()`. `modulename.New()` works great if
you name the packages properly. If the constructor creates an instance from
+11 -22
View File
@@ -28,18 +28,13 @@ with your task.
root — never a file or directory named after one agent tool, such as
`CLAUDE.md` or `.claude/`, and never separate memory files. Move what any
such committed file says into `AGENTS.md` and delete it.
- [ ] `.gitignore` is comprehensive (OS, editor, agent scratch, secrets, the
repo's own build outputs) — fetch from
- [ ] `.gitignore` is comprehensive (OS, editor, agent scratch, language
artifacts, secrets) — fetch from
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitignore` if missing.
An existing repo usually has a hand-written one that is never re-fetched,
so check the entries rather than the file's presence. The file is the
canonical content followed by the repo's own entries, such as its
binaries; a re-vendor replaces the canonical part and keeps those entries.
so check the entries rather than the file's presence.
- [ ] `.editorconfig` exists — fetch from
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.editorconfig`. The
file is the canonical content followed by the repo's own sections, such as
one for another language it uses; a re-vendor replaces the canonical part
and keeps those sections.
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.editorconfig`
- [ ] `Dockerfile` and `.dockerignore` exist; the Dockerfile carries a `lint`
phase and a `test` phase, and the final stage carries a `COPY --from=` of
a harmless file from each — fetch `.dockerignore` from
@@ -91,20 +86,14 @@ 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.
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.
`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.
- [ ] Gitea Actions workflow in `.gitea/workflows/` runs `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
push, checks out with `persist-credentials: false`, 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 -20
View File
@@ -34,17 +34,14 @@ Template files can be fetched from:
## Fetch Template Files
- [ ] `.gitignore` — fetch from
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitignore`, then add
the repo's own build outputs, such as its binaries, at the end of the
file, where a re-vendor keeps them. Extensions are written to
`.gitignore`'s own semantics, where an unanchored pattern already matches
at every depth: never add a `**/` prefix here, which is a `.dockerignore`
form. The canonical file already carries `.claude/` so agent worktrees
cannot be committed by accident.
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitignore`, extend for
language-specific artifacts. Extensions are written to `.gitignore`'s own
semantics, where an unanchored pattern already matches at every depth:
never add a `**/` prefix here, which is a `.dockerignore` form. The
canonical file already carries `.claude/` so agent worktrees cannot be
committed by accident.
- [ ] `.editorconfig` — fetch from
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.editorconfig`, then
add the repo's own sections, such as one for another language it uses, at
the end of the file, where a re-vendor keeps them.
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.editorconfig`
- [ ] `Makefile` — fetch from
`https://git.eeqj.de/sneak/prompts/raw/branch/main/Makefile`, adapt
targets for the project's language and tools
@@ -97,12 +94,6 @@ 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
@@ -112,10 +103,9 @@ 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, 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
`script/cibuild` on push, checks out with `persist-credentials: false`,
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
+7 -23
View File
@@ -281,21 +281,12 @@ 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,
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
later step. Its `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.
@@ -402,12 +393,9 @@ style conventions are in separate documents:
- `.gitignore` should be comprehensive from the start: OS files (`.DS_Store`),
editor files (`.swp`, `*~`), in-repo agent scratch directories (`.claude/`),
`node_modules/`, and the repo's own build outputs. Fetch the standard
`.gitignore` from
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitignore` when setting up
a new repo. A repo's `.gitignore` is the standard file followed by the repo's
own entries, such as its binaries; a re-vendor replaces the standard part and
keeps those entries. These patterns are written to `.gitignore`'s own
language build artifacts, and `node_modules/`. Fetch the standard `.gitignore`
from `https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitignore` when
setting up a new repo. These patterns are written to `.gitignore`'s own
semantics, in which an unanchored pattern already matches at every depth; they
are not a `.dockerignore` and must not be transplanted into one unmodified.
@@ -475,8 +463,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 the canonical
`.gitea/workflows/check.yml` sets `fetch-depth: 0` on its checkout step.
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.
- **Verify `.dockerignore` by enumerating the image, not by reading the
patterns.** Plant files at the root _and_ at least two directories deep, build
@@ -659,11 +647,7 @@ style conventions are in separate documents:
Never edit existing migrations after release.
- All repos should have an `.editorconfig` enforcing the project's indentation
settings: the standard file from
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.editorconfig`, which sets
tabs for `Makefile` and Go files, followed by the repo's own sections, such as
one for another language it uses. A re-vendor replaces the standard part and
keeps those sections.
settings.
- Avoid putting files in the repo root unless necessary. Root should contain
only project-level config files (`README.md`, `AGENTS.md`, `Makefile`,
+1 -9
View File
@@ -19,7 +19,6 @@ YARN_VERSION="1.22.22"
PKGMGR=""
SUDO=""
APT_UPDATED=""
detect_pkgmgr() {
[ -n "$PKGMGR" ] && return 0
@@ -48,14 +47,7 @@ pkg_install() {
detect_pkgmgr
case "$PKGMGR" in
nix) nix-env -iA "nixpkgs.$1" ;;
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"
;;
apt) $SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y "$2" ;;
brew) brew install "$3" ;;
apk) apk add --no-cache "$4" ;;
esac