/
lerna.ts
122 lines (119 loc) · 4.09 KB
/
lerna.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import semver, { validRange } from 'semver';
import { quote } from 'shlex';
import { getAdminConfig } from '../../../config/admin';
import { TEMPORARY_ERROR } from '../../../constants/error-messages';
import { logger } from '../../../logger';
import { ExecOptions, exec } from '../../../util/exec';
import type { PackageFile, PostUpdateConfig } from '../../types';
import { getNodeConstraint } from './node-version';
import { getOptimizeCommand } from './yarn';
export interface GenerateLockFileResult {
error?: boolean;
stderr?: string;
}
// Exported for testability
export function getLernaVersion(
lernaPackageFile: Partial<PackageFile>
): string {
const lernaDep = lernaPackageFile.deps?.find((d) => d.depName === 'lerna');
if (!lernaDep || !semver.validRange(lernaDep.currentValue)) {
logger.warn(
`Could not detect lerna version in ${lernaPackageFile.packageFile}, using 'latest'`
);
return 'latest';
}
return lernaDep.currentValue;
}
export async function generateLockFiles(
lernaPackageFile: Partial<PackageFile>,
cwd: string,
config: PostUpdateConfig,
env: NodeJS.ProcessEnv,
artifactUpdateApproach?: string
): Promise<GenerateLockFileResult> {
const lernaClient = lernaPackageFile.lernaClient;
if (!lernaClient) {
logger.warn('No lernaClient specified - returning');
return { error: false };
}
logger.debug(`Spawning lerna with ${lernaClient} to create lock files`);
const preCommands = [];
const cmd = [];
let cmdOptions = '';
try {
if (lernaClient === 'yarn') {
let installYarn = 'npm i -g yarn';
const yarnCompatibility = config.constraints?.yarn;
if (validRange(yarnCompatibility)) {
installYarn += `@${quote(yarnCompatibility)}`;
}
preCommands.push(installYarn);
if (artifactUpdateApproach !== 'deep') {
preCommands.push(getOptimizeCommand());
}
cmdOptions = '--ignore-scripts --ignore-engines --ignore-platform';
} else if (lernaClient === 'npm') {
let installNpm = 'npm i -g npm';
const npmCompatibility = config.constraints?.npm;
if (validRange(npmCompatibility)) {
installNpm += `@${quote(npmCompatibility)} || true`;
}
preCommands.push(installNpm, 'hash -d npm');
cmdOptions = '--ignore-scripts --no-audit';
if (artifactUpdateApproach !== 'deep') {
cmdOptions += ' --package-lock-only';
}
} else {
logger.warn({ lernaClient }, 'Unknown lernaClient');
return { error: false };
}
let lernaCommand = `lerna bootstrap --no-ci --ignore-scripts -- `;
if (getAdminConfig().allowScripts && config.ignoreScripts !== false) {
cmdOptions = cmdOptions.replace('--ignore-scripts ', '');
lernaCommand = lernaCommand.replace('--ignore-scripts ', '');
}
lernaCommand += cmdOptions;
const allowUnstable = true; // lerna will pick the default installed npm@6 unless we use node@>=15
const tagConstraint = await getNodeConstraint(config, allowUnstable);
const execOptions: ExecOptions = {
cwd,
extraEnv: {
NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE,
npm_config_store: env.npm_config_store,
},
docker: {
image: 'node',
tagScheme: 'npm',
tagConstraint,
preCommands,
},
};
// istanbul ignore if
if (getAdminConfig().exposeAllEnv) {
execOptions.extraEnv.NPM_AUTH = env.NPM_AUTH;
execOptions.extraEnv.NPM_EMAIL = env.NPM_EMAIL;
}
const lernaVersion = getLernaVersion(lernaPackageFile);
logger.debug('Using lerna version ' + lernaVersion);
preCommands.push(`npm i -g lerna@${quote(lernaVersion)}`);
cmd.push('lerna info || echo "Ignoring lerna info failure"');
cmd.push(`${lernaClient} install ${cmdOptions}`);
cmd.push(lernaCommand);
await exec(cmd, execOptions);
} catch (err) /* istanbul ignore next */ {
if (err.message === TEMPORARY_ERROR) {
throw err;
}
logger.debug(
{
cmd,
err,
type: 'lerna',
lernaClient,
},
'lock file error'
);
return { error: true, stderr: err.stderr };
}
return { error: false };
}