diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 2e35e8f..0e15d4a 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -75,6 +75,8 @@ jobs: grep -E 'hostedtoolcache|workspace|overlay' /proc/mounts || true ls -la /opt/hostedtoolcache || true ls -la /opt/hostedtoolcache/node || true + ls -la "/opt/hostedtoolcache/node/$(tr -d '[:space:]' < .node-version)/" || true + test -f "/opt/hostedtoolcache/node/$(tr -d '[:space:]' < .node-version)/x64.complete" && echo MARKER-PRESENT || echo MARKER-MISSING ls -la "/opt/hostedtoolcache/node/$(tr -d '[:space:]' < .node-version)/x64/bin" || true "/opt/hostedtoolcache/node/$(tr -d '[:space:]' < .node-version)/x64/bin/node" -v || true env | grep -iE 'RUNNER|TOOL|CACHE' || true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ee23cfd..786164a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -102,6 +102,11 @@ Bumping Node is one coordinated change, committed as a unit: Skipping step 2 fails CI at image pull; skipping step 3 silently reverts to the per-job download. +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. + ## Publishing workflow Publishing is CI-only by policy. Local `npm publish` is not supported. The maintainer triggers releases from `main`: diff --git a/docker/Dockerfile b/docker/Dockerfile index babcb5a..8cb0475 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -39,6 +39,13 @@ ARG NODE_VERSION=26.8.2 # node image: bin/ + lib/ under /usr/local → tool cache: bin/ + lib/ under /x64. COPY --from=nodebase /usr/local /opt/hostedtoolcache/node/${NODE_VERSION}/x64 +# actions/tool-cache only accepts a cached tool when the sibling marker file +# "/.complete" exists — tc.find() checks it and falls back to +# downloading otherwise, however complete the directory is. The marker is what +# tc.cacheDir() writes after *it* installs a tool, so a pre-baked entry has to +# reproduce it explicitly. +RUN touch "/opt/hostedtoolcache/node/${NODE_VERSION}/x64.complete" + # Fail the build (not CI) if the overlay or the version arg were wrong. # Shell form on purpose: exec form (`RUN [...]`) does not expand ARG values. RUN "/opt/hostedtoolcache/node/${NODE_VERSION}/x64/bin/node" --version