Repository navigation
Conversation
…nager The fetch stage installed curl, tar and xz with apk, which trusts the Alpine package index on top of the release's own checksums. The base image's busybox already provides wget, tar with xz decompression and sha256sum, so the stage now installs nothing. The archive is still checked against the release's SHASUMS256.txt before it is unpacked, and the resulting tool cache layout is unchanged.
A matrix entry of the publish workflow can now name a version, which reaches the Dockerfile through its own ARG <TOOL>_VERSION, so one directory publishes several versions as tags of one repository. An entry without a version builds the Dockerfile's default as before. The digest artifacts carry the version, so two versions of one image do not share an artifact name or a download pattern. The matrix gains node 26.12.1. A unit test keeps the build and merge matrices equal and no two entries on the same tag, and checks that the Node.js image runs no package manager. The capabilities test builds the second version, adds it to the plain profile and checks that both versions sit in the pod's tool cache and that @actions/tool-cache finds each by its major version.
actionlint's shellcheck run reports SC2129 for the three consecutive appends to GITHUB_OUTPUT the multi-version change added.
Node.js 26 links libatomic, which the stock runner image the test uses does not carry, so running its node there fails for a reason unrelated to the capability. The test now checks that the version's directory, its .complete marker and an executable node are in the pod's tool cache, and that @actions/tool-cache finds it by its major version.
…ed index GitHub's ubuntu-latest moved to 26.04, whose Docker keeps pulled images in the containerd store as multi-platform indexes. kind load saves only the pulled platform's content, so ctr images import --all-platforms then fails on the other platforms' digests with "content digest ... not found". The test now builds its stand-in pod image from the base image, a single platform image of the kind the watcher image already is.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A job on this fleet that calls
actions/setup-nodewithnode-version-fileandengines.node>=26(resolved to 26.12.1) downloads the 26.12.1 linux-arm64 tarball fromactions/node-versionsinto every ephemeral pod, then extracts and caches it. Observed on 2026-10-28 on cold pods of a private repository's CI: about 131 s for the download at roughly 0.2 MB/s (one job took 31 s), the largest remaining part of a job of a few hundred seconds. One observation on one fleet, not a benchmark.The reference tool-cache image for Node.js already exists for 24.21.0, so this publishes 26.12.1 from the same Dockerfile. A matrix entry of
publish-tool-images.ymlcan now carry aversion, which reaches the Dockerfile through its ownARG <TOOL>_VERSION; an entry without one still builds the default. Both versions are tags ofgithub-runner-toolcache-node, and the digest artifacts now carry the version so two versions of one image cannot collide. A profile that names the image as a capability getsnode/26.12.1/<arch>and<arch>.completein its tool cache, and setup-node uses it for any range 26.12.1 satisfies unlesscheck-latestis set. Bumping is a newversionin both matrices; the README says so.I also dropped
apk addfrom the Node.js fetch stage. The base image's busybox already haswget,tarwith xz andsha256sum, so the image build runs no package manager, and the archive is still checked against the release'sSHASUMS256.txtbefore it is unpacked. That changes the recipe for 24.21.0 too, but not its output, and a published tag is never rebuilt.Checked locally: the 26.12.1 tarballs' SHA-256 for linux-x64 and linux-arm64 against nodejs.org's
SHASUMS256.txt(the build fails otherwise); a build of both architectures (arm64 natively, amd64 under emulation), laid out asnode/26.12.1/{arm64,x64}with the.completemarker beside it, 4744 files;tests/unit/test_tool_images_workflow.py, which fails on a reintroducedapk addand on shared artifact names (mutation-checked); actionlint, shellcheck, hadolint and yamllint on the changed files. I cannot run the publish workflow without pushing images.tests/capabilities/run.shpassed in this PR'sCapabilities in kindjob on 236e117, which is the quiet host: both Node.js versions in the pod's tool cache,@actions/tool-cachefinding each by its major version, and the rest of the script. It did not pass locally. On my laptop (a loaded Colima VM, 2 CPUs, 4 GB) it ran seven times and none of the runs reached its Node.js assertions: a Docker Hub DNS timeout, mypython3lacking ansible and then PyYAML, kind passing a loopbackHTTPS_PROXYinto a node that cannot reach it (busybox, then the runner image), a chart fetch failure, and finallyNo space left on devicein the VM. The first CI run failed on my own assertion: Node.js 26 linkslibatomic.so.1, which the stock runner image lacks, so the test now checks the second version's directory, marker, executable and tool-cache lookup without running itsnode. The fleet's own runner image does run Node.js 26 (setup-node downloaded the same tarball on those pods and the job passed); Its arm64 build haslibatomic1installed (read from the image); The amd64 build has it too (read on 2026-10-28 from a throwaway container ofghcr.io/exadev/github-runner:lateston the amd64 node:/lib/x86_64-linux-gnu/libatomic.so.1).Recovery in kindfailed on this branch twice and also fails on main (workflow_dispatch run 40752458235, same digest in the same error), so it is not caused by this change.ubuntu-latestis now ubuntu-26.04, andkind loadof the pulledbusybox:1.36index fails inctr images import --all-platformswithcontent digest ... not found. I assume the cause is that the runner's Docker keeps pulled images as multi-platform indexes in the containerd store, but I did not look at the store itself. 236e117 builds the stand-in pod image from the base image instead of loading the pulled one, and the job passes with it.Order: merge, run
gh workflow run publish-tool-images.yml, make the newgithub-runner-toolcache-nodetag public if the package needs it, and take the digest from the run summary into the fleet's capability (ExaDev/github-runner-fleet#54).