📝 Document CI runner-image bump ritual

build:runner-image broke the script prefix convention: build is a bare
single-tool command, and no tier fits a docker-daemon + registry-cred action,
so the script leaves package.json and is invoked directly. CONTRIBUTING gains
a 'CI runner image' section recording where the image pushes
(gitea.e1nsnull.de/tmu/act-ci:<version>), the .node-version coupling, and the
three-step Node-bump ritual.
This commit is contained in:
tmu committed 2026-09-14 12:51:34 +00:00
1 parent abbdf4410e
commit 3e33b51d1b
3 files changed
+15 -4

No files matched your search

+3 -3
View File
@@ -52,9 +52,9 @@ jobs:
# `image` extends the runner's default job image (catthehacker/act) # `image` extends the runner's default job image (catthehacker/act)
# with Node 26 pre-planted in the tool cache layout, so setup-node's # with Node 26 pre-planted in the tool cache layout, so setup-node's
# version probe hits and never downloads (see docker/Dockerfile). The # version probe hits and never downloads (see docker/Dockerfile). The
# tag MUST equal the exact version pinned in `.node-version`; rebuild # tag MUST equal the exact version pinned in `.node-version`; the bump
# via `npm run build:runner-image -- --push` and repoint here on every # ritual is documented in CONTRIBUTING.md § CI runner image. The volume
# Node bump. The volume bind-mounts the shared pages tree so the # bind-mounts the shared pages tree so the
# coverage step below can write into it; the runner whitelists this # coverage step below can write into it; the runner whitelists this
# path via `container.valid_volumes` (docker-space `setup/gitea.sh`). # path via `container.valid_volumes` (docker-space `setup/gitea.sh`).
container: container:
+12
View File
@@ -90,6 +90,18 @@ This is why every test in the suite pairs an `expectTypeOf(...)` with an `assert
- CI runs `npm run check` + `npm run test:ci` on every push to `main` — this is the authoritative gate. The one exception: a push headed by a release commit (`:rocket: Release x.y.z`) skips the full `build`/`maintain` jobs, because `create:release` pushes the tag for that exact commit right after and the tag run is the authoritative one (see `release-gate` in [.gitea/workflows/ci.yml](./.gitea/workflows/ci.yml)). - CI runs `npm run check` + `npm run test:ci` on every push to `main` — this is the authoritative gate. The one exception: a push headed by a release commit (`:rocket: Release x.y.z`) skips the full `build`/`maintain` jobs, because `create:release` pushes the tag for that exact commit right after and the tag run is the authoritative one (see `release-gate` in [.gitea/workflows/ci.yml](./.gitea/workflows/ci.yml)).
- **Releases are NOT triggered by pushes.** Only the maintainer triggers a release (see [Publishing workflow](#publishing-workflow)). - **Releases are NOT triggered by pushes.** Only the maintainer triggers a release (see [Publishing workflow](#publishing-workflow)).
## CI runner image
The `build` / `maintain` / `publish` jobs run in `gitea.e1nsnull.de/tmu/act-ci:<version>` ([docker/Dockerfile](./docker/Dockerfile)) — the runner's default act image with the Node distribution overlaid at the exact `/opt/hostedtoolcache` layout `actions/setup-node` probes before downloading, so no job pays the ~50 MB fetch. The image tag MUST equal the exact version pinned in `.node-version`; `release-gate` uses no Node and stays on the default image. The script is deliberately NOT an `npm run` script: building requires a docker daemon and registry credentials, so it belongs to no feedback tier — per [Script prefix convention](#script-prefix-convention), no existing prefix fits and that is the signal.
Bumping Node is one coordinated change, committed as a unit:
1. Edit `.node-version` to the new exact `x.y.z` — floats like `26` resolve to the latest patch at runtime and silently bust the baked entry; `scripts/runner-image.sh` refuses them.
2. `docker login gitea.e1nsnull.de` (user + package/access token), then `./scripts/runner-image.sh --push` — it reads the version from `.node-version` and builds/pushes `<IMAGE_REPO>:<version>`.
3. Repoint the three `container.image` tags in [.gitea/workflows/ci.yml](./.gitea/workflows/ci.yml) to the same version.
Skipping step 2 fails CI at image pull; skipping step 3 silently reverts to the per-job download.
## Publishing workflow ## Publishing workflow
Publishing is CI-only by policy. Local `npm publish` is not supported. The maintainer triggers releases from `main`: Publishing is CI-only by policy. Local `npm publish` is not supported. The maintainer triggers releases from `main`:
-1
View File
@@ -38,7 +38,6 @@
}, },
"scripts": { "scripts": {
"build": "tsc -p tsconfig.build.json", "build": "tsc -p tsconfig.build.json",
"build:runner-image": "./scripts/runner-image.sh",
"prebuild": "rm -rf dist", "prebuild": "rm -rf dist",
"check": "npm run check:tsc && npm run check:oxlint && npm run check:oxfmt && npm run check:cspell", "check": "npm run check:tsc && npm run check:oxlint && npm run check:oxfmt && npm run check:cspell",
"check:cspell": "cspell lint ${LEFTHOOK_FILES:-.}", "check:cspell": "cspell lint ${LEFTHOOK_FILES:-.}",