Skip to content

Commit

Permalink
feat(manager/npm): prepare for buildpack support (#16979)
Browse files Browse the repository at this point in the history
* feat(manager/npm): prepare for buildpack support

* chore: fixes
  • Loading branch information
viceice authored Aug 4, 2022
1 parent 60609dc commit 3b699e9
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 24 deletions.
12 changes: 0 additions & 12 deletions lib/modules/manager/npm/post-update/__snapshots__/npm.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`modules/manager/npm/post-update/npm catches errors 1`] = `Array []`;

exports[`modules/manager/npm/post-update/npm finds npm globally 1`] = `Array []`;

exports[`modules/manager/npm/post-update/npm generates lock files 1`] = `
Array [
Object {
Expand Down Expand Up @@ -45,8 +41,6 @@ Array [
]
`;

exports[`modules/manager/npm/post-update/npm performs full install 1`] = `Array []`;

exports[`modules/manager/npm/post-update/npm performs lock file maintenance 1`] = `
Array [
Object {
Expand Down Expand Up @@ -202,9 +196,3 @@ Array [
},
]
`;

exports[`modules/manager/npm/post-update/npm performs npm-shrinkwrap.json updates (no package-lock.json) 1`] = `Array []`;

exports[`modules/manager/npm/post-update/npm performs npm-shrinkwrap.json updates 1`] = `Array []`;

exports[`modules/manager/npm/post-update/npm uses docker npm 1`] = `Array []`;
26 changes: 25 additions & 1 deletion lib/modules/manager/npm/post-update/node-version.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { fs } from '../../../../../test/util';
import { getNodeConstraint, getNodeUpdate } from './node-version';
import {
getNodeConstraint,
getNodeToolConstraint,
getNodeUpdate,
} from './node-version';

jest.mock('../../../../util/fs');

Expand Down Expand Up @@ -56,4 +60,24 @@ describe('modules/manager/npm/post-update/node-version', () => {
expect(getNodeUpdate([])).toBeUndefined();
});
});

describe('getNodeToolContraint()', () => {
it('returns getNodeUpdate', async () => {
expect(
await getNodeToolConstraint(config, [
{ depName: 'node', newValue: '16.15.0' },
])
).toEqual({
toolName: 'node',
constraint: '16.15.0',
});
});

it('returns getNodeConstraint', async () => {
expect(await getNodeToolConstraint(config, [])).toEqual({
toolName: 'node',
constraint: '^12.16.0',
});
});
});
});
19 changes: 17 additions & 2 deletions lib/modules/manager/npm/post-update/node-version.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import semver from 'semver';
import { logger } from '../../../../logger';
import type { ToolConstraint } from '../../../../util/exec/types';
import { getSiblingFileName, readLocalFile } from '../../../../util/fs';
import { newlineRegex, regEx } from '../../../../util/regex';
import type { PostUpdateConfig, Upgrade } from '../../types';
Expand Down Expand Up @@ -35,9 +36,10 @@ export async function getNodeConstraint(
config: Partial<PostUpdateConfig>
): Promise<string | null> {
const { packageFile } = config;
// TODO: fix types (#7154)
const constraint =
(await getNodeFile(getSiblingFileName(packageFile, '.nvmrc'))) ??
(await getNodeFile(getSiblingFileName(packageFile, '.node-version'))) ??
(await getNodeFile(getSiblingFileName(packageFile!, '.nvmrc'))) ??
(await getNodeFile(getSiblingFileName(packageFile!, '.node-version'))) ??
getPackageJsonConstraint(config);
if (!constraint) {
logger.debug('No node constraint found - using latest');
Expand All @@ -48,3 +50,16 @@ export async function getNodeConstraint(
export function getNodeUpdate(upgrades: Upgrade[]): string | undefined {
return upgrades.find((u) => u.depName === 'node')?.newValue;
}

export async function getNodeToolConstraint(
config: Partial<PostUpdateConfig>,
upgrades: Upgrade[]
): Promise<ToolConstraint> {
const constraint =
getNodeUpdate(upgrades) ?? (await getNodeConstraint(config));

return {
toolName: 'node',
constraint,
};
}
91 changes: 84 additions & 7 deletions lib/modules/manager/npm/post-update/npm.spec.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import upath from 'upath';
import { envMock, mockExecAll } from '../../../../../test/exec-util';
import { Fixtures } from '../../../../../test/fixtures';
import { env, fs } from '../../../../../test/util';
import { env, fs, mockedFunction } from '../../../../../test/util';
import { GlobalConfig } from '../../../../config/global';
import { getNodeToolConstraint } from './node-version';
import * as npmHelper from './npm';

jest.mock('../../../../util/exec/env');
jest.mock('../../../../util/fs');
jest.mock('./node-version');

process.env.BUILDPACK = 'true';

describe('modules/manager/npm/post-update/npm', () => {
beforeEach(() => {
jest.resetAllMocks();
jest.resetModules();
env.getChildProcessEnv.mockReturnValue(envMock.basic);
GlobalConfig.set({ localDir: '' });
mockedFunction(getNodeToolConstraint).mockResolvedValueOnce({
toolName: 'node',
constraint: '16.16.0',
});
});

it('generates lock files', async () => {
Expand Down Expand Up @@ -109,7 +116,8 @@ describe('modules/manager/npm/post-update/npm', () => {
);
expect(res.error).toBeUndefined();
expect(res.lockFile).toBe('package-lock-contents');
expect(execSnapshots).toMatchSnapshot();
// TODO: is that right?
expect(execSnapshots).toEqual([]);
});

it('performs npm-shrinkwrap.json updates (no package-lock.json)', async () => {
Expand All @@ -131,7 +139,8 @@ describe('modules/manager/npm/post-update/npm', () => {
);
expect(res.error).toBeUndefined();
expect(res.lockFile).toBe('package-lock-contents');
expect(execSnapshots).toMatchSnapshot();
// TODO: is that right?
expect(execSnapshots).toEqual([]);
});

it('performs full install', async () => {
Expand All @@ -148,7 +157,8 @@ describe('modules/manager/npm/post-update/npm', () => {
expect(fs.readLocalFile).toHaveBeenCalledTimes(1);
expect(res.error).toBeUndefined();
expect(res.lockFile).toBe('package-lock-contents');
expect(execSnapshots).toMatchSnapshot();
// TODO: is that right?
expect(execSnapshots).toEqual([]);
});

it('runs twice if remediating', async () => {
Expand Down Expand Up @@ -181,7 +191,7 @@ describe('modules/manager/npm/post-update/npm', () => {
expect(fs.readLocalFile).toHaveBeenCalledTimes(1);
expect(res.error).toBeTrue();
expect(res.lockFile).toBeUndefined();
expect(execSnapshots).toMatchSnapshot();
expect(execSnapshots).toEqual([]);
});

it('finds npm globally', async () => {
Expand All @@ -194,7 +204,8 @@ describe('modules/manager/npm/post-update/npm', () => {
);
expect(fs.readLocalFile).toHaveBeenCalledTimes(1);
expect(res.lockFile).toBe('package-lock-contents');
expect(execSnapshots).toMatchSnapshot();
// TODO: is that right?
expect(execSnapshots).toEqual([]);
});

it('uses docker npm', async () => {
Expand All @@ -208,7 +219,8 @@ describe('modules/manager/npm/post-update/npm', () => {
);
expect(fs.readLocalFile).toHaveBeenCalledTimes(1);
expect(res.lockFile).toBe('package-lock-contents');
expect(execSnapshots).toMatchSnapshot();
// TODO: is that right?
expect(execSnapshots).toEqual([]);
});

it('performs lock file maintenance', async () => {
Expand All @@ -226,4 +238,69 @@ describe('modules/manager/npm/post-update/npm', () => {
expect(res.lockFile).toBe('package-lock-contents');
expect(execSnapshots).toMatchSnapshot();
});

it('works for docker mode', async () => {
GlobalConfig.set({
localDir: '',
cacheDir: '/tmp',
binarySource: 'docker',
allowScripts: true,
});
const execSnapshots = mockExecAll();
fs.readLocalFile.mockResolvedValue('package-lock-contents');
const res = await npmHelper.generateLockFile(
'some-dir',
{},
'package-lock.json',
{ constraints: { npm: '6.0.0' } },
[{ isLockFileMaintenance: true }]
);
expect(fs.readLocalFile).toHaveBeenCalledTimes(1);
expect(res.lockFile).toBe('package-lock-contents');
expect(execSnapshots).toMatchObject([
{ cmd: 'docker pull renovate/node' },
{ cmd: 'docker ps --filter name=renovate_node -aq' },
{
cmd:
'docker run --rm --name=renovate_node --label=renovate_child ' +
'-v "/tmp":"/tmp" ' +
'-e BUILDPACK_CACHE_DIR ' +
'-w "some-dir" ' +
'renovate/node ' +
'bash -l -c "' +
'install-tool npm 6.0.0 ' +
'&& ' +
'hash -d npm 2>/dev/null || true ' +
'&& ' +
'npm install --package-lock-only --no-audit' +
'"',
},
]);
});

it('works for install mode', async () => {
GlobalConfig.set({
localDir: '',
cacheDir: '/tmp',
binarySource: 'install',
});
const execSnapshots = mockExecAll();
fs.readLocalFile.mockResolvedValue('package-lock-contents');
const res = await npmHelper.generateLockFile(
'some-dir',
{},
'package-lock.json',
{ constraints: { npm: '6.0.0' } },
[{ isLockFileMaintenance: true }]
);
expect(fs.readLocalFile).toHaveBeenCalledTimes(1);
expect(res.lockFile).toBe('package-lock-contents');
expect(execSnapshots).toMatchObject([
{ cmd: 'install-tool npm 6.0.0' },
{ cmd: 'hash -d npm 2>/dev/null || true' },
{
cmd: 'npm install --package-lock-only --no-audit --ignore-scripts',
},
]);
});
});
59 changes: 59 additions & 0 deletions lib/modules/manager/npm/post-update/pnpm.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jest.mock('../../../../util/fs');
jest.mock('./node-version');

delete process.env.NPM_CONFIG_CACHE;
process.env.BUILDPACK = 'true';

describe('modules/manager/npm/post-update/pnpm', () => {
let config: PostUpdateConfig;
Expand Down Expand Up @@ -178,4 +179,62 @@ describe('modules/manager/npm/post-update/pnpm', () => {
expect(fs.readLocalFile).toHaveBeenCalledTimes(3);
expect(res.lockFile).toBe('lockfileVersion: 5.3\n');
});

it('works for docker mode', async () => {
GlobalConfig.set({
localDir: '',
cacheDir: '/tmp',
binarySource: 'docker',
allowScripts: true,
});
const execSnapshots = mockExecAll();
fs.readLocalFile.mockResolvedValue('package-lock-contents');
const res = await pnpmHelper.generateLockFile(
'some-dir',
{},
{ ...config, constraints: { pnpm: '6.0.0' } }
);
expect(fs.readLocalFile).toHaveBeenCalledTimes(1);
expect(res.lockFile).toBe('package-lock-contents');
expect(execSnapshots).toMatchObject([
{ cmd: 'docker pull renovate/node' },
{ cmd: 'docker ps --filter name=renovate_node -aq' },
{
cmd:
'docker run --rm --name=renovate_node --label=renovate_child ' +
'-v "/tmp":"/tmp" ' +
'-e BUILDPACK_CACHE_DIR ' +
'-w "some-dir" ' +
'renovate/node ' +
'bash -l -c "' +
'install-tool pnpm 6.0.0 ' +
'&& ' +
'pnpm install --recursive --lockfile-only' +
'"',
},
]);
});

it('works for install mode', async () => {
GlobalConfig.set({
localDir: '',
cacheDir: '/tmp',
binarySource: 'install',
});
const execSnapshots = mockExecAll();
fs.readLocalFile.mockResolvedValue('package-lock-contents');
const res = await pnpmHelper.generateLockFile(
'some-dir',
{},
{ ...config, constraints: { pnpm: '6.0.0' } }
);
expect(fs.readLocalFile).toHaveBeenCalledTimes(1);
expect(res.lockFile).toBe('package-lock-contents');
expect(execSnapshots).toMatchObject([
{ cmd: 'install-tool pnpm 6.0.0' },
{
cmd: 'pnpm install --recursive --lockfile-only --ignore-scripts --ignore-pnpmfile',
},
]);
});
});
2 changes: 2 additions & 0 deletions lib/modules/manager/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ export interface PostUpdateConfig<T = Record<string, any>>
skipInstalls?: boolean;
ignoreScripts?: boolean;

packageFile?: string;

upgrades: Upgrade[];
npmLock?: string;
yarnLock?: string;
Expand Down
4 changes: 2 additions & 2 deletions lib/util/exec/buildpack.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ describe('util/exec/buildpack', () => {
process.env.BUILDPACK = 'true';
const toolConstraints: ToolConstraint[] = [
{ toolName: 'node' },
{ toolName: 'npm' },
{ toolName: 'invalid' },
];
expect(isDynamicInstall(toolConstraints)).toBeFalse();
});

it('returns false if supported tools', () => {
it('returns true if supported tools', () => {
GlobalConfig.set({ binarySource: 'install' });
process.env.BUILDPACK = 'true';
const toolConstraints: ToolConstraint[] = [{ toolName: 'npm' }];
Expand Down
5 changes: 5 additions & 0 deletions lib/util/exec/buildpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ const allToolConfig: Record<string, ToolConfig> = {
depName: 'jsonnet-bundler/jsonnet-bundler',
versioning: semverVersioningId,
},
node: {
datasource: 'node',
depName: 'node',
versioning: npmVersioningId,
},
npm: {
datasource: 'npm',
depName: 'npm',
Expand Down

0 comments on commit 3b699e9

Please sign in to comment.