Set a time limit on the canonical check job (closes #120)
check / check (push) Canceled after 0s

The canonical check workflow gave its job no time limit, so a hung
script/cibuild held the shared runner until the runner's own default.
The check job now sets timeout-minutes: 20. script/cibuild runs three
Docker builds (the lint phase, the test phase, then the image, which
runs both again), each held to the 5-minute build limit, plus the
bootstrap. REPO_POLICIES.md and both checklists name the limit among
what the workflow sets.

Model: opus-5-5
This commit is contained in:
2026-10-07 08:37:34 +00:00
parent b3508a4361
commit 3474bf0e58
5 changed files with 37 additions and 20 deletions
+2
View File
@@ -7,6 +7,8 @@ concurrency:
jobs: jobs:
check: check:
runs-on: ubuntu-latest runs-on: ubuntu-latest
# Free the shared runner from a hung build.
timeout-minutes: 20
steps: steps:
# actions/checkout v4.2.2, 2026-02-22 # actions/checkout v4.2.2, 2026-02-22
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+8
View File
@@ -21,6 +21,14 @@ fmt-check, and commit.
# Completed Steps # Completed Steps
- 2026-10-07: The canonical `.gitea/workflows/check.yml` now sets
`timeout-minutes: 20` on its `check` job (issue 120), so a hung build frees
the shared runner instead of holding it until the runner's own limit.
`script/cibuild` runs three Docker builds, each held to the 5-minute Docker
build limit, plus the bootstrap; if that limit changes (issue 113), the value
follows it. `REPO_POLICIES.md` and both checklists name the limit among what
the workflow sets. Not yet tried on the shared runner. Repositories pick this
up on their next re-vendor.
- 2026-10-06: The canonical `.gitea/workflows/check.yml` now sets - 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 `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 and tags that `git describe --tags --always` needs, and a tagged repository
+5 -4
View File
@@ -1,6 +1,6 @@
--- ---
title: Existing Repo Checklist title: Existing Repo Checklist
last_modified: 2026-10-06 last_modified: 2026-10-07
--- ---
Use this checklist when beginning work in a repo that may not yet conform to our Use this checklist when beginning work in a repo that may not yet conform to our
@@ -102,9 +102,10 @@ with your task.
build finds the tag too. build finds the tag too.
- [ ] Gitea Actions workflow in `.gitea/workflows/` runs `script/cibuild` on - [ ] Gitea Actions workflow in `.gitea/workflows/` runs `script/cibuild` on
push, checks out with `persist-credentials: false` and with push, checks out with `persist-credentials: false` and with
`fetch-depth: 0` (which fetches the tags `git describe` needs), and `fetch-depth: 0` (which fetches the tags `git describe` needs), carries
carries the `concurrency` block that lets a new push cancel only the same the `concurrency` block that lets a new push cancel only the same branch's
branch's older run — reference older run, and sets `timeout-minutes: 20` on the `check` job so a hung
build frees the shared runner — reference
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitea/workflows/check.yml` `https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitea/workflows/check.yml`
- [ ] Language-specific config: - [ ] Language-specific config:
- [ ] Go: `go.mod`, `go.sum`, `.golangci.yml` (fetch from - [ ] Go: `go.mod`, `go.sum`, `.golangci.yml` (fetch from
+4 -3
View File
@@ -1,6 +1,6 @@
--- ---
title: New Repo Checklist title: New Repo Checklist
last_modified: 2026-10-06 last_modified: 2026-10-07
--- ---
Use this checklist when creating a new repository from scratch. Follow the steps Use this checklist when creating a new repository from scratch. Follow the steps
@@ -113,9 +113,10 @@ Template files can be fetched from:
- Image pinned by sha256 hash with version/date comment - Image pinned by sha256 hash with version/date comment
- [ ] Gitea Actions workflow at `.gitea/workflows/check.yml` that runs - [ ] Gitea Actions workflow at `.gitea/workflows/check.yml` that runs
`script/cibuild` on push, checks out with `persist-credentials: false` and `script/cibuild` on push, checks out with `persist-credentials: false` and
with `fetch-depth: 0` (which fetches the tags `git describe` needs), and with `fetch-depth: 0` (which fetches the tags `git describe` needs),
carries the `concurrency` block that lets a new push cancel only the same carries the `concurrency` block that lets a new push cancel only the same
branch's older run — reference branch's older run, and sets `timeout-minutes: 20` on the `check` job so a
hung build frees the shared runner — reference
`https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitea/workflows/check.yml` `https://git.eeqj.de/sneak/prompts/raw/branch/main/.gitea/workflows/check.yml`
- [ ] Language-specific: - [ ] Language-specific:
- [ ] Go: `go mod init sneak.berlin/go/<name>`, `.golangci.yml` (fetch from - [ ] Go: `go mod init sneak.berlin/go/<name>`, `.golangci.yml` (fetch from
+18 -13
View File
@@ -1,6 +1,6 @@
--- ---
title: Repository Policies title: Repository Policies
last_modified: 2026-10-06 last_modified: 2026-10-07
--- ---
This document covers repository structure, tooling, and workflow standards. Code This document covers repository structure, tooling, and workflow standards. Code
@@ -298,18 +298,23 @@ style conventions are in separate documents:
workflow's `concurrency` block groups runs by workflow and branch workflow's `concurrency` block groups runs by workflow and branch
(`${{ github.workflow }}-${{ github.ref }}`) with `cancel-in-progress: true`, (`${{ 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 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. no other: runs for replaced commits do not hold up the shared runner. The
`script/cibuild` bootstraps, runs the gate phases, and then builds the image, `check` job sets `timeout-minutes: 20`, so a hung build frees the shared
so a successful run means every check passed; a bare `docker build .` does not runner after 20 minutes. That allows for the three Docker builds
carry the same guarantee, because its gate phases may come from the cache. The `script/cibuild` runs (the lint phase, the test phase, then the image, which
image build is uncached and so runs the gate phases a second time. That is the runs both again), each held to the 5-minute Docker build limit below, plus the
price of the rule above, and it is worth paying: the image that ships is built bootstrap. `script/cibuild` bootstraps, runs the gate phases, and then builds
from a run of its own gates rather than from a cache entry. A separate the image, so a successful run means every check passed; a bare
workflow limited to `main` by a `branches` list under `on: push` cannot be `docker build .` does not carry the same guarantee, because its gate phases
checked by review: to try a change to it, add the feature branch to that list may come from the cache. The image build is uncached and so runs the gate
and push, then remove the branch from the list again before merging. Keep any phases a second time. That is the price of the rule above, and it is worth
job in it that publishes behind `if: github.ref_name == 'main'`, so the run paying: the image that ships is built from a run of its own gates rather than
from the feature branch publishes nothing. from a cache entry. A separate workflow limited to `main` by a `branches` list
under `on: push` cannot be checked by review: to try a change to it, add the
feature branch to that list and push, then remove the branch from the list
again before merging. Keep any job in it that publishes behind
`if: github.ref_name == 'main'`, so the run from the feature branch publishes
nothing.
- Use platform-standard formatters: `black` for Python, `prettier` for - Use platform-standard formatters: `black` for Python, `prettier` for
JS/CSS/Markdown/HTML, `go fmt` for Go. Always use default configuration with JS/CSS/Markdown/HTML, `go fmt` for Go. Always use default configuration with