[build-utils] Handle case of not having lockfile (#11697)

In the scenario where we don't have a lockfile, cliType was detected by build utils as npm regardless of what's set in corepack. This fixes that.
This commit is contained in:
Austin Merrick
2024-06-05 13:23:39 -07:00
committed by GitHub
parent b735f37fd9
commit 06d2d860e4
3 changed files with 76 additions and 3 deletions

View File

@@ -0,0 +1,6 @@
---
"@vercel/build-utils": patch
"vercel": patch
---
[built-utils] Handle case of not having lockfile when corepack is enabled

View File

@@ -353,7 +353,9 @@ export async function scanParentDirs(
// TODO: read "bun-lockfile-format-v0"
lockfileVersion = 0;
} else {
cliType = 'npm';
cliType = packageJson
? detectPackageManagerNameWithoutLockfile(packageJson)
: 'npm';
}
const packageJsonPath = pkgJsonPath || undefined;
@@ -366,6 +368,37 @@ export async function scanParentDirs(
};
}
function detectPackageManagerNameWithoutLockfile(packageJson: PackageJson) {
const packageJsonPackageManager = packageJson.packageManager;
if (usingCorepack(process.env, packageJsonPackageManager)) {
const corepackPackageManager = validateVersionSpecifier(
packageJsonPackageManager as string
);
switch (corepackPackageManager?.packageName) {
case 'npm':
case 'pnpm':
case 'yarn':
case 'bun':
return corepackPackageManager.packageName;
case undefined:
return 'npm';
default:
throw new Error(
`Unknown package manager "${corepackPackageManager?.packageName}". Change your package.json "packageManager" field to a known package manager.`
);
}
}
return 'npm';
}
function usingCorepack(
env: { [x: string]: string | undefined },
packageJsonPackageManager: string | undefined
) {
const corepackFlagged = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
return corepackFlagged && Boolean(packageJsonPackageManager);
}
export async function walkParentDirs({
base,
start,
@@ -557,8 +590,7 @@ export function getEnvForPackageManager({
nodeVersion: NodeVersion | undefined;
env: { [x: string]: string | undefined };
}) {
const corepackFlagged = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
const corepackEnabled = corepackFlagged && Boolean(packageJsonPackageManager);
const corepackEnabled = usingCorepack(env, packageJsonPackageManager);
const {
detectedLockfile,
@@ -753,6 +785,39 @@ export function getPathOverrideForPackageManager({
}
}
function validateVersionSpecifier(version: string) {
if (!version) {
return undefined;
}
const [before, after, ...extra] = version.split('@');
if (extra.length) {
// should not have more than one `@`
return undefined;
}
if (!before) {
// should have a package before the `@`
return undefined;
}
if (!after) {
// should have a version after the `@`
return undefined;
}
if (!validRange(after)) {
// the version after the `@` should be a valid semver value
return undefined;
}
return {
packageName: before,
packageVersionRange: after,
};
}
/**
* Helper to get the binary paths that link to the used package manager.
* Note: Make sure it doesn't contain any `console.log` calls.

View File

@@ -263,6 +263,7 @@ test('[vc build] should build project with corepack and select pnpm@7.1.0', asyn
path.join(directory, '.vercel/cache/corepack')
);
expect(contents).toEqual(['home', 'shim']);
expect(output.stdout).toMatch(/Running "pnpm run build"/gm);
} finally {
delete process.env.ENABLE_EXPERIMENTAL_COREPACK;
}
@@ -291,6 +292,7 @@ test('[vc build] should build project with corepack and select yarn@2.4.3', asyn
path.join(directory, '.vercel/cache/corepack')
);
expect(contents).toEqual(['home', 'shim']);
expect(output.stdout).toMatch(/Running "yarn run build"/gm);
} finally {
delete process.env.ENABLE_EXPERIMENTAL_COREPACK;
}