Skip to content

Commit

Permalink
fix(npm): delete lock files before lock file maintenance
Browse files Browse the repository at this point in the history
  • Loading branch information
rarkins committed Jun 3, 2020
1 parent 2216762 commit a3d7159
Show file tree
Hide file tree
Showing 11 changed files with 248 additions and 10 deletions.
1 change: 1 addition & 0 deletions lib/manager/common.ts
Expand Up @@ -193,6 +193,7 @@ export interface Upgrade<T = Record<string, any>>
toVersion?: string;
updateType?: UpdateType;
version?: string;
isLockFileMaintenance?: boolean;
}

export interface ArtifactError {
Expand Down
22 changes: 22 additions & 0 deletions lib/manager/npm/post-update/__snapshots__/npm.spec.ts.snap
Expand Up @@ -45,6 +45,28 @@ Array [

exports[`generateLockFile performs full install 1`] = `Array []`;

exports[`generateLockFile performs lock file maintenance 1`] = `
Array [
Object {
"cmd": "npm install --package-lock-only --ignore-scripts --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[`generateLockFile performs lock file updates 1`] = `
Array [
Object {
Expand Down
22 changes: 22 additions & 0 deletions lib/manager/npm/post-update/__snapshots__/pnpm.spec.ts.snap
Expand Up @@ -65,3 +65,25 @@ Array [
},
]
`;

exports[`generateLockFile performs lock file maintenance 1`] = `
Array [
Object {
"cmd": "pnpm install --lockfile-only --ignore-scripts --ignore-pnpmfile",
"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,
},
},
]
`;
90 changes: 90 additions & 0 deletions lib/manager/npm/post-update/__snapshots__/yarn.spec.ts.snap
Expand Up @@ -112,6 +112,96 @@ Array [
]
`;

exports[`manager/npm/post-update/yarn performs lock file maintenance using yarn v1.22.0 1`] = `
Array [
Object {
"cmd": "yarn install --ignore-engines --ignore-platform --network-timeout 100000 --ignore-scripts",
"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 yarn-deduplicate --strategy fewer",
"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": "yarn install --ignore-engines --ignore-platform --network-timeout 100000 --ignore-scripts",
"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 yarn-deduplicate --strategy highest",
"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": "yarn install --ignore-engines --ignore-platform --network-timeout 100000 --ignore-scripts",
"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[`manager/npm/post-update/yarn performs lock file updates and full install using yarn v1.22.0 1`] = `
Array [
Object {
Expand Down
6 changes: 5 additions & 1 deletion lib/manager/npm/post-update/index.ts
Expand Up @@ -572,10 +572,14 @@ export async function getAdditionalFiles(
additionalNpmrcContent
);
logger.debug(`Generating pnpm-lock.yaml for ${lockFileDir}`);
const upgrades = config.upgrades.filter(
(upgrade) => upgrade.pnpmShrinkwrap === lockFile
);
const res = await pnpm.generateLockFile(
upath.join(config.localDir, lockFileDir),
env,
config
config,
upgrades
);
if (res.error) {
// istanbul ignore if
Expand Down
15 changes: 15 additions & 0 deletions lib/manager/npm/post-update/npm.spec.ts
Expand Up @@ -172,4 +172,19 @@ describe('generateLockFile', () => {
expect(res.lockFile).toEqual('package-lock-contents');
expect(execSnapshots).toMatchSnapshot();
});
it('performs lock file maintenance', async () => {
const execSnapshots = mockExecAll(exec);
fs.readFile = jest.fn(() => 'package-lock-contents') as never;
const res = await npmHelper.generateLockFile(
'some-dir',
{},
'package-lock.json',
{},
[{ isLockFileMaintenance: true }]
);
expect(fs.readFile).toHaveBeenCalledTimes(1);
expect(fs.remove).toHaveBeenCalledTimes(1);
expect(res.lockFile).toEqual('package-lock-contents');
expect(execSnapshots).toMatchSnapshot();
});
});
17 changes: 16 additions & 1 deletion lib/manager/npm/post-update/npm.ts
@@ -1,4 +1,4 @@
import { move, pathExists, readFile } from 'fs-extra';
import { move, pathExists, readFile, remove } from 'fs-extra';
import { validRange } from 'semver';
import { quote } from 'shlex';
import { join } from 'upath';
Expand Down Expand Up @@ -88,6 +88,21 @@ export async function generateLockFile(
commands.push('npm dedupe');
}

if (upgrades.find((upgrade) => upgrade.isLockFileMaintenance)) {
const lockFileName = join(cwd, filename);
logger.debug(
`Removing ${lockFileName} first due to lock file maintenance upgrade`
);
try {
await remove(lockFileName);
} catch (err) /* istanbul ignore next */ {
logger.debug(
{ err, lockFileName },
'Error removing yarn.lock for lock file maintenance'
);
}
}

// Run the commands
await exec(commands, execOptions);

Expand Down
11 changes: 11 additions & 0 deletions lib/manager/npm/post-update/pnpm.spec.ts
Expand Up @@ -51,4 +51,15 @@ describe('generateLockFile', () => {
expect(res.lockFile).toEqual('package-lock-contents');
expect(execSnapshots).toMatchSnapshot();
});
it('performs lock file maintenance', async () => {
const execSnapshots = mockExecAll(exec);
fs.readFile = jest.fn(() => 'package-lock-contents') as never;
const res = await pnpmHelper.generateLockFile('some-dir', {}, config, [
{ isLockFileMaintenance: true },
]);
expect(fs.readFile).toHaveBeenCalledTimes(1);
expect(fs.remove).toHaveBeenCalledTimes(1);
expect(res.lockFile).toEqual('package-lock-contents');
expect(execSnapshots).toMatchSnapshot();
});
});
27 changes: 22 additions & 5 deletions lib/manager/npm/post-update/pnpm.ts
@@ -1,10 +1,10 @@
import { readFile } from 'fs-extra';
import { readFile, remove } from 'fs-extra';
import { validRange } from 'semver';
import { quote } from 'shlex';
import { join } from 'upath';
import { logger } from '../../../logger';
import { ExecOptions, exec } from '../../../util/exec';
import { PostUpdateConfig } from '../../common';
import { PostUpdateConfig, Upgrade } from '../../common';
import { getNodeConstraint } from './node-version';

export interface GenerateLockFileResult {
Expand All @@ -17,9 +17,11 @@ export interface GenerateLockFileResult {
export async function generateLockFile(
cwd: string,
env: NodeJS.ProcessEnv,
config: PostUpdateConfig
config: PostUpdateConfig,
upgrades: Upgrade[] = []
): Promise<GenerateLockFileResult> {
logger.debug(`Spawning pnpm install to create ${cwd}/pnpm-lock.yaml`);
const lockFileName = join(cwd, 'pnpm-lock.yaml');
logger.debug(`Spawning pnpm install to create ${lockFileName}`);
let lockFile = null;
let stdout: string;
let stderr: string;
Expand Down Expand Up @@ -58,8 +60,23 @@ export async function generateLockFile(
args += ' --ignore-pnpmfile';
}
logger.debug({ cmd, args }, 'pnpm command');

if (upgrades.find((upgrade) => upgrade.isLockFileMaintenance)) {
logger.debug(
`Removing ${lockFileName} first due to lock file maintenance upgrade`
);
try {
await remove(lockFileName);
} catch (err) /* istanbul ignore next */ {
logger.debug(
{ err, lockFileName },
'Error removing yarn.lock for lock file maintenance'
);
}
}

await exec(`${cmd} ${args}`, execOptions);
lockFile = await readFile(join(cwd, 'pnpm-lock.yaml'), 'utf8');
lockFile = await readFile(lockFileName, 'utf8');
} catch (err) /* istanbul ignore next */ {
logger.debug(
{
Expand Down
26 changes: 26 additions & 0 deletions lib/manager/npm/post-update/yarn.spec.ts
Expand Up @@ -47,6 +47,7 @@ describe(getName(__filename), () => {
};
const res = await yarnHelper.generateLockFile('some-dir', {}, config);
expect(fs.readFile).toHaveBeenCalledTimes(2);
expect(fs.remove).toHaveBeenCalledTimes(0);
expect(res.lockFile).toEqual('package-lock-contents');
expect(fixSnapshots(execSnapshots)).toMatchSnapshot();
}
Expand Down Expand Up @@ -93,6 +94,31 @@ describe(getName(__filename), () => {
expect(fixSnapshots(execSnapshots)).toMatchSnapshot();
}
);
it.each([['1.22.0']])(
'performs lock file maintenance using yarn v%s',
async (yarnVersion) => {
const execSnapshots = mockExecAll(exec, {
stdout: yarnVersion,
stderr: '',
});
fs.readFile.mockResolvedValue(null); // .yarnrc
fs.readFile.mockResolvedValue('package-lock-contents' as never);
const config = {
dockerMapDotfiles: true,
compatibility: {
yarn: '^1.10.0',
},
postUpdateOptions: ['yarnDedupeFewer', 'yarnDedupeHighest'],
};
const res = await yarnHelper.generateLockFile('some-dir', {}, config, [
{ isLockFileMaintenance: true },
]);
expect(fs.readFile).toHaveBeenCalledTimes(2);
expect(fs.remove).toHaveBeenCalledTimes(1);
expect(res.lockFile).toEqual('package-lock-contents');
expect(fixSnapshots(execSnapshots)).toMatchSnapshot();
}
);
it('catches errors', async () => {
const execSnapshots = mockExecAll(exec, {
stdout: '1.9.4',
Expand Down
21 changes: 18 additions & 3 deletions lib/manager/npm/post-update/yarn.ts
@@ -1,5 +1,5 @@
import is from '@sindresorhus/is';
import { readFile } from 'fs-extra';
import { readFile, remove } from 'fs-extra';
import { validRange } from 'semver';
import { quote } from 'shlex';
import { join } from 'upath';
Expand Down Expand Up @@ -42,7 +42,8 @@ export async function generateLockFile(
config: PostUpdateConfig = {},
upgrades: Upgrade[] = []
): Promise<GenerateLockFileResult> {
logger.debug(`Spawning yarn install to create ${cwd}/yarn.lock`);
const lockFileName = join(cwd, 'yarn.lock');
logger.debug(`Spawning yarn install to create ${lockFileName}`);
let lockFile = null;
try {
let installYarn = 'npm i -g yarn';
Expand Down Expand Up @@ -114,11 +115,25 @@ export async function generateLockFile(
commands.push(`yarn install ${cmdOptions}`.trim());
}

if (upgrades.find((upgrade) => upgrade.isLockFileMaintenance)) {
logger.debug(
`Removing ${lockFileName} first due to lock file maintenance upgrade`
);
try {
await remove(lockFileName);
} catch (err) /* istanbul ignore next */ {
logger.debug(
{ err, lockFileName },
'Error removing yarn.lock for lock file maintenance'
);
}
}

// Run the commands
await exec(commands, execOptions);

// Read the result
lockFile = await readFile(join(cwd, 'yarn.lock'), 'utf8');
lockFile = await readFile(lockFileName, 'utf8');
} catch (err) /* istanbul ignore next */ {
logger.debug(
{
Expand Down

0 comments on commit a3d7159

Please sign in to comment.