/
pnpm.ts
155 lines (147 loc) · 4.56 KB
/
pnpm.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import is from '@sindresorhus/is';
import { load } from 'js-yaml';
import upath from 'upath';
import { GlobalConfig } from '../../../../config/global';
import { TEMPORARY_ERROR } from '../../../../constants/error-messages';
import { logger } from '../../../../logger';
import { exec } from '../../../../util/exec';
import type {
ExecOptions,
ExtraEnv,
ToolConstraint,
} from '../../../../util/exec/types';
import { deleteLocalFile, readLocalFile } from '../../../../util/fs';
import type { PostUpdateConfig, Upgrade } from '../../types';
import type { NpmPackage } from '../extract/types';
import { getNodeToolConstraint } from './node-version';
import type { GenerateLockFileResult, PnpmLockFile } from './types';
function getPnpmConstraintFromUpgrades(upgrades: Upgrade[]): string | null {
for (const upgrade of upgrades) {
if (upgrade.depName === 'pnpm' && upgrade.newVersion) {
return upgrade.newVersion;
}
}
return null;
}
export async function generateLockFile(
lockFileDir: string,
env: NodeJS.ProcessEnv,
config: PostUpdateConfig,
upgrades: Upgrade[] = []
): Promise<GenerateLockFileResult> {
const lockFileName = upath.join(lockFileDir, 'pnpm-lock.yaml');
logger.debug(`Spawning pnpm install to create ${lockFileName}`);
let lockFile: string | null = null;
let stdout: string | undefined;
let stderr: string | undefined;
let cmd = 'pnpm';
try {
const pnpmToolConstraint: ToolConstraint = {
toolName: 'pnpm',
constraint:
getPnpmConstraintFromUpgrades(upgrades) ??
config.constraints?.pnpm ??
(await getPnpmConstraint(lockFileDir)),
};
const extraEnv: ExtraEnv = {
NPM_CONFIG_CACHE: env.NPM_CONFIG_CACHE,
npm_config_store: env.npm_config_store,
};
const execOptions: ExecOptions = {
cwdFile: lockFileName,
extraEnv,
docker: {},
toolConstraints: [
await getNodeToolConstraint(config, upgrades, lockFileDir),
pnpmToolConstraint,
],
};
// istanbul ignore if
if (GlobalConfig.get('exposeAllEnv')) {
extraEnv.NPM_AUTH = env.NPM_AUTH;
extraEnv.NPM_EMAIL = env.NPM_EMAIL;
}
const commands: string[] = [];
cmd = 'pnpm';
let args = 'install --recursive --lockfile-only';
if (!GlobalConfig.get('allowScripts') || config.ignoreScripts) {
args += ' --ignore-scripts';
args += ' --ignore-pnpmfile';
}
logger.trace({ cmd, args }, 'pnpm command');
commands.push(`${cmd} ${args}`);
// postUpdateOptions
if (config.postUpdateOptions?.includes('pnpmDedupe')) {
logger.debug('Performing pnpm dedupe');
commands.push('pnpm dedupe');
}
if (upgrades.find((upgrade) => upgrade.isLockFileMaintenance)) {
logger.debug(
`Removing ${lockFileName} first due to lock file maintenance upgrade`
);
try {
await deleteLocalFile(lockFileName);
} catch (err) /* istanbul ignore next */ {
logger.debug(
{ err, lockFileName },
'Error removing yarn.lock for lock file maintenance'
);
}
}
await exec(commands, execOptions);
lockFile = await readLocalFile(lockFileName, 'utf8');
} catch (err) /* istanbul ignore next */ {
if (err.message === TEMPORARY_ERROR) {
throw err;
}
logger.debug(
{
cmd,
err,
stdout,
stderr,
type: 'pnpm',
},
'lock file error'
);
return { error: true, stderr: err.stderr, stdout: err.stdout };
}
return { lockFile };
}
async function getPnpmConstraint(
lockFileDir: string
): Promise<string | undefined> {
let result: string | undefined;
const rootPackageJson = upath.join(lockFileDir, 'package.json');
const content = await readLocalFile(rootPackageJson, 'utf8');
if (content) {
const packageJson: NpmPackage = JSON.parse(content);
const packageManager = packageJson?.packageManager;
if (packageManager?.includes('@')) {
const nameAndVersion = packageManager.split('@');
const name = nameAndVersion[0];
if (name === 'pnpm') {
result = nameAndVersion[1];
}
} else {
const engines = packageJson?.engines;
if (engines) {
result = engines['pnpm'];
}
}
}
if (!result) {
const lockFileName = upath.join(lockFileDir, 'pnpm-lock.yaml');
const content = await readLocalFile(lockFileName, 'utf8');
if (content) {
const pnpmLock = load(content) as PnpmLockFile;
if (
is.number(pnpmLock.lockfileVersion) &&
pnpmLock.lockfileVersion < 5.4
) {
result = '<7';
}
}
}
return result;
}