diff --git a/cspell.json b/cspell.json index a31d295..bebc052 100644 --- a/cspell.json +++ b/cspell.json @@ -28,6 +28,8 @@ "runwisp", "glab", "hostedtoolcache", + "nodebase", + "frontends", "catthehacker", "nsnull", "dedup", diff --git a/docker/Dockerfile b/docker/Dockerfile index 2650cb5..babcb5a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -18,12 +18,26 @@ # baked entry; `.node-version` is pinned to x.y.z and scripts/runner-image.sh # guards the coupling. Rebuild + repoint `container.image` in # .gitea/workflows/ci.yml on every bump. +# +# The extra `nodebase` stage is load-bearing: `COPY --from=` resolves its value +# as a *stage name* at parse time, before build args exist, so +# `COPY --from=node:${NODE_VERSION}` collapses to the invalid `node:` on +# frontends that do not expand args there. ARGs declared before the first FROM +# *are* expanded in FROM, so routing through a named stage works everywhere. + +# Global scope: only visible to FROM lines, but that is exactly where we need it. +ARG NODE_VERSION=26.8.2 +FROM node:${NODE_VERSION} AS nodebase + FROM catthehacker/ubuntu:act-latest +# ARGs do not cross stage boundaries; redeclare (with the same default, so a +# bare `docker build -f docker/Dockerfile .` still works) for the paths below. +# Keep this default in sync with the global one above. ARG NODE_VERSION=26.8.2 # node image: bin/ + lib/ under /usr/local → tool cache: bin/ + lib/ under /x64. -COPY --from=node:${NODE_VERSION} /usr/local /opt/hostedtoolcache/node/${NODE_VERSION}/x64 +COPY --from=nodebase /usr/local /opt/hostedtoolcache/node/${NODE_VERSION}/x64 # 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.