Skip to content

Commit df9883b

Browse files
committed
fix(pnpm-policy): generate without a lockfile when scopes alone define the exemptions
1 parent 474247f commit df9883b

4 files changed

Lines changed: 18 additions & 4 deletions

File tree

packages/pnpm-policy/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ Two rules govern how it compresses:
172172

173173
**Unscoped names are listed individually**, which is exact: they come from your own maintainer query.
174174

175-
**Intersection.** By default only names this workspace actually resolves (read from `pnpm-lock.yaml`) are written out — 1104 published packages becomes the ~85 that appear in this repo. Scope globs are never intersected: nobody else can publish into a scope you own, so the glob stays correct when a new package lands there tomorrow. Pass `--no-intersect` to emit everything.
175+
**Intersection.** By default only names this workspace actually resolves (read from `pnpm-lock.yaml`) are written out — 1104 published packages becomes the ~85 that appear in this repo. Scope globs are never intersected: nobody else can publish into a scope you own, so the glob stays correct when a new package lands there tomorrow. Pass `--no-intersect` to emit everything. A config with no `inventory:` has no individual names to narrow, so it needs no lockfile at all — which is what lets a freshly scaffolded workspace generate its policy before its first install.
176176

177177
Commit the inventory and review its diffs. It is an exemption list, so a name appearing in it is a name that stops being quarantined — worth one human glance, which is also why refreshing it should open a pull request rather than run silently in an install hook.
178178

packages/pnpm-policy/__tests__/generate.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { mkdtempSync, readFileSync, writeFileSync } from 'fs';
1+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
22
import { tmpdir } from 'os';
33
import { join } from 'path';
44

@@ -84,6 +84,12 @@ describe('generate', () => {
8484
expect(readFileSync(result.file, 'utf-8')).toContain('never-used');
8585
});
8686

87+
it('needs no lockfile when scopes alone define the exemptions', () => {
88+
const dir = workspace('minimumReleaseAge: 14d\nscopes:\n - "@acme"\n');
89+
rmSync(join(dir, 'pnpm-lock.yaml'));
90+
expect(readFileSync(generate({ cwd: dir }).file, 'utf-8')).toContain('"@acme/*"');
91+
});
92+
8793
it('reports no change on a second run', () => {
8894
const dir = workspace(CONFIG);
8995
generate({ cwd: dir });

packages/pnpm-policy/src/generate.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,16 @@ function load(options: RunOptions): Loaded {
7373
);
7474
}
7575

76+
// Intersection only ever narrows individual inventory names, so a workspace
77+
// with no inventory (scopes alone, which are never intersected) has nothing to
78+
// read a lockfile for — and demanding one would fail a freshly scaffolded
79+
// project that has not installed yet.
80+
const needsLockfile = intersect && inventory != null;
81+
7682
const policy = resolvePolicy({
7783
config: { ...config, intersect },
7884
inventory,
79-
resolved: intersect ? readWorkspacePackages(workspaceDir) : undefined,
85+
resolved: needsLockfile ? readWorkspacePackages(workspaceDir) : undefined,
8086
buildsKey: options.buildsKey,
8187
now: options.now
8288
});

packages/pnpm-policy/src/policy.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@ function buildComments(
107107
? `First-party membership comes from what ${config.maintainers.join(', ')} ${
108108
config.maintainers.length === 1 ? 'publishes' : 'publish'
109109
} on npm — waiting on your own release protects nothing.`
110-
: 'First-party membership comes from the inventory.'
110+
: report.firstPartyPackages.length
111+
? 'First-party membership comes from the inventory.'
112+
: 'First-party membership comes from the scopes claimed in pnpm-policy.yaml.'
111113
].join('\n')
112114
]);
113115
}

0 commit comments

Comments
 (0)