Skip to content

Commit

Permalink
feat(pnpm): support package.json#packageManager
Browse files Browse the repository at this point in the history
  • Loading branch information
privatenumber committed Aug 9, 2023
1 parent d8e2870 commit ae263ca
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 15 deletions.
13 changes: 9 additions & 4 deletions src/ci.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { existsSync } from 'fs';
import { spawnSync } from 'child_process';
import { detectPnpmVersionFromPackageManager } from './utils/detect-pnpm-version-from-package-manager.js';
import { guessPnpmVersion } from './utils/guess-pnpm-version.js';
import { getPnpmLockVersion } from './utils/get-pnpm-lock-version.js';
import type { NodeVersion } from './types.js';
import { parseVersionString } from './utils/parse-version-string.js';
import type { NodeVersion } from './types.js';

export const ci = async () => {
const options = {
Expand All @@ -26,10 +27,14 @@ export const ci = async () => {
}

if (existsSync('pnpm-lock.yaml')) {
const pnpmVersion = guessPnpmVersion(
parseVersionString<NodeVersion>(process.versions.node),
await getPnpmLockVersion(),
const pnpmVersion = (
detectPnpmVersionFromPackageManager()
|| guessPnpmVersion(
parseVersionString<NodeVersion>(process.versions.node),
await getPnpmLockVersion(),
)
);

return spawnSync(
'npx',
[`pnpm${pnpmVersion}`, 'i', '--frozen-lockfile'],
Expand Down
20 changes: 20 additions & 0 deletions src/utils/detect-pnpm-version-from-package-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { readFileSync } from 'fs';

/**
* This is specific to pnpm because it's the only package manager with
* incompatibility between the lockfile and the package manager version.
*
* The source of truth is still the lock file type because `npm ci` only
* installs from the lock file.
*
* That's to say if there's a package-lock.json, but the packageManager
* is pnpm, then we'll still use npm.
*/
export const detectPnpmVersionFromPackageManager = () => {
try {
const { packageManager } = JSON.parse(readFileSync('package.json', 'utf8'));
if (packageManager.startsWith('pnpm')) {
return packageManager.slice(4);
}
} catch {}
};
6 changes: 6 additions & 0 deletions tests/fixtures/pnpm-package-manager/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"packageManager": "pnpm@8.0.0",
"dependencies": {
"test-package": "^0.0.1"
}
}
12 changes: 12 additions & 0 deletions tests/fixtures/pnpm-package-manager/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 23 additions & 11 deletions tests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const ciBinaryPath = path.resolve('dist/cli.js');
const ci = (cwd: string) => execa(ciBinaryPath, [], { cwd });

describe('ci', ({ describe, runTestSuite }) => {
describe('lock file', ({ test }) => {
describe('lock file', ({ test, describe }) => {
test('npm', async ({ onTestFinish }) => {
const fixture = await createFixture('tests/fixtures/npm');
onTestFinish(async () => await fixture.rm());
Expand All @@ -16,23 +16,35 @@ describe('ci', ({ describe, runTestSuite }) => {
expect(stdout).toMatch('added 1 package, and audited 2 packages');
});

test('pnpm', async ({ onTestFinish }) => {
const fixture = await createFixture('tests/fixtures/pnpm');
onTestFinish(async () => await fixture.rm());

const { stdout } = await ci(fixture.path);

// pnpm changed "Lockfile is up-to-date" to "Lockfile is up to date"
expect(stdout).toMatch('Lockfile is up');
});

test('yarn', async ({ onTestFinish }) => {
const fixture = await createFixture('tests/fixtures/yarn');
onTestFinish(async () => await fixture.rm());

const { stdout } = await ci(fixture.path);
expect(stdout).toMatch('YN0000: Done in');
});

describe('pnpm', ({ test }) => {
test('detect veresion', async ({ onTestFinish }) => {
const fixture = await createFixture('tests/fixtures/pnpm');
onTestFinish(async () => await fixture.rm());

const { stdout } = await ci(fixture.path);

// pnpm changed "Lockfile is up-to-date" to "Lockfile is up to date"
expect(stdout).toMatch('Lockfile is up');
});

test('packageManager', async ({ onTestFinish }) => {
const fixture = await createFixture('tests/fixtures/pnpm-package-manager');
onTestFinish(async () => await fixture.rm());

const { stdout } = await ci(fixture.path);

// pnpm changed "Lockfile is up-to-date" to "Lockfile is up to date"
expect(stdout).toMatch('Lockfile is up');
});
});
});

runTestSuite(import('./get-pnpm-version.spec.js'));
Expand Down

0 comments on commit ae263ca

Please sign in to comment.