Skip to content

Commit

Permalink
feat(lerna): use docker exec (#6407)
Browse files Browse the repository at this point in the history
Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
  • Loading branch information
rarkins and viceice committed Jun 2, 2020
1 parent 93e7209 commit 6516cc1
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,44 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`generateLockFiles() allows scripts for trust level high 1`] = `
Array [
Object {
"cmd": "npm install --package-lock-only --no-audit",
"options": Object {
"cwd": "some-dir",
"encoding": "utf-8",
"env": Object {
"HOME": "/home/user",
"HTTPS_PROXY": "https://example.com",
"HTTP_PROXY": "http://example.com",
"LANG": "en_US.UTF-8",
"LC_ALL": "en_US",
"NO_PROXY": "localhost",
"PATH": "/tmp/path",
},
"timeout": 900000,
},
},
Object {
"cmd": "npx lerna@latest bootstrap --no-ci -- --package-lock-only --no-audit",
"options": Object {
"cwd": "some-dir",
"encoding": "utf-8",
"env": Object {
"HOME": "/home/user",
"HTTPS_PROXY": "https://example.com",
"HTTP_PROXY": "http://example.com",
"LANG": "en_US.UTF-8",
"LC_ALL": "en_US",
"NO_PROXY": "localhost",
"PATH": "/tmp/path",
},
"timeout": 900000,
},
},
]
`;

exports[`generateLockFiles() defaults to latest 1`] = `
Array [
Object {
Expand Down Expand Up @@ -117,6 +156,45 @@ Array [
]
`;

exports[`generateLockFiles() maps dot files 1`] = `
Array [
Object {
"cmd": "npm install --package-lock-only --no-audit",
"options": Object {
"cwd": "some-dir",
"encoding": "utf-8",
"env": Object {
"HOME": "/home/user",
"HTTPS_PROXY": "https://example.com",
"HTTP_PROXY": "http://example.com",
"LANG": "en_US.UTF-8",
"LC_ALL": "en_US",
"NO_PROXY": "localhost",
"PATH": "/tmp/path",
},
"timeout": 900000,
},
},
Object {
"cmd": "npx lerna@latest bootstrap --no-ci -- --package-lock-only --no-audit",
"options": Object {
"cwd": "some-dir",
"encoding": "utf-8",
"env": Object {
"HOME": "/home/user",
"HTTPS_PROXY": "https://example.com",
"HTTP_PROXY": "http://example.com",
"LANG": "en_US.UTF-8",
"LC_ALL": "en_US",
"NO_PROXY": "localhost",
"PATH": "/tmp/path",
},
"timeout": 900000,
},
},
]
`;

exports[`generateLockFiles() performs full npm install 1`] = `
Array [
Object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { exec as _exec } from 'child_process';
import { envMock, mockExecAll } from '../../../../test/execUtil';
import { mocked } from '../../../../test/util';
import * as _lernaHelper from '../../../manager/npm/post-update/lerna';
import { platform as _platform } from '../../../platform';
import * as _env from '../../../util/exec/env';
import * as _lernaHelper from './lerna';

jest.mock('child_process');
jest.mock('../../../util/exec/env');
jest.mock('../../../manager/npm/post-update/node-version');

const exec: jest.Mock<typeof _exec> = _exec as any;
const env = mocked(_env);
Expand All @@ -20,7 +21,16 @@ describe('generateLockFiles()', () => {
env.getChildProcessEnv.mockReturnValue(envMock.basic);
});
it('returns if no lernaClient', async () => {
const res = await lernaHelper.generateLockFiles(undefined, 'some-dir', {});
const res = await lernaHelper.generateLockFiles(
undefined,
'some-dir',
{},
{}
);
expect(res.error).toBe(false);
});
it('returns if invalid lernaClient', async () => {
const res = await lernaHelper.generateLockFiles('foo', 'some-dir', {}, {});
expect(res.error).toBe(false);
});
it('generates package-lock.json files', async () => {
Expand Down Expand Up @@ -60,14 +70,35 @@ describe('generateLockFiles()', () => {
JSON.stringify({ devDependencies: { lerna: '2.0.0' } })
);
const execSnapshots = mockExecAll(exec);
const res = await lernaHelper.generateLockFiles('yarn', 'some-dir', {});
expect(res.error).toBe(false);
const res = await lernaHelper.generateLockFiles('yarn', 'some-dir', {}, {});
expect(execSnapshots).toMatchSnapshot();
expect(res.error).toBe(false);
});
it('defaults to latest', async () => {
platform.getFile.mockReturnValueOnce(undefined);
const execSnapshots = mockExecAll(exec);
const res = await lernaHelper.generateLockFiles('npm', 'some-dir', {});
const res = await lernaHelper.generateLockFiles('npm', 'some-dir', {}, {});
expect(res.error).toBe(false);
expect(execSnapshots).toMatchSnapshot();
});
it('maps dot files', async () => {
platform.getFile.mockReturnValueOnce(undefined);
const execSnapshots = mockExecAll(exec);
const res = await lernaHelper.generateLockFiles(
'npm',
'some-dir',
{ dockerMapDotfiles: true },
{}
);
expect(res.error).toBe(false);
expect(execSnapshots).toMatchSnapshot();
});
it('allows scripts for trust level high', async () => {
platform.getFile.mockReturnValueOnce(undefined);
const execSnapshots = mockExecAll(exec);
global.trustLevel = 'high';
const res = await lernaHelper.generateLockFiles('npm', 'some-dir', {}, {});
delete global.trustLevel;
expect(res.error).toBe(false);
expect(execSnapshots).toMatchSnapshot();
});
Expand Down
91 changes: 56 additions & 35 deletions lib/manager/npm/post-update/lerna.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import semver from 'semver';
import { quote } from 'shlex';
import { join } from 'upath';
import { logger } from '../../../logger';
import { platform } from '../../../platform';
import { exec } from '../../../util/exec';
import { ExecOptions, exec } from '../../../util/exec';
import { PostUpdateConfig } from '../../common';
import { getNodeConstraint } from './node-version';
import { optimizeCommand } from './yarn';

export interface GenerateLockFileResult {
error?: boolean;
Expand All @@ -13,19 +17,59 @@ export async function generateLockFiles(
lernaClient: string,
cwd: string,
config: PostUpdateConfig,
env?: NodeJS.ProcessEnv,
env: NodeJS.ProcessEnv,
skipInstalls?: boolean
): Promise<GenerateLockFileResult> {
if (!lernaClient) {
logger.warn('No lernaClient specified - returning');
return { error: false };
}
logger.debug(`Spawning lerna with ${lernaClient} to create lock files`);
const cmd: string[] = [];
// const envVars = ['NPM_CONFIG_CACHE', 'npm_config_store'];
const preCommands = [];
const cmd = [];
let cmdOptions = '';
try {
if (lernaClient === 'yarn') {
preCommands.push('npm i -g yarn');
if (skipInstalls !== false) {
preCommands.push(optimizeCommand);
}
cmdOptions = '--ignore-scripts --ignore-engines --ignore-platform';
} else if (lernaClient === 'npm') {
if (skipInstalls === false) {
cmdOptions = '--ignore-scripts --no-audit';
} else {
cmdOptions = '--package-lock-only --no-audit';
}
} else {
logger.warn({ lernaClient }, 'Unknown lernaClient');
return { error: false };
}
if (global.trustLevel === 'high' && config.ignoreScripts !== false) {
cmdOptions = cmdOptions.replace('--ignore-scripts ', '');
}
const tagConstraint = await getNodeConstraint(config.packageFile);
const execOptions: ExecOptions = {
cwd,
extraEnv: {
NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE,
npm_config_store: env.npm_config_store,
},
docker: {
image: 'renovate/node',
tagScheme: 'npm',
tagConstraint,
preCommands,
},
};
if (config.dockerMapDotfiles) {
const homeDir =
process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
const homeNpmrc = join(homeDir, '.npmrc');
execOptions.docker.volumes = [[homeNpmrc, '/home/ubuntu/.npmrc']];
}
cmd.push(`${lernaClient} install ${cmdOptions}`);
let lernaVersion: string;
// const volumes: VolumeOption[] = [];
try {
const pJson = JSON.parse(await platform.getFile('package.json'));
lernaVersion =
Expand All @@ -34,37 +78,14 @@ export async function generateLockFiles(
} catch (err) {
logger.warn('Could not detect lerna version in package.json');
}
lernaVersion = lernaVersion || 'latest';
logger.debug('Using lerna version ' + lernaVersion);
let params: string;
if (lernaClient === 'npm') {
if (skipInstalls === false) {
params = '--ignore-scripts --no-audit';
} else {
params = '--package-lock-only --no-audit';
}
} else {
params = '--ignore-scripts --ignore-engines --ignore-platform';
if (!lernaVersion || !semver.validRange(lernaVersion)) {
lernaVersion = 'latest';
}

// // istanbul ignore if
// if (config.dockerMapDotfiles) {
// const homeDir =
// process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
// const homeNpmrc = join(homeDir, '.npmrc');
// volumes.push([homeNpmrc, `/home/ubuntu/.npmrc`]);
// }
cmd.push(`${lernaClient} install ${params}`);
cmd.push(`npx lerna@${quote(lernaVersion)} bootstrap --no-ci -- ${params}`);
await exec(cmd, {
cwd,
env,
// docker: {
// image: `renovate/${lernaClient}`,
// volumes,
// envVars,
// },
});
logger.debug('Using lerna version ' + lernaVersion);
cmd.push(
`npx lerna@${quote(lernaVersion)} bootstrap --no-ci -- ${cmdOptions}`
);
await exec(cmd, execOptions);
} catch (err) /* istanbul ignore next */ {
logger.debug(
{
Expand Down
7 changes: 4 additions & 3 deletions lib/manager/npm/post-update/yarn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export async function hasYarnOfflineMirror(cwd: string): Promise<boolean> {
return false;
}

export const optimizeCommand =
"sed -i 's/ steps,/ steps.slice(0,1),/' /home/ubuntu/.npm-global/lib/node_modules/yarn/lib/cli.js";

export async function generateLockFile(
cwd: string,
env: NodeJS.ProcessEnv,
Expand All @@ -47,9 +50,7 @@ export async function generateLockFile(
) {
logger.debug('Updating yarn.lock only - skipping node_modules');
// The following change causes Yarn 1.x to exit gracefully after updating the lock file but without installing node_modules
preCommands.push(
"sed -i 's/ steps,/ steps.slice(0,1),/' /home/ubuntu/.npm-global/lib/node_modules/yarn/lib/cli.js"
);
preCommands.push(optimizeCommand);
}
const commands = [];
let cmdOptions = '--network-timeout 100000';
Expand Down

0 comments on commit 6516cc1

Please sign in to comment.