diff --git a/.gitea/workflows/check.yml b/.gitea/workflows/check.yml index ee73864..6246a7e 100644 --- a/.gitea/workflows/check.yml +++ b/.gitea/workflows/check.yml @@ -1,9 +1,16 @@ 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 - run: script/cibuild diff --git a/TODO.md b/TODO.md index 20c8a60..fe43659 100644 --- a/TODO.md +++ b/TODO.md @@ -21,6 +21,12 @@ fmt-check, and commit. # Completed Steps +- 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-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 diff --git a/prompts/EXISTING_REPO_CHECKLIST.md b/prompts/EXISTING_REPO_CHECKLIST.md index 0540bb5..b891572 100644 --- a/prompts/EXISTING_REPO_CHECKLIST.md +++ b/prompts/EXISTING_REPO_CHECKLIST.md @@ -1,6 +1,6 @@ --- title: Existing Repo Checklist -last_modified: 2026-10-04 +last_modified: 2026-10-06 --- Use this checklist when beginning work in a repo that may not yet conform to our @@ -91,7 +91,9 @@ with your task. `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 — 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 diff --git a/prompts/NEW_REPO_CHECKLIST.md b/prompts/NEW_REPO_CHECKLIST.md index b425e37..b9eac78 100644 --- a/prompts/NEW_REPO_CHECKLIST.md +++ b/prompts/NEW_REPO_CHECKLIST.md @@ -1,6 +1,6 @@ --- title: New Repo Checklist -last_modified: 2026-10-04 +last_modified: 2026-10-06 --- Use this checklist when creating a new repository from scratch. Follow the steps @@ -103,7 +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 — 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/`, `.golangci.yml` (fetch from diff --git a/prompts/REPO_POLICIES.md b/prompts/REPO_POLICIES.md index 7fa4bf4..d86cd71 100644 --- a/prompts/REPO_POLICIES.md +++ b/prompts/REPO_POLICIES.md @@ -1,6 +1,6 @@ --- title: Repository Policies -last_modified: 2026-10-04 +last_modified: 2026-10-06 --- This document covers repository structure, tooling, and workflow standards. Code @@ -283,9 +283,15 @@ style conventions are in separate documents: refuses an empty build argument drops that refusal and keeps the argument. - 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. 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. + `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