From e1dec54363a522282b613fa5dca4fe24b3406464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 15 Sep 2026 12:02:59 +0000 Subject: [PATCH 1/2] :memo: Cancel force-pull task and document the runner-image decision The act-ci image is rebuilt only when Node is bumped, which changes the tag, so the runner's default no-force-pull behavior already picks up every normal update. Forcing a pull would re-pull on every job and a missed runner-side image change is acceptable, so document that decision as a known issue with a manual docker rmi workaround instead of tracking a force-pull task. --- CONTRIBUTING.md | 4 ++-- backlog.tasks | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f38e45b..6514cf9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,7 +92,7 @@ This is why every test in the suite pairs an `expectTypeOf(...)` with an `assert ## CI runner image -The `build` / `maintain` / `publish` jobs run in `gitea.e1nsnull.de/tmu/act-ci:` ([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. +The `build` / `maintain` / `publish` jobs run in `gitea.e1nsnull.de/tmu/act-ci:` ([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`, and the image is rebuilt only as part of a Node bump — there is no other trigger. `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: @@ -105,7 +105,7 @@ Skipping step 2 fails CI at image pull; skipping step 3 silently reverts to the Two invariants the image must satisfy for the probe to hit, both easy to break: - **The `x64.complete` marker.** `actions/tool-cache` accepts a cached tool only when `/.complete` exists next to the directory (`tc.find()` checks it); a plausible-looking `node//x64/` alone is ignored and the download happens anyway. See the comment in [docker/Dockerfile](./docker/Dockerfile). -- **Tag freshness.** The tag encodes only the Node version, so a Dockerfile change (like the marker above) produces _new content under an unchanged tag_. `act_runner` skips the pull when a tag of that name already exists locally (`forcePull=false` in the job log), so the runner must either force-pull (`force_pull` under `container:` in its `config.yaml`, if the installed version has it) or have the tag removed on the runner host (`docker rmi gitea.e1nsnull.de/tmu/act-ci:`) after any image change. Symptom of getting this wrong: CI keeps running the previous image while the registry shows the new digest. +- **Tag freshness (force-pull deliberately off).** The tag encodes only the Node version, and the image is rebuilt only when that version changes — so the normal flow always yields a new tag, and `act_runner` pulls it. `force_pull` stays disabled (the job log shows `forcePull=false`): it is acceptable to miss a runner-side image change, and forcing a pull would re-pull the image on every job for no benefit. Known issue: a Dockerfile-only change (like the marker above) re-pushed under an unchanged tag is invisible to the runner — it keeps the old image while the registry shows the new digest. If that ever matters, remove the stale tag on the runner host (`docker rmi gitea.e1nsnull.de/tmu/act-ci:`); do not reach for force-pull. ## Publishing workflow diff --git a/backlog.tasks b/backlog.tasks index 6a7c7e9..8dd21d6 100644 --- a/backlog.tasks +++ b/backlog.tasks @@ -53,8 +53,8 @@ Maintenance: ✔ Write the `/x64.complete` marker — actions/tool-cache ignores a bare directory, so the probe missed and the download continued @done ✔ Log tool-cache state from the job container to find it (temporary, removed once understood) @done ✔ Guard the invariant in CI (`Assert the baked tool cache is present`) @done -☐ Enable force-pull for the runner so a changed act-ci image is never missed @low - → the tag encodes only the Node version, so a Dockerfile change yields new content under an unchanged tag; with `forcePull=false` the runner keeps the old image (see CONTRIBUTING § CI runner image) +✘ Enable force-pull for the runner so a changed act-ci image is never missed @low @cancelled + → decided against: it is acceptable to miss a runner-side image change, and the image is only rebuilt on a Node bump, which changes the tag anyway. A Dockerfile-only change re-pushed under an unchanged tag is a known issue with a manual `docker rmi` workaround (see CONTRIBUTING § CI runner image). ✔ Improve CI publish @done ✔ Check whether publish job is only run on tags, if not, guard it @done ✔ Gate only single steps @done From 5bb58137c4eed313318293377159472abbb127b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 15 Sep 2026 12:07:34 +0000 Subject: [PATCH 2/2] :memo: Check off the Gitea release-page verification task --- backlog.tasks | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backlog.tasks b/backlog.tasks index 8dd21d6..dc8cee8 100644 --- a/backlog.tasks +++ b/backlog.tasks @@ -6,7 +6,7 @@ Backlog and tracking for tiny-pattern-ts. Managed in vscode-todotasks format. Setup: ✔ Add gitea release page in CI @high @done -☐ Manually verify the Gitea release page on a real tag push (needs main) @high +✔ Manually verify the Gitea release page on a real tag push (needs main) @high @done (9/15/2026, 1:18:15 PM) ☐ Split off template into separate package => pi --session 01a07dde-7050-7054-bb36-1606d7eb2bc3 @high v1.0: