From be67fb432c71cc75201bb8b381b097f7bee0ce37 Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Wed, 24 Jul 2024 12:30:52 +0200 Subject: [PATCH] feat(node)!: require prepare, drop prefix config, redirect home --- src/cli/prepare-tool/index.ts | 2 + src/cli/tools/index.ts | 1 - src/cli/tools/node/index.ts | 83 ++++++++++++++--------------------- src/cli/tools/node/utils.ts | 28 ++++++++++++ test/node/Dockerfile | 6 ++- 5 files changed, 67 insertions(+), 53 deletions(-) diff --git a/src/cli/prepare-tool/index.ts b/src/cli/prepare-tool/index.ts index 373cc25e3..77434fe97 100644 --- a/src/cli/prepare-tool/index.ts +++ b/src/cli/prepare-tool/index.ts @@ -9,6 +9,7 @@ import { PrepareJavaJreService, PrepareJavaService, } from '../tools/java'; +import { PrepareNodeService } from '../tools/node'; import { logger } from '../utils'; import { PrepareLegacyToolsService } from './prepare-legacy-tools.service'; import { PREPARE_TOOL_TOKEN, PrepareToolService } from './prepare-tool.service'; @@ -30,6 +31,7 @@ function prepareContainer(): Container { container.bind(PREPARE_TOOL_TOKEN).to(PrepareJavaService); container.bind(PREPARE_TOOL_TOKEN).to(PrepareJavaJreService); container.bind(PREPARE_TOOL_TOKEN).to(PrepareJavaJdkService); + container.bind(PREPARE_TOOL_TOKEN).to(PrepareNodeService); logger.trace('preparing container done'); return container; diff --git a/src/cli/tools/index.ts b/src/cli/tools/index.ts index 896be4c0a..9b68c6c24 100644 --- a/src/cli/tools/index.ts +++ b/src/cli/tools/index.ts @@ -13,7 +13,6 @@ export const NoPrepareTools = [ 'gradle', 'lerna', 'maven', - 'node', 'npm', 'pnpm', 'renovate', diff --git a/src/cli/tools/node/index.ts b/src/cli/tools/node/index.ts index 627ee9c1f..e19b0a583 100644 --- a/src/cli/tools/node/index.ts +++ b/src/cli/tools/node/index.ts @@ -1,9 +1,9 @@ import fs from 'node:fs/promises'; import { join } from 'node:path'; import { env as penv } from 'node:process'; -import { codeBlock } from 'common-tags'; import { execa } from 'execa'; import { inject, injectable } from 'inversify'; +import { PrepareToolBaseService } from '../../prepare-tool/prepare-tool-base.service'; import { CompressionService, EnvService, @@ -14,15 +14,32 @@ import { import { getDistro, parse } from '../../utils'; import { InstallNodeBaseService, - prepareGlobalConfig, - prepareUserConfig, + prepareNpmCache, + prepareNpmrc, + prepareSymlinks, } from './utils'; +@injectable() +export class PrepareNodeService extends PrepareToolBaseService { + override name = 'node'; + override async execute(): Promise { + await prepareNpmCache(this.pathSvc); + await prepareNpmrc(this.pathSvc); + await prepareSymlinks(this.envSvc, this.pathSvc); + + await this.pathSvc.exportToolEnv(this.name, { + NO_UPDATE_NOTIFIER: '1', + npm_config_update_notifier: 'false', + npm_config_fund: 'false', + }); + } +} + @injectable() export class InstallNodeService extends InstallNodeBaseService { readonly name = 'node'; - private get arch(): string { + private get nodeArch(): string { switch (this.envSvc.arch) { case 'arm64': return 'arm64'; @@ -51,10 +68,7 @@ export class InstallNodeService extends InstallNodeBaseService { } override async install(version: string): Promise { - const distro = await getDistro(); - const arch = this.arch; const name = this.name; - const versionCode = distro.versionCode; let filename = `${version}/${name}-${version}-${this.ghArch}.tar.xz`; let checksumFileUrl = `https://github.com/containerbase/${name}-prebuild/releases/download/${filename}.sha512`; let isOnGithub = await this.http.exists(checksumFileUrl); @@ -62,25 +76,21 @@ export class InstallNodeService extends InstallNodeBaseService { if (isOnGithub) { // no distro specific prebuilds - const checksumFile = await this.http.download({ url: checksumFileUrl }); - const expectedChecksum = ( - await fs.readFile(checksumFile, 'utf-8') - ).trim(); + const expectedChecksum = await this.getChecksum(checksumFileUrl); file = await this.http.download({ url: `https://github.com/containerbase/${name}-prebuild/releases/download/${filename}`, checksumType: 'sha512', expectedChecksum, }); } else { + const distro = await getDistro(); + const versionCode = distro.versionCode; // distro specific prebuilds filename = ` ${version}/${name}-${version}-${versionCode}-${this.ghArch}.tar.xz`; checksumFileUrl = `https://github.com/containerbase/${name}-prebuild/releases/download/${filename}.sha512`; isOnGithub = await this.http.exists(checksumFileUrl); if (isOnGithub) { - const checksumFile = await this.http.download({ url: checksumFileUrl }); - const expectedChecksum = ( - await fs.readFile(checksumFile, 'utf-8') - ).trim(); + const expectedChecksum = await this.getChecksum(checksumFileUrl); file = await this.http.download({ url: `https://github.com/containerbase/${name}-prebuild/releases/download/${filename}`, checksumType: 'sha512', @@ -89,7 +99,7 @@ export class InstallNodeService extends InstallNodeBaseService { } else { // fallback to nodejs.org checksumFileUrl = `https://nodejs.org/dist/v${version}/SHASUMS256.txt`; - filename = `${name}-v${version}-linux-${arch}.tar.xz`; + filename = `${name}-v${version}-linux-${this.nodeArch}.tar.xz`; const checksumFile = await this.http.download({ url: checksumFileUrl }); const expectedChecksum = (await fs.readFile(checksumFile, 'utf-8')) .split('\n') @@ -108,23 +118,6 @@ export class InstallNodeService extends InstallNodeBaseService { const path = await this.pathSvc.createVersionedToolPath(this.name, version); await this.compress.extract({ file, cwd: path, strip: 1 }); - if (this.envSvc.isRoot) { - await prepareGlobalConfig({ - prefix: '/usr/local', - versionedToolPath: path, - }); - await prepareUserConfig({ - prefix: `${this.envSvc.userHome}/.npm-global`, - home: this.envSvc.userHome, - name: this.envSvc.userName, - }); - } else { - await prepareGlobalConfig({ - prefix: `${this.envSvc.userHome}/.npm-global`, - versionedToolPath: path, - }); - } - const ver = parse(version); if (ver.major < 15) { const tmp = await fs.mkdtemp( @@ -142,24 +135,6 @@ export class InstallNodeService extends InstallNodeBaseService { force: true, }); } - - if (!(await this.pathSvc.toolEnvExists(this.name))) { - await this.pathSvc.exportToolEnv(this.name, { - NO_UPDATE_NOTIFIER: '1', - npm_config_update_notifier: 'false', - npm_config_fund: 'false', - }); - - await this.pathSvc.exportToolEnvContent( - this.name, - codeBlock` - # openshift override unknown user home - if [ "\${EUID}" != 0 ] && [ "\${EUID}" != ${this.envSvc.userId} ]; then - export npm_config_prefix="${this.envSvc.userHome}/.npm-global" - fi - `, - ); - } } override async link(version: string): Promise { @@ -194,4 +169,10 @@ export class InstallNodeService extends InstallNodeBaseService { }); } } + + private async getChecksum(checksumFileUrl: string): Promise { + const checksumFile = await this.http.download({ url: checksumFileUrl }); + const expectedChecksum = (await fs.readFile(checksumFile, 'utf-8')).trim(); + return expectedChecksum; + } } diff --git a/src/cli/tools/node/utils.ts b/src/cli/tools/node/utils.ts index 331ab8218..d0a23684f 100644 --- a/src/cli/tools/node/utils.ts +++ b/src/cli/tools/node/utils.ts @@ -276,3 +276,31 @@ async function readPackageJson(path: string): Promise { const data = await readFile(path, { encoding: 'utf8' }); return JSON.parse(data); } + +export async function prepareNpmCache(pathSvc: PathService): Promise { + const path = join(pathSvc.homePath, '.npm'); + if (!(await pathExists(path, true))) { + await pathSvc.createDir(path); + } +} + +export async function prepareNpmrc(pathSvc: PathService): Promise { + const path = join(pathSvc.homePath, '.npmrc'); + if (!(await pathExists(path, false))) { + await fs.writeFile(path, ''); + } +} + +export async function prepareSymlinks( + envSvc: EnvService, + pathSvc: PathService, +): Promise { + await fs.symlink( + join(pathSvc.homePath, '.npm'), + join(envSvc.userHome, '.npm'), + ); + await fs.symlink( + join(pathSvc.homePath, '.npmrc'), + join(envSvc.userHome, '.npmrc'), + ); +} diff --git a/test/node/Dockerfile b/test/node/Dockerfile index 3d2289bd0..d37d4bcab 100644 --- a/test/node/Dockerfile +++ b/test/node/Dockerfile @@ -109,6 +109,8 @@ RUN set -ex; cd a; pnpm i FROM base AS testd +RUN prepare-tool node + USER 1000 # renovate: datasource=node @@ -230,7 +232,7 @@ ARG CONTAINERBASE_DEBUG RUN install-tool node v14.18.1 RUN install-tool node v14.18.2 -RUN cat $USER_HOME/.npmrc | grep "prefix = \"$USER_HOME/.npm-global\"" +RUN set -ex; ls -la $USER_HOME/; test -L $USER_HOME/.npmrc RUN touch /.dummy @@ -453,6 +455,8 @@ RUN set -ex; \ #-------------------------------------- FROM base AS testq +RUN prepare-tool node + # install latest version RUN install-tool node RUN install-tool yarn