diff --git a/src/cli/tools/node/index.spec.ts b/src/cli/tools/node/index.spec.ts index 11fd0ef3fb..5007af3894 100644 --- a/src/cli/tools/node/index.spec.ts +++ b/src/cli/tools/node/index.spec.ts @@ -400,12 +400,20 @@ describe('cli/tools/node/index', () => { describe('NodePrepareService', () => { test('initialize and prepare', async () => { + // CI configures an apt proxy, which `AptService` would write to `/etc` + vi.stubEnv('APT_HTTP_PROXY', undefined); const { svc, child } = await toolContext(NodePrepareService); const pathSvc = await child.getAsync(PathService); const envSvc = await child.getAsync(EnvService); await expect(svc.prepare()).resolves.toBeUndefined(); + expect(execaMock).toHaveBeenCalledWith( + 'apt-get', + expect.arrayContaining(['libatomic1']), + { env: { DEBIAN_FRONTEND: 'noninteractive' } }, + ); + const env = await fs.readFile( join(pathSvc.toolPath('node'), 'env.sh'), 'utf8', diff --git a/src/cli/tools/node/index.ts b/src/cli/tools/node/index.ts index e877d834e0..f2333f532d 100644 --- a/src/cli/tools/node/index.ts +++ b/src/cli/tools/node/index.ts @@ -1,8 +1,9 @@ import fs from 'node:fs/promises'; import { join } from 'node:path'; import { env as penv } from 'node:process'; -import { injectFromHierarchy, injectable } from 'inversify'; +import { inject, injectFromHierarchy, injectable } from 'inversify'; import { BasePrepareService } from '../../prepare-tool/base-prepare.service.ts'; +import { AptService } from '../../services/index.ts'; import { fileContent, parse } from '../../utils/index.ts'; import { NodeBaseInstallService, @@ -13,10 +14,18 @@ import { @injectable() @injectFromHierarchy() export class NodePrepareService extends BasePrepareService { + @inject(AptService) + private readonly aptSvc!: AptService; + override name = 'node'; - /** Initializes the cache and links the user's npm and yarn folders to it. */ + /** + * Installs `libatomic1`, which the official node 26.13.0+ binaries need, + * then initializes the cache and links the user's npm and yarn folders to it. + */ override async prepare(): Promise { + // https://github.com/nodejs/node/issues/60790 + await this.aptSvc.install('libatomic1'); await this.initialize(); await prepareSymlinks(this.envSvc, this.pathSvc); } diff --git a/test/node/Dockerfile b/test/node/Dockerfile index b56d354f9a..81c255c665 100644 --- a/test/node/Dockerfile +++ b/test/node/Dockerfile @@ -917,6 +917,10 @@ FROM build AS test-vp USER root +# pin the node vp's setup downloads, it uses the latest lts otherwise +# renovate: datasource=github-releases packageName=containerbase/node-prebuild versioning=node +ARG VP_SETUP_NODE_VERSION=24.22.1 + # renovate: datasource=github-releases depName=vp packageName=voidzero-dev/vite-plus ARG VP_VERSION=1.4.0 RUN install-tool vp "${VP_VERSION}" diff --git a/test/node/Dockerfile.arm64 b/test/node/Dockerfile.arm64 index 44dd3152d1..f3fa71e765 100644 --- a/test/node/Dockerfile.arm64 +++ b/test/node/Dockerfile.arm64 @@ -85,6 +85,10 @@ RUN install-tool renovate 44.181.8 #-------------------------------------- FROM test-node AS test-vp +# pin the node vp's setup downloads, it uses the latest lts otherwise +# renovate: datasource=github-releases packageName=containerbase/node-prebuild versioning=node +ARG VP_SETUP_NODE_VERSION=24.22.1 + # renovate: datasource=github-releases depName=vp packageName=voidzero-dev/vite-plus ARG VP_VERSION=1.4.0 RUN install-tool vp "${VP_VERSION}"