Skip to content

Commit ac518c4

Browse files
authored
fix: ignore devEngines version range when CLI provides a version (#762)
1 parent cf0ddc1 commit ac518c4

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

sources/Engine.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ export class Engine {
244244
* project using the default package managers, and configure it so that we
245245
* don't need to ask again in the future.
246246
*/
247-
async findProjectSpec(initialCwd: string, locator: Locator | LazyLocator, {transparent = false}: {transparent?: boolean} = {}): Promise<Descriptor> {
247+
async findProjectSpec(initialCwd: string, locator: Locator | LazyLocator, {transparent = false, binaryVersion}: {transparent?: boolean, binaryVersion?: string | null} = {}): Promise<Descriptor> {
248248
// A locator is a valid descriptor (but not the other way around)
249249
const fallbackDescriptor = {name: locator.name, range: `${locator.reference}`};
250250

@@ -293,7 +293,7 @@ export class Engine {
293293
}
294294

295295
case `Found`: {
296-
const spec = result.getSpec();
296+
const spec = result.getSpec({enforceExactVersion: !binaryVersion});
297297
if (spec.name !== locator.name) {
298298
if (transparent) {
299299
if (typeof locator.reference === `function`)
@@ -344,7 +344,7 @@ export class Engine {
344344
};
345345
}
346346

347-
const descriptor = await this.findProjectSpec(cwd, fallbackLocator, {transparent: isTransparentCommand});
347+
const descriptor = await this.findProjectSpec(cwd, fallbackLocator, {transparent: isTransparentCommand, binaryVersion});
348348

349349
if (binaryVersion)
350350
descriptor.range = binaryVersion;

sources/specUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ export async function setLocalPackageManager(cwd: string, info: PreparedPackageM
150150
interface FoundSpecResult {
151151
type: `Found`;
152152
target: string;
153-
getSpec: () => Descriptor;
153+
getSpec: (options?: {enforceExactVersion?: boolean}) => Descriptor;
154154
range?: Descriptor & {onFail?: DevEngineDependency[`onFail`]};
155155
envFilePath?: string;
156156
}
@@ -249,6 +249,6 @@ export async function loadSpec(initialCwd: string): Promise<LoadSpecResult> {
249249
onFail: selection.data.devEngines.packageManager.onFail,
250250
},
251251
// Lazy-loading it so we do not throw errors on commands that do not need valid spec.
252-
getSpec: () => parseSpec(rawPmSpec, path.relative(initialCwd, selection.manifestPath)),
252+
getSpec: ({enforceExactVersion = true} = {}) => parseSpec(rawPmSpec, path.relative(initialCwd, selection.manifestPath), {enforceExactVersion}),
253253
};
254254
}

tests/main.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,3 +1709,51 @@ describe(`handle integrity checks`, () => {
17091709
});
17101710
});
17111711
});
1712+
1713+
describe(`allow range versions in devEngines.packageManager.version when user specifies exact version`, () => {
1714+
for (const {name, versionRange, userProvidedVersion} of [
1715+
{name: `npm`, versionRange: `^10.7.0`, userProvidedVersion: `6.14.2`},
1716+
{name: `yarn`, versionRange: `^2.2.0`, userProvidedVersion: `2.2.2`},
1717+
{name: `pnpm`, versionRange: `^5.8.0`, userProvidedVersion: `5.8.0`},
1718+
]) {
1719+
it(`should work with ${name}`, async () => {
1720+
await xfs.mktempPromise(async cwd => {
1721+
await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), {
1722+
devEngines: {
1723+
packageManager: {
1724+
name,
1725+
version: versionRange,
1726+
},
1727+
},
1728+
});
1729+
1730+
await expect(runCli(cwd, [`${name}@${userProvidedVersion}`, `--version`])).resolves.toMatchObject({
1731+
exitCode: 0,
1732+
stderr: ``,
1733+
stdout: `${userProvidedVersion}\n`,
1734+
});
1735+
});
1736+
});
1737+
}
1738+
});
1739+
1740+
it(`should still validate devEngines.packageManager.version format when no user version specified`, async () => {
1741+
await xfs.mktempPromise(async cwd => {
1742+
// When no user version is specified, range versions in devEngines should still cause error
1743+
await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), {
1744+
devEngines: {
1745+
packageManager: {
1746+
name: `npm`,
1747+
version: `^6.14.2`,
1748+
},
1749+
},
1750+
});
1751+
1752+
// Without user-specified version, should still fail due to range version in devEngines
1753+
await expect(runCli(cwd, [`npm`, `--version`])).resolves.toMatchObject({
1754+
exitCode: 1,
1755+
stderr: expect.stringContaining(`Invalid package manager specification in package.json (npm@^6.14.2); expected a semver version`),
1756+
stdout: ``,
1757+
});
1758+
});
1759+
});

0 commit comments

Comments
 (0)