@pnpm/releasing.commands 1100.5.5 → 1100.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,7 +16,7 @@ export declare function handler(opts: Omit<PublishRecursiveOpts, 'workspaceDir'>
16
16
  json?: boolean;
17
17
  recursive?: boolean;
18
18
  workspaceDir?: string;
19
- } & Pick<Config, 'bin' | 'gitChecks' | 'ignoreScripts' | 'pnpmHomeDir' | 'publishBranch' | 'embedReadme' | 'skipManifestObfuscation'> & Pick<ConfigContext, 'allProjects'>, params: string[]): Promise<{
19
+ } & Pick<Config, 'bin' | 'gitChecks' | 'ignoreScripts' | 'pnpmHomeDir' | 'publishBranch' | 'embedReadme' | 'skipManifestObfuscation' | 'versioning'> & Pick<ConfigContext, 'allProjects'>, params: string[]): Promise<{
20
20
  exitCode?: number;
21
21
  output?: string;
22
22
  } | undefined>;
@@ -36,5 +36,5 @@ export declare function publish(opts: Omit<PublishRecursiveOpts, 'workspaceDir'>
36
36
  engineStrict?: boolean;
37
37
  recursive?: boolean;
38
38
  workspaceDir?: string;
39
- } & Pick<Config, 'bin' | 'gitChecks' | 'ignoreScripts' | 'pnpmHomeDir' | 'publishBranch' | 'embedReadme' | 'packGzipLevel' | 'skipManifestObfuscation'> & Pick<ConfigContext, 'allProjects'>, params: string[]): Promise<PublishResult>;
39
+ } & Pick<Config, 'bin' | 'gitChecks' | 'ignoreScripts' | 'pnpmHomeDir' | 'publishBranch' | 'embedReadme' | 'packGzipLevel' | 'skipManifestObfuscation' | 'versioning'> & Pick<ConfigContext, 'allProjects'>, params: string[]): Promise<PublishResult>;
40
40
  export declare function runScriptsIfPresent(opts: RunLifecycleHookOptions, scriptNames: string[], manifest: ProjectManifest): Promise<void>;
@@ -11,7 +11,7 @@ import { pick } from 'ramda';
11
11
  import { realpathMissing } from 'realpath-missing';
12
12
  import { renderHelp } from 'render-help';
13
13
  import { temporaryDirectory } from 'tempy';
14
- import { extractManifestFromPacked, isTarballPath } from './extractManifestFromPacked.js';
14
+ import { extractPublishManifestFromPacked, isTarballPath } from './extractManifestFromPacked.js';
15
15
  import { optionsWithOtpEnv } from './otpEnv.js';
16
16
  import * as pack from './pack.js';
17
17
  import { publishPackedPkg } from './publishPackedPkg.js';
@@ -188,7 +188,7 @@ export async function publish(opts, params) {
188
188
  const dirInParams = (params.length > 0) ? params[0] : undefined;
189
189
  if (dirInParams != null && isTarballPath(dirInParams)) {
190
190
  const tarballPath = dirInParams;
191
- const publishedManifest = await extractManifestFromPacked(tarballPath);
191
+ const publishedManifest = await extractPublishManifestFromPacked(tarballPath);
192
192
  // Publishing a pre-built tarball bypasses `pack.api()`, so we don't have the file listing
193
193
  // or unpacked size — those summary fields are reported as empty/zero.
194
194
  const publishSummary = await publishPackedPkg({
@@ -1,6 +1,6 @@
1
1
  import type { Config, ConfigContext } from '@pnpm/config.reader';
2
2
  import type { PublishPackedPkgOptions, PublishSummary } from './publishPackedPkg.js';
3
- export type PublishRecursiveOpts = Required<Pick<Config, 'bin' | 'cacheDir' | 'dir' | 'pnpmHomeDir' | 'configByUri' | 'registries' | 'workspaceDir'>> & Required<Pick<ConfigContext, 'cliOptions'>> & Partial<Pick<Config, 'tag' | 'ca' | 'catalogs' | 'cert' | 'fetchTimeout' | 'force' | 'dryRun' | 'extraBinPaths' | 'extraEnv' | 'fetchRetries' | 'fetchRetryFactor' | 'fetchRetryMaxtimeout' | 'fetchRetryMintimeout' | 'key' | 'httpProxy' | 'httpsProxy' | 'localAddress' | 'lockfileDir' | 'noProxy' | 'npmPath' | 'offline' | 'strictSsl' | 'unsafePerm' | 'userAgent' | 'verifyStoreIntegrity'>> & Partial<Pick<ConfigContext, 'selectedProjectsGraph' | 'allProjectsGraph' | 'prodAllProjectsGraph' | 'prodOnlySelectedProjectDirs'>> & {
3
+ export type PublishRecursiveOpts = Required<Pick<Config, 'bin' | 'cacheDir' | 'dir' | 'pnpmHomeDir' | 'configByUri' | 'registries' | 'workspaceDir'>> & Required<Pick<ConfigContext, 'cliOptions'>> & Partial<Pick<Config, 'tag' | 'ca' | 'catalogs' | 'cert' | 'fetchTimeout' | 'force' | 'dryRun' | 'extraBinPaths' | 'extraEnv' | 'fetchRetries' | 'fetchRetryFactor' | 'fetchRetryMaxtimeout' | 'fetchRetryMintimeout' | 'key' | 'httpProxy' | 'httpsProxy' | 'localAddress' | 'lockfileDir' | 'noProxy' | 'npmPath' | 'offline' | 'strictSsl' | 'unsafePerm' | 'userAgent' | 'verifyStoreIntegrity' | 'versioning'>> & Partial<Pick<ConfigContext, 'selectedProjectsGraph' | 'allProjectsGraph' | 'prodAllProjectsGraph' | 'prodOnlySelectedProjectDirs'>> & {
4
4
  access?: 'public' | 'restricted';
5
5
  argv: {
6
6
  original: string[];
@@ -1,12 +1,14 @@
1
1
  import { type Config } from '@pnpm/config.reader';
2
- import type { ProjectsGraph } from '@pnpm/types';
2
+ import type { Project, ProjectsGraph } from '@pnpm/types';
3
3
  export declare function rcOptionsTypes(): Record<string, unknown>;
4
4
  export declare function cliOptionsTypes(): Record<string, unknown>;
5
5
  export declare const commandNames: string[];
6
6
  export declare function help(): string;
7
7
  interface VersionHandlerOptions extends Config {
8
+ allProjects?: Project[];
8
9
  allowSameVersion?: boolean;
9
10
  commitHooks?: boolean;
11
+ dryRun?: boolean;
10
12
  gitChecks?: boolean;
11
13
  gitTagVersion?: boolean;
12
14
  json?: boolean;
@@ -4,10 +4,13 @@ import { types as allTypes } from '@pnpm/config.reader';
4
4
  import { PnpmError } from '@pnpm/error';
5
5
  import { runLifecycleHook } from '@pnpm/exec.lifecycle';
6
6
  import { isGitRepo, isWorkingTreeClean } from '@pnpm/network.git-utils';
7
+ import { applyReleasePlan, assembleReleasePlan, changelogStorage, readChangeIntents, readLedger, toProjectDir, } from '@pnpm/releasing.versioning';
7
8
  import { safeExeca as execa } from 'execa';
8
9
  import { pick } from 'ramda';
9
10
  import { renderHelp } from 'render-help';
10
11
  import { inc, valid } from 'semver';
12
+ import { renderReleasePlan, toWorkspaceProjects } from '../change/index.js';
13
+ import { changelogHasSection, fetchPublishedChangelog } from '../publish/previousChangelog.js';
11
14
  export function rcOptionsTypes() {
12
15
  return pick([
13
16
  'allow-same-version',
@@ -22,6 +25,7 @@ export function rcOptionsTypes() {
22
25
  export function cliOptionsTypes() {
23
26
  return {
24
27
  ...rcOptionsTypes(),
28
+ 'dry-run': Boolean,
25
29
  json: Boolean,
26
30
  preid: String,
27
31
  recursive: Boolean,
@@ -38,6 +42,7 @@ export function help() {
38
42
  usages: [
39
43
  'pnpm version <newversion>',
40
44
  'pnpm version <major|minor|patch|premajor|preminor|prepatch|prerelease>',
45
+ 'pnpm version -r [--dry-run]',
41
46
  ],
42
47
  descriptionLists: [
43
48
  {
@@ -84,9 +89,13 @@ export function help() {
84
89
  name: '--json',
85
90
  },
86
91
  {
87
- description: 'Apply command to all packages in workspace',
92
+ description: 'Apply command to all packages in workspace. Without a version argument, consumes the pending change intents from .changeset/ and applies the resulting release plan',
88
93
  name: '--recursive',
89
94
  },
95
+ {
96
+ description: 'Print the release plan the pending change intents produce without applying it',
97
+ name: '--dry-run',
98
+ },
90
99
  ],
91
100
  },
92
101
  ],
@@ -95,6 +104,9 @@ export function help() {
95
104
  export async function handler(opts, params) {
96
105
  const rawBump = params[0];
97
106
  if (!rawBump) {
107
+ if (opts.recursive) {
108
+ return releaseFromIntents(opts);
109
+ }
98
110
  throw new PnpmError('INVALID_VERSION_BUMP', 'A version argument is required. Must be a valid semver version (e.g. 1.2.3) or one of: major, minor, patch, premajor, preminor, prepatch, prerelease');
99
111
  }
100
112
  const explicitVersion = valid(rawBump);
@@ -142,6 +154,83 @@ export async function handler(opts, params) {
142
154
  }
143
155
  return output;
144
156
  }
157
+ async function releaseFromIntents(opts) {
158
+ const workspaceDir = opts.workspaceDir;
159
+ if (!workspaceDir) {
160
+ throw new PnpmError('WORKSPACE_ONLY', 'The bare "pnpm version -r" form consumes change intents and is only supported in a workspace');
161
+ }
162
+ if (!opts.dryRun && opts.gitChecks !== false && await isGitRepo({ cwd: workspaceDir })) {
163
+ if (!await isWorkingTreeClean({ cwd: workspaceDir })) {
164
+ throw new PnpmError('UNCLEAN_WORKING_TREE', 'Working tree is not clean. Commit or stash your changes.');
165
+ }
166
+ }
167
+ const intents = await readChangeIntents(workspaceDir);
168
+ const ledger = await readLedger(workspaceDir);
169
+ const projects = toWorkspaceProjects(opts.allProjects ?? []);
170
+ const filter = (opts.filter ?? []).length > 0
171
+ ? new Set(Object.keys(opts.selectedProjectsGraph ?? {}).map((rootDir) => toProjectDir(workspaceDir, rootDir)))
172
+ : undefined;
173
+ const plan = assembleReleasePlan({
174
+ workspaceDir,
175
+ projects,
176
+ intents,
177
+ ledger,
178
+ versioning: opts.versioning,
179
+ filter,
180
+ enforceWorkspaceProtocol: true,
181
+ });
182
+ const applyOpts = {
183
+ workspaceDir,
184
+ projects,
185
+ allIntents: intents,
186
+ versioning: opts.versioning,
187
+ verifyPublished: buildVerifyPublished(opts),
188
+ };
189
+ if (plan.releases.length === 0) {
190
+ // A full (unfiltered) run garbage-collects the intent files an empty plan
191
+ // leaves behind: declined ("none"-only) intents and files a merge
192
+ // resurrected after every named package had already consumed them. A
193
+ // filtered run must not — "nothing pending in this scope" is no reason to
194
+ // delete prose belonging to packages outside the filter.
195
+ if (!opts.dryRun && filter == null) {
196
+ await applyReleasePlan(plan, applyOpts);
197
+ }
198
+ return 'No pending changes. Record one with "pnpm change".';
199
+ }
200
+ if (opts.dryRun) {
201
+ return renderReleasePlan(plan);
202
+ }
203
+ const applied = await applyReleasePlan(plan, applyOpts);
204
+ if (opts.json) {
205
+ return JSON.stringify(applied, null, 2);
206
+ }
207
+ let output = 'Versions applied:\n';
208
+ for (const release of applied) {
209
+ output += `${release.name}: ${release.currentVersion} → ${release.newVersion}\n`;
210
+ }
211
+ return output;
212
+ }
213
+ /**
214
+ * In `registry` storage, the gate that lets consumed intents be collected:
215
+ * the release must be published and its tarball's CHANGELOG.md must already
216
+ * carry the composed section. Any error resolving that (offline, transient
217
+ * failure) counts as "not confirmed" so the intent — still the only prose —
218
+ * is kept. `undefined` in `repository` storage, where the committed changelog
219
+ * makes the ledger alone sufficient.
220
+ */
221
+ function buildVerifyPublished(opts) {
222
+ if (changelogStorage(opts.versioning) !== 'registry')
223
+ return undefined;
224
+ return async (name, version, section) => {
225
+ try {
226
+ const changelog = await fetchPublishedChangelog(opts, name, version);
227
+ return changelog != null && changelogHasSection(changelog, section);
228
+ }
229
+ catch {
230
+ return false;
231
+ }
232
+ };
233
+ }
145
234
  async function bumpPackageVersion(pkgDir, rawBump, explicitVersion, opts) {
146
235
  const { manifest, writeProjectManifest, fileName } = await readProjectManifest(pkgDir);
147
236
  if (!manifest.name || !manifest.version) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/releasing.commands",
3
- "version": "1100.5.5",
3
+ "version": "1100.6.0",
4
4
  "description": "Commands for deploy, pack, and publish",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -28,36 +28,42 @@
28
28
  ],
29
29
  "dependencies": {
30
30
  "@inquirer/prompts": "^8.4.3",
31
- "@pnpm/bins.resolver": "1100.0.8",
31
+ "@pnpm/bins.resolver": "1100.0.9",
32
32
  "@pnpm/catalogs.types": "1100.0.0",
33
33
  "@pnpm/cli.common-cli-options-help": "1100.0.2",
34
- "@pnpm/cli.utils": "1101.0.13",
35
- "@pnpm/config.pick-registry-for-package": "1100.0.9",
36
- "@pnpm/config.reader": "1101.11.2",
34
+ "@pnpm/cli.utils": "1101.0.14",
35
+ "@pnpm/config.pick-registry-for-package": "1100.0.10",
36
+ "@pnpm/config.reader": "1101.12.0",
37
37
  "@pnpm/constants": "1100.0.0",
38
- "@pnpm/deps.path": "1100.0.8",
39
- "@pnpm/engine.runtime.commands": "1100.1.10",
40
- "@pnpm/engine.runtime.node-resolver": "1101.1.12",
38
+ "@pnpm/deps.path": "1100.0.9",
39
+ "@pnpm/engine.runtime.commands": "1100.1.11",
40
+ "@pnpm/engine.runtime.node-resolver": "1101.1.13",
41
41
  "@pnpm/error": "1100.0.1",
42
- "@pnpm/exec.lifecycle": "1100.1.2",
42
+ "@pnpm/exec.lifecycle": "1100.1.3",
43
43
  "@pnpm/exec.pnpm-cli-runner": "1100.0.1",
44
- "@pnpm/fetching.directory-fetcher": "1100.0.19",
45
- "@pnpm/fs.indexed-pkg-importer": "1100.0.17",
44
+ "@pnpm/fetching.directory-fetcher": "1100.0.20",
45
+ "@pnpm/fetching.types": "1100.0.2",
46
+ "@pnpm/fs.indexed-pkg-importer": "1100.0.18",
46
47
  "@pnpm/fs.is-empty-dir-or-nothing": "1100.0.0",
47
- "@pnpm/fs.packlist": "1100.0.1",
48
- "@pnpm/installing.client": "1100.2.13",
49
- "@pnpm/installing.commands": "1100.10.4",
50
- "@pnpm/lockfile.fs": "1100.1.10",
51
- "@pnpm/lockfile.types": "1100.0.13",
52
- "@pnpm/network.auth-header": "1101.1.3",
53
- "@pnpm/network.fetch": "1100.1.4",
48
+ "@pnpm/fs.packlist": "1100.0.2",
49
+ "@pnpm/installing.client": "1100.2.14",
50
+ "@pnpm/installing.commands": "1100.10.5",
51
+ "@pnpm/lockfile.fs": "1100.1.11",
52
+ "@pnpm/lockfile.types": "1100.0.14",
53
+ "@pnpm/network.auth-header": "1101.1.4",
54
+ "@pnpm/network.fetch": "1100.1.5",
54
55
  "@pnpm/network.git-utils": "1100.0.2",
55
56
  "@pnpm/network.web-auth": "1101.2.0",
56
57
  "@pnpm/npm-package-arg": "^2.0.0",
57
- "@pnpm/releasing.exportable-manifest": "1100.1.9",
58
- "@pnpm/resolving.resolver-base": "1100.5.1",
59
- "@pnpm/types": "1101.3.2",
60
- "@pnpm/workspace.projects-sorter": "1100.0.8",
58
+ "@pnpm/releasing.exportable-manifest": "1100.1.10",
59
+ "@pnpm/releasing.versioning": "1100.1.0",
60
+ "@pnpm/resolving.npm-resolver": "1102.1.3",
61
+ "@pnpm/resolving.registry.types": "1100.1.4",
62
+ "@pnpm/resolving.resolver-base": "1100.5.2",
63
+ "@pnpm/types": "1101.4.0",
64
+ "@pnpm/workspace.projects-filter": "1100.0.27",
65
+ "@pnpm/workspace.projects-sorter": "1100.0.9",
66
+ "@pnpm/workspace.workspace-manifest-writer": "1100.0.16",
61
67
  "@types/normalize-path": "^3.0.2",
62
68
  "@zkochan/rimraf": "^4.0.0",
63
69
  "chalk": "^5.6.2",
@@ -87,17 +93,16 @@
87
93
  },
88
94
  "devDependencies": {
89
95
  "@jest/globals": "30.4.1",
90
- "@pnpm/assert-project": "1100.0.18",
96
+ "@pnpm/assert-project": "1100.0.19",
91
97
  "@pnpm/catalogs.config": "1100.0.2",
92
- "@pnpm/hooks.pnpmfile": "1100.0.18",
98
+ "@pnpm/hooks.pnpmfile": "1100.0.19",
93
99
  "@pnpm/logger": "1100.0.0",
94
- "@pnpm/prepare": "1100.0.18",
95
- "@pnpm/releasing.commands": "1100.5.5",
100
+ "@pnpm/prepare": "1100.0.19",
101
+ "@pnpm/releasing.commands": "1100.6.0",
96
102
  "@pnpm/test-fixtures": "1100.0.0",
97
103
  "@pnpm/test-ipc-server": "1100.0.0",
98
- "@pnpm/testing.command-defaults": "1100.0.8",
99
- "@pnpm/testing.registry-mock": "1100.0.8",
100
- "@pnpm/workspace.projects-filter": "1100.0.26",
104
+ "@pnpm/testing.command-defaults": "1100.0.9",
105
+ "@pnpm/testing.registry-mock": "1100.0.9",
101
106
  "@types/cross-spawn": "^6.0.6",
102
107
  "@types/is-windows": "^1.0.2",
103
108
  "@types/libnpmpublish": "^11.2.0",