fix(ci): pin Node.js 22.23.4 in the Ubicloud free-suite bootstrap too, and verify both archives by SHA-256

#3355 bumped Dockerfile.ci only; scripts/ubicloud/setup-free-suite.sh still
installed 22.20.0. Both now pin the same version and the linux-x64 SHA-256
from the release's signed SHASUMS256.txt, check the archive before unpacking,
and test/ci-image-cli-pin.test.ts keeps the two pins equal (#3354).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

Co-authored-by: Michael Sumner <75835774+michael-sumner@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
committed 2026-10-25 02:10:54 +00:00
1 parent 1b4f6e082f
commit bb055753ff
3 files changed
+53 -4

No files matched your search

+5
View File
@@ -90,8 +90,13 @@ RUN curl --retry 5 --retry-delay 5 --retry-connrefused -fsSL https://cli.github.
# and "gnupg" was renamed to "gpg" on Ubuntu 24.04 anyway, so NodeSource's script
# fails before it can add its own repo. Direct tarball download is network-simpler
# (one host: nodejs.org) and doesn't touch apt at all.
# The hash comes from the release's signed SHASUMS256.txt, and the archive is
# checked before it is unpacked. scripts/ubicloud/setup-free-suite.sh pins the
# same version and hash (test/ci-image-cli-pin.test.ts keeps them equal).
ENV NODE_VERSION=22.23.4
ARG NODE_SHA256=1805bcd35e6815559bd2eb97db438d3fdb0eb3a5e6a977b7c1badca76337e9ce
RUN curl --retry 5 --retry-delay 5 --retry-connrefused -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz" -o /tmp/node.tar.xz \
&& echo "${NODE_SHA256} /tmp/node.tar.xz" | sha256sum -c - \
&& tar -xJ -C /usr/local --strip-components=1 --no-same-owner -f /tmp/node.tar.xz \
&& rm -f /tmp/node.tar.xz \
&& node --version \
+8 -3
View File
@@ -5,7 +5,8 @@
set -euo pipefail
BUN_VERSION=1.4.2
NODE_VERSION=22.20.0
NODE_VERSION=22.23.4
NODE_SHA256=1805bcd35e6815559bd2eb97db438d3fdb0eb3a5e6a977b7c1badca76337e9ce
export DEBIAN_FRONTEND=noninteractive
sudo -E apt-get update -qq
@@ -17,9 +18,13 @@ sudo -E apt-get install -y -qq --no-install-recommends \
# needs; GitHub-hosted runners ship with this relaxed.
sudo sysctl -qw kernel.apparmor_restrict_unprivileged_userns=0
# The same verified release archive as .github/docker/Dockerfile.ci.
if ! command -v node >/dev/null; then
curl -fsSL "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
| sudo tar -xJ -C /usr/local --strip-components=1
node_tmp=$(mktemp -d)
curl -fsSL "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" -o "$node_tmp/node.tar.xz"
echo "$NODE_SHA256 $node_tmp/node.tar.xz" | sha256sum -c - >/dev/null
sudo tar -xJ -C /usr/local --strip-components=1 -f "$node_tmp/node.tar.xz"
rm -rf "$node_tmp"
fi
# The exact release archive, verified by SHA-256 before it is unpacked, as in
+40 -1
View File
@@ -193,7 +193,7 @@ describe('other CI Bun installs match the image (#1713, #1706)', () => {
test(`${rel} downloads the verified linux-x64 archive instead of piping an installer into a shell`, () => {
expect(curlPipedToShell(source)).toEqual([]);
const download = source.indexOf('/releases/download/bun-v$BUN_VERSION/bun-linux-x64.zip');
const verify = source.indexOf('sha256sum -c');
const verify = source.indexOf('sha256sum -c', download);
const unpack = source.indexOf('unzip -q');
expect(download).toBeGreaterThan(-1);
expect(verify).toBeGreaterThan(download);
@@ -216,3 +216,42 @@ describe('other CI Bun installs match the image (#1713, #1706)', () => {
});
}
});
describe('CI Node.js installs match the image and are verified (#3354)', () => {
const docker = fs.readFileSync(DOCKERFILE, 'utf-8');
const imageVersion = docker.match(/^ENV NODE_VERSION=(\S+)$/m)?.[1];
const imageSha = docker.match(/^ARG NODE_SHA256=(\S+)$/m)?.[1];
const nodeRun = logicalLines(docker).find((line) => line.includes('nodejs.org/dist/v${NODE_VERSION}/')) ?? '';
test('Dockerfile.ci pins an exact Node.js version and the SHA-256 of its linux-x64 archive', () => {
expect(imageVersion).toMatch(/^\d+\.\d+\.\d+$/);
expect(imageSha).toMatch(/^[0-9a-f]{64}$/);
});
test('Dockerfile.ci checks the Node.js archive before it is unpacked', () => {
expect(nodeRun, 'Node.js must come from the nodejs.org release archive').not.toBe('');
const download = nodeRun.indexOf('-o /tmp/node.tar.xz');
const verify = nodeRun.indexOf('echo "${NODE_SHA256} /tmp/node.tar.xz" | sha256sum -c -');
const unpack = nodeRun.indexOf('tar -xJ');
expect(download).toBeGreaterThan(-1);
expect(verify).toBeGreaterThan(download);
expect(unpack).toBeGreaterThan(verify);
});
const rel = 'scripts/ubicloud/setup-free-suite.sh';
const source = fs.readFileSync(path.join(ROOT, rel), 'utf-8');
test(`${rel} pins the same Node.js version and SHA-256 as Dockerfile.ci`, () => {
expect(source.match(/^NODE_VERSION=(\S+)$/m)?.[1]).toBe(imageVersion!);
expect(source.match(/^NODE_SHA256=(\S+)$/m)?.[1]).toBe(imageSha!);
});
test(`${rel} checks the Node.js archive before it is unpacked`, () => {
const download = source.indexOf('/node-v$NODE_VERSION-linux-x64.tar.xz" -o "$node_tmp/node.tar.xz"');
const verify = source.indexOf('echo "$NODE_SHA256 $node_tmp/node.tar.xz" | sha256sum -c -');
const unpack = source.indexOf('tar -xJ');
expect(download).toBeGreaterThan(-1);
expect(verify).toBeGreaterThan(download);
expect(unpack).toBeGreaterThan(verify);
});
});