Skip to content

Commit 16038a6

Browse files
committed
add COREPACK_ENV_FILE to control which file to load
1 parent 52f968e commit 16038a6

5 files changed

Lines changed: 158 additions & 11 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,9 @@ same major line. Should you need to upgrade to a new major, use an explicit
304304
Corepack a specific version matching the range defined in `package.json`'s
305305
`devEngines.packageManager` field.
306306

307+
- `COREPACK_ENV_FILE` can be set to `0` to request Corepack to not attempt to
308+
load `.corepack.env`; it can be set to a path to specify a different env file.
309+
307310
## Troubleshooting
308311

309312
The environment variable `DEBUG` can be set to `corepack` to enable additional debug logging.

sources/specUtils.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -185,17 +185,22 @@ export async function loadSpec(initialCwd: string): Promise<LoadSpecResult> {
185185
throw new UsageError(`Invalid package.json in ${path.relative(initialCwd, manifestPath)}`);
186186

187187
let localEnv: LocalEnvFile;
188-
const envFilePath = path.resolve(currCwd, `./.corepack.env`);
189-
debugUtils.log(`Checking ${envFilePath}`);
190-
try {
191-
localEnv = {...parseEnv(await fs.promises.readFile(envFilePath, `utf8`)), ...process.env};
192-
debugUtils.log(`Successfully loaded env file found at ${envFilePath}`);
193-
} catch (err) {
194-
if ((err as NodeError)?.code !== `ENOENT`)
195-
throw err;
196-
197-
debugUtils.log(`No env file found at ${envFilePath}`);
188+
const envFilePath = path.resolve(currCwd, process.env.COREPACK_ENV_FILE ?? `.corepack.env`);
189+
if (process.env.COREPACK_ENV_FILE == `0`) {
190+
debugUtils.log(`Skipping env file as configured with COREPACK_ENV_FILE`);
198191
localEnv = process.env;
192+
} else {
193+
debugUtils.log(`Checking ${envFilePath}`);
194+
try {
195+
localEnv = {...parseEnv(await fs.promises.readFile(envFilePath, `utf8`)), ...process.env};
196+
debugUtils.log(`Successfully loaded env file found at ${envFilePath}`);
197+
} catch (err) {
198+
if ((err as NodeError)?.code !== `ENOENT`)
199+
throw err;
200+
201+
debugUtils.log(`No env file found at ${envFilePath}`);
202+
localEnv = process.env;
203+
}
199204
}
200205

201206
selection = {data, manifestPath, localEnv, envFilePath};
@@ -210,10 +215,16 @@ export async function loadSpec(initialCwd: string): Promise<LoadSpecResult> {
210215

211216
debugUtils.log(`${selection.manifestPath} defines ${rawPmSpec} as local package manager`);
212217

218+
let envFilePath: string | undefined;
219+
if (selection.localEnv !== process.env) {
220+
envFilePath = selection.envFilePath;
221+
process.env = selection.localEnv;
222+
}
223+
213224
return {
214225
type: `Found`,
215226
target: selection.manifestPath,
216-
envFilePath: selection.localEnv !== process.env ? selection.envFilePath : undefined,
227+
envFilePath,
217228
spec: parseSpec(rawPmSpec, path.relative(initialCwd, selection.manifestPath)),
218229
};
219230
}

tests/Up.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,39 @@ describe(`UpCommand`, () => {
6767
});
6868
})));
6969
});
70+
71+
it(`should update the ".other.env" file from the current project when configured to use that`, async () => {
72+
await Promise.all([
73+
`COREPACK_DEV_ENGINES_YARN=2.1.0\n`,
74+
`\nCOREPACK_DEV_ENGINES_YARN=2.1.0\n`,
75+
`COREPACK_DEV_ENGINES_YARN=2.1.0`,
76+
`\nCOREPACK_DEV_ENGINES_YARN=2.1.0`,
77+
`FOO=bar\nCOREPACK_DEV_ENGINES_YARN=2.1.0\n`,
78+
`FOO=bar\nCOREPACK_DEV_ENGINES_YARN=2.1.0`,
79+
].map(originalEnv => xfs.mktempPromise(async cwd => {
80+
await xfs.writeJsonPromise(ppath.join(cwd, `package.json`), {
81+
devEngines: {packageManager: {name: `yarn`, version: `2.x`}},
82+
});
83+
await xfs.writeFilePromise(ppath.join(cwd, `.other.env`), originalEnv);
84+
85+
process.env.COREPACK_ENV_FILE = `.other.env`;
86+
await expect(runCli(cwd, [`up`])).resolves.toMatchObject({
87+
exitCode: 0,
88+
stderr: ``,
89+
});
90+
91+
try {
92+
await expect(xfs.readFilePromise(ppath.join(cwd, `.other.env`), `utf-8`).then(parseEnv)).resolves.toMatchObject({
93+
COREPACK_DEV_ENGINES_YARN: `2.4.3+sha512.8dd9fedc5451829619e526c56f42609ad88ae4776d9d3f9456d578ac085115c0c2f0fb02bb7d57fd2e1b6e1ac96efba35e80a20a056668f61c96934f67694fd0`,
94+
});
95+
} catch (cause) {
96+
throw new Error(JSON.stringify(originalEnv), {cause});
97+
}
98+
99+
await expect(runCli(cwd, [`yarn`, `--version`])).resolves.toMatchObject({
100+
exitCode: 0,
101+
stdout: `2.4.3\n`,
102+
});
103+
})));
104+
});
70105
});

tests/Use.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,40 @@ describe(`UseCommand`, () => {
6666
})));
6767
});
6868

69+
it(`should update .other.env if present`, async () => {
70+
await Promise.all([
71+
`COREPACK_DEV_ENGINES_YARN=1.1.0\n`,
72+
`\nCOREPACK_DEV_ENGINES_YARN=1.1.0\n`,
73+
`COREPACK_DEV_ENGINES_YARN=1.1.0`,
74+
`\nCOREPACK_DEV_ENGINES_YARN=1.1.0`,
75+
`FOO=bar\nCOREPACK_DEV_ENGINES_YARN=1.1.0\n`,
76+
`FOO=bar\nCOREPACK_DEV_ENGINES_YARN=1.1.0`,
77+
].map(originalEnv => xfs.mktempPromise(async cwd => {
78+
await xfs.writeJsonPromise(ppath.join(cwd, `package.json`), {
79+
devEngines: {packageManager: {name: `yarn`, version: `1.x`}},
80+
});
81+
await xfs.writeFilePromise(ppath.join(cwd, `.other.env`), `COREPACK_DEV_ENGINES_YARN=1.0.0\n`);
82+
83+
process.env.COREPACK_ENV_FILE = `.other.env`;
84+
await expect(runCli(cwd, [`use`, `yarn@1.22.4`])).resolves.toMatchObject({
85+
exitCode: 0,
86+
});
87+
88+
try {
89+
await expect(xfs.readFilePromise(ppath.join(cwd, `.other.env`), `utf-8`).then(parseEnv)).resolves.toMatchObject({
90+
COREPACK_DEV_ENGINES_YARN: `1.22.4+sha512.a1833b862fe52169bd6c2a033045a07df5bc6a23595c259e675fed1b2d035ab37abe6ce309720abb6636d68f03615054b6292dc0a70da31c8697fda228b50d18`,
91+
});
92+
} catch (cause) {
93+
throw new Error(JSON.stringify(originalEnv), {cause});
94+
}
95+
96+
await expect(runCli(cwd, [`yarn`, `--version`])).resolves.toMatchObject({
97+
exitCode: 0,
98+
stdout: `1.22.4\n`,
99+
});
100+
})));
101+
});
102+
69103
it(`should create a package.json if absent`, async () => {
70104
await xfs.mktempPromise(async cwd => {
71105
await expect(runCli(cwd, [`use`, `yarn@1.22.4`])).resolves.toMatchObject({

tests/main.test.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,32 @@ describe(`should accept range in devEngines only if a specific version is provid
361361
});
362362
});
363363
});
364+
it(`either in a different env file specified in env`, async() => {
365+
await xfs.mktempPromise(async cwd => {
366+
await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as PortablePath), {
367+
devEngines: {
368+
packageManager: {
369+
name: `pnpm`,
370+
version: `6.x`,
371+
},
372+
},
373+
});
374+
await expect(runCli(cwd, [`pnpm`, `--version`])).resolves.toMatchObject({
375+
exitCode: 1,
376+
stderr: `Invalid package manager specification in package.json (pnpm@6.x); expected a semver version\n`,
377+
stdout: ``,
378+
});
379+
380+
await xfs.writeFilePromise(ppath.join(cwd, `.env` as PortablePath),
381+
`COREPACK_DEV_ENGINES_PNPM=6.6.2+sha224.eb5c0acad3b0f40ecdaa2db9aa5a73134ad256e17e22d1419a2ab073\n`);
382+
process.env.COREPACK_ENV_FILE = `.env`;
383+
await expect(runCli(cwd, [`pnpm`, `--version`])).resolves.toMatchObject({
384+
exitCode: 0,
385+
stderr: ``,
386+
stdout: `6.6.2\n`,
387+
});
388+
});
389+
});
364390
it(`either in an env variable`, async() => {
365391
await xfs.mktempPromise(async cwd => {
366392
await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as PortablePath), {
@@ -419,6 +445,44 @@ describe(`should accept range in devEngines only if a specific version is provid
419445
});
420446
});
421447

448+
it(`Should use version from correct source`, async () => {
449+
await xfs.mktempPromise(async cwd => {
450+
await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as PortablePath), {
451+
devEngines: {
452+
packageManager: {
453+
name: `pnpm`,
454+
version: `6.6.2+sha1.11111`,
455+
},
456+
},
457+
});
458+
await xfs.writeFilePromise(ppath.join(cwd, `.corepack.env` as PortablePath), `COREPACK_DEV_ENGINES_PNPM=6.6.2+sha1.22222\n`);
459+
await xfs.writeFilePromise(ppath.join(cwd, `.other.env` as PortablePath), `COREPACK_DEV_ENGINES_PNPM=6.6.2+sha1.33333\n`);
460+
461+
// By default, it should pick up .corepack.env
462+
await expect(runCli(cwd, [`pnpm`, `--version`])).resolves.toMatchObject({
463+
exitCode: 1,
464+
stderr: expect.stringContaining(`Mismatch hashes. Expected 22222, got 7b4d6b176c1b93b5670ed94c24babb7d80c13854`),
465+
stdout: ``,
466+
});
467+
468+
// When disabling env file, it should pick up the hash inn package.json
469+
process.env.COREPACK_ENV_FILE = `0`;
470+
await expect(runCli(cwd, [`pnpm`, `--version`])).resolves.toMatchObject({
471+
exitCode: 1,
472+
stderr: expect.stringContaining(`Mismatch hashes. Expected 11111, got 7b4d6b176c1b93b5670ed94c24babb7d80c13854`),
473+
stdout: ``,
474+
});
475+
476+
// When specifying another env file, this one should used
477+
process.env.COREPACK_ENV_FILE = `.other.env`;
478+
await expect(runCli(cwd, [`pnpm`, `--version`])).resolves.toMatchObject({
479+
exitCode: 1,
480+
stderr: expect.stringContaining(`Mismatch hashes. Expected 33333, got 7b4d6b176c1b93b5670ed94c24babb7d80c13854`),
481+
stdout: ``,
482+
});
483+
});
484+
});
485+
422486
describe(`should reject if range in devEngines does not match version provided`, () => {
423487
it(`in .corepack.env`, async () => {
424488
await xfs.mktempPromise(async cwd => {

0 commit comments

Comments
 (0)