@williamthorsen/release-kit 14.1.0 → 14.2.1

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.
Files changed (92) hide show
  1. package/.meta/changelog.json +136 -0
  2. package/.readyup/kits/default.js +63 -6
  3. package/.readyup/kits/npm-auto-publish.js +47 -35
  4. package/.readyup/manifest.json +12 -7
  5. package/CHANGELOG.md +39 -0
  6. package/README.md +2 -16
  7. package/dist/esm/assertTaggedBaseline.d.ts +2 -2
  8. package/dist/esm/attachChangelogDiagnostics.d.ts +2 -2
  9. package/dist/esm/bin/release-kit.js +5 -4
  10. package/dist/esm/buildChangelogEntries.d.ts +3 -3
  11. package/dist/esm/buildChangelogEntries.js +3 -3
  12. package/dist/esm/buildDependencyGraph.d.ts +11 -11
  13. package/dist/esm/buildDependencyGraph.js +13 -13
  14. package/dist/esm/buildReleaseSummary.d.ts +3 -3
  15. package/dist/esm/buildReleaseSummary.js +4 -12
  16. package/dist/esm/changelogArchive.d.ts +14 -0
  17. package/dist/esm/changelogArchive.js +21 -0
  18. package/dist/esm/changelogJsonFile.d.ts +2 -2
  19. package/dist/esm/changelogOverrides.d.ts +9 -8
  20. package/dist/esm/changelogOverrides.js +3 -6
  21. package/dist/esm/createGithubReleaseCommand.d.ts +2 -1
  22. package/dist/esm/createGithubReleaseCommand.js +7 -4
  23. package/dist/esm/deriveDirectoryConfig.d.ts +13 -0
  24. package/dist/esm/deriveDirectoryConfig.js +59 -0
  25. package/dist/esm/deriveWorkspaceConfig.js +0 -1
  26. package/dist/esm/discoverWorkspaces.d.ts +3 -3
  27. package/dist/esm/findTransitiveDependents.js +3 -3
  28. package/dist/esm/findUnroutedEntryScopes.d.ts +2 -2
  29. package/dist/esm/formatDirectoryPublishSkip.d.ts +3 -0
  30. package/dist/esm/formatDirectoryPublishSkip.js +3 -0
  31. package/dist/esm/formatExcludedSkip.d.ts +5 -2
  32. package/dist/esm/formatExcludedSkip.js +2 -2
  33. package/dist/esm/formatProjectPublishSkip.d.ts +3 -0
  34. package/dist/esm/formatProjectPublishSkip.js +3 -0
  35. package/dist/esm/generateChangelogs.d.ts +7 -7
  36. package/dist/esm/generateChangelogs.js +2 -2
  37. package/dist/esm/help/prepareHelp.d.ts +1 -1
  38. package/dist/esm/help/prepareHelp.js +7 -5
  39. package/dist/esm/init/templates.js +1 -1
  40. package/dist/esm/loadConfig.d.ts +12 -12
  41. package/dist/esm/loadConfig.js +79 -30
  42. package/dist/esm/prepareCommand.d.ts +1 -1
  43. package/dist/esm/prepareCommand.js +47 -46
  44. package/dist/esm/prepareTarget.d.ts +103 -0
  45. package/dist/esm/prepareTarget.js +274 -0
  46. package/dist/esm/previewTagPrefixes.d.ts +5 -3
  47. package/dist/esm/previewTagPrefixes.js +58 -13
  48. package/dist/esm/propagateBumps.js +1 -1
  49. package/dist/esm/publishCommand.js +13 -1
  50. package/dist/esm/readChangelogSections.d.ts +6 -4
  51. package/dist/esm/readChangelogSections.js +18 -4
  52. package/dist/esm/releasePlan.d.ts +4 -2
  53. package/dist/esm/releasePlan.js +34 -12
  54. package/dist/esm/releasePrepareTargets.d.ts +47 -0
  55. package/dist/esm/releasePrepareTargets.js +335 -0
  56. package/dist/esm/renderChangelogMarkdown.d.ts +23 -0
  57. package/dist/esm/renderChangelogMarkdown.js +47 -11
  58. package/dist/esm/reportPrepare.d.ts +2 -3
  59. package/dist/esm/reportPrepare.js +24 -12
  60. package/dist/esm/resolveCommandTags.d.ts +3 -1
  61. package/dist/esm/resolveCommandTags.js +15 -22
  62. package/dist/esm/resolveReleaseDeclaration.d.ts +45 -0
  63. package/dist/esm/resolveReleaseDeclaration.js +153 -0
  64. package/dist/esm/resolveReleaseTags.d.ts +14 -3
  65. package/dist/esm/resolveReleaseTags.js +36 -15
  66. package/dist/esm/resolveReleaseTargets.d.ts +29 -0
  67. package/dist/esm/resolveReleaseTargets.js +131 -0
  68. package/dist/esm/sync-labels/generateCommand.js +2 -1
  69. package/dist/esm/sync-labels/resolveLabels.d.ts +4 -3
  70. package/dist/esm/sync-labels/resolveLabels.js +30 -1
  71. package/dist/esm/sync-labels/types.d.ts +2 -0
  72. package/dist/esm/types.d.ts +251 -167
  73. package/dist/esm/types.js +22 -0
  74. package/dist/esm/validateConfig.js +80 -21
  75. package/dist/esm/validateOverridesCommand.d.ts +1 -1
  76. package/dist/esm/validateOverridesCommand.js +17 -28
  77. package/docs/api.md +25 -58
  78. package/docs/changelogs.md +26 -6
  79. package/docs/configuration.md +79 -16
  80. package/docs/labels.md +25 -2
  81. package/docs/project-releases.md +42 -2
  82. package/docs/publishing.md +3 -3
  83. package/docs/releasing.md +4 -4
  84. package/docs/work-types.md +1 -1
  85. package/package.json +3 -3
  86. package/presets/labels/common.yaml +11 -0
  87. package/dist/esm/releasePrepare.d.ts +0 -36
  88. package/dist/esm/releasePrepare.js +0 -230
  89. package/dist/esm/releasePrepareMono.d.ts +0 -29
  90. package/dist/esm/releasePrepareMono.js +0 -503
  91. package/dist/esm/releasePrepareProject.d.ts +0 -47
  92. package/dist/esm/releasePrepareProject.js +0 -164
@@ -64,6 +64,14 @@ export interface ChangelogJsonConfig {
64
64
  outputPath: string;
65
65
  devOnlySections: string[];
66
66
  }
67
+ /** Configuration for the rendered `CHANGELOG.md`. */
68
+ export interface ChangelogMarkdownConfig {
69
+ /**
70
+ * How many of the newest versioned sections `CHANGELOG.md` keeps; older sections go to per-major archive files
71
+ * under `changelogs/`. When omitted, `CHANGELOG.md` keeps every section.
72
+ */
73
+ keepVersions?: number;
74
+ }
67
75
  /**
68
76
  * Editorial override for changelog items, keyed in the override file by `<hash>` (every item of the commit) or
69
77
  * `<hash>:<n>` (the item derived from the commit's `n`th change-record entry), where the hash is lowercase hex
@@ -87,7 +95,10 @@ export type ChangelogOverridesFile = Record<string, ChangelogOverride>;
87
95
  export interface ReleaseNotesConfig {
88
96
  shouldInjectIntoReadme: boolean;
89
97
  }
90
- /** Project-release config after merging defaults: `ProjectConfig` with every field required. */
98
+ /**
99
+ * The composite release after merging defaults, declared by a `project` block or by a `releases` composite entry.
100
+ * Both are versioned by the root `package.json`.
101
+ */
91
102
  export interface ResolvedProjectConfig {
92
103
  /**
93
104
  * Resolved commit window for the project release: the git pathspecs that select which commits
@@ -96,6 +107,10 @@ export interface ResolvedProjectConfig {
96
107
  paths: string[];
97
108
  /** Resolved tag prefix for project-level tags. */
98
109
  tagPrefix: string;
110
+ /** Name that selects the composite; `undefined` for a `project` block, whose composite cannot be selected. */
111
+ name?: string;
112
+ /** Target names of the member workspaces; `undefined` means every retained workspace, as a `project` block has. */
113
+ members?: string[];
99
114
  }
100
115
  /** Identifies a dependency whose version bump triggered a propagated release. */
101
116
  export interface PropagationSource {
@@ -167,22 +182,12 @@ export interface ChangelogPreservation {
167
182
  /** Headings of the sections that do not name any version, which the regenerated file does not contain. */
168
183
  droppedUnversionedHeadings: string[];
169
184
  }
170
- /**
171
- * Result of preparing a single workspace (package) for release when a release was produced. `releaseType` is absent
172
- * for `--set-version`.
173
- */
174
- export interface ReleasedWorkspaceResult {
175
- status: 'released';
176
- /** Workspace name; absent in single-package mode, present in monorepo mode. */
177
- name?: string;
185
+ /** Fields of every target result: what `prepare` read from the target's unreleased window. */
186
+ interface TargetResultFields {
187
+ /** Id of the target that the result describes. */
188
+ targetId: string;
178
189
  previousTag?: string;
179
190
  commitCount: number;
180
- /**
181
- * Count of commits that yield at least one changelog item; `0` when the unreleased window does
182
- * not contain any commits or when none does. Absent for `--set-version` and propagation-only
183
- * workspaces. `bumpOverride`, not this count, signals that the user supplied `--bump=X`.
184
- */
185
- parsedCommitCount?: number;
186
191
  /** Commits that do not yield any changelog item and are not accounted for by any exclusion or diagnostic. */
187
192
  unparseableCommits?: Commit[];
188
193
  /** Policy violations of the unreleased window's titles and change-record entries; omitted when none. */
@@ -191,14 +196,17 @@ export interface ReleasedWorkspaceResult {
191
196
  malformedBlocks?: MalformedChangeRecordBlock[];
192
197
  /** Change-record entries of the unreleased window whose type is undeclared; omitted when none. */
193
198
  undeclaredEntryTypes?: UndeclaredEntryType[];
194
- /** Change-record entry scopes of the unreleased window that route their entry nowhere; omitted when none. */
195
- unroutedEntryScopes?: UnroutedEntryScope[];
196
- releaseType?: ReleaseType;
199
+ }
200
+ /** Fields of every released target result: the version, tag, and files of the release. */
201
+ interface ReleaseFields {
197
202
  currentVersion: string;
198
203
  newVersion: string;
199
204
  tag: string;
200
205
  bumpedFiles: string[];
206
+ /** The `CHANGELOG.md`, then any archive files that the release writes. */
201
207
  changelogFiles: string[];
208
+ /** Archive files of the `CHANGELOG.md` that the release removes; omitted when it removes none. */
209
+ removedChangelogFiles?: string[];
202
210
  /** Release-notes preview files; present only under `--with-release-notes`. */
203
211
  previewFiles?: string[];
204
212
  /**
@@ -206,134 +214,125 @@ export interface ReleasedWorkspaceResult {
206
214
  * any.
207
215
  */
208
216
  changelogPreservation?: ChangelogPreservation[];
209
- /** Raw commits of the workspace's unreleased window. */
210
- commits?: Commit[];
211
217
  /**
212
- * Present when `--bump=X` was supplied and selected the release level for this workspace, which
213
- * distinguishes a bump-override release from a `--force` fallback or a natural-bump release.
218
+ * Present when `--bump=X` was supplied and selected the release level, which distinguishes a bump-override release
219
+ * from a `--force` fallback or a natural-bump release.
214
220
  */
215
221
  bumpOverride?: ReleaseType;
216
- /** Dependencies that triggered a propagated bump (present for propagated or mixed workspaces). */
222
+ }
223
+ /** Fields of every package target result. */
224
+ interface PackageResultFields extends TargetResultFields {
225
+ kind: 'package';
226
+ /** Workspace `dir`; absent for the single-package root. */
227
+ name?: string;
228
+ /** Change-record entry scopes of the unreleased window that route their entry nowhere; omitted when none. */
229
+ unroutedEntryScopes?: UnroutedEntryScope[];
230
+ }
231
+ /** Result of a package target that releases. `releaseType` is absent for `--set-version`. */
232
+ export interface ReleasedPackageResult extends PackageResultFields, ReleaseFields {
233
+ status: 'released';
234
+ /**
235
+ * Count of commits that yield at least one changelog item; `0` when the unreleased window does
236
+ * not contain any commits or when none does. Absent for `--set-version` and propagation-only
237
+ * releases. `bumpOverride`, not this count, signals that the user supplied `--bump=X`.
238
+ */
239
+ parsedCommitCount?: number;
240
+ releaseType?: ReleaseType;
241
+ /** Raw commits of the package's unreleased window. */
242
+ commits?: Commit[];
243
+ /** Dependencies that triggered a propagated bump (present for propagated or mixed releases). */
217
244
  propagatedFrom?: PropagationSource[];
218
- /** Present when propagation alone set the bump, the workspace's own commits having called for none. */
245
+ /** Present when propagation alone set the bump, the package's own commits having called for none. */
219
246
  propagatedOnly?: true;
220
- /** Present when this workspace was written via `--set-version`; the explicit version that was applied. */
247
+ /** Present when the package was written via `--set-version`; the explicit version that was applied. */
221
248
  setVersion?: string;
222
249
  }
223
- /**
224
- * Result of preparing a single workspace (package) for release when the release was skipped: the diagnostic fields
225
- * and a human-readable `skipReason`, without the release-only fields.
226
- */
227
- export interface SkippedWorkspaceResult {
250
+ /** Result of a package target that skips: the diagnostic fields and a human-readable `skipReason`. */
251
+ export interface SkippedPackageResult extends PackageResultFields {
228
252
  status: 'skipped';
229
- /** Workspace name; absent in single-package mode, present in monorepo mode. */
230
- name?: string;
231
- previousTag?: string;
232
- commitCount: number;
233
253
  /**
234
254
  * Count of commits that yield at least one changelog item; `0` when the unreleased window does not contain any
235
255
  * commits or when none does.
236
256
  */
237
257
  parsedCommitCount: number;
238
- /** Commits that do not yield any changelog item and are not accounted for by any exclusion or diagnostic. */
239
- unparseableCommits?: Commit[];
240
- /** Policy violations of the unreleased window's titles and change-record entries; omitted when none. */
241
- policyViolations?: PolicyViolation[];
242
- /** Commits of the unreleased window whose `change-record` block could not be read; omitted when none. */
243
- malformedBlocks?: MalformedChangeRecordBlock[];
244
- /** Change-record entries of the unreleased window whose type is undeclared; omitted when none. */
245
- undeclaredEntryTypes?: UndeclaredEntryType[];
258
+ skipReason: string;
259
+ }
260
+ /** Fields of every directory target result. */
261
+ interface DirectoryResultFields extends TargetResultFields {
262
+ kind: 'directory';
263
+ /** Name of the directory target. */
264
+ name: string;
246
265
  /** Change-record entry scopes of the unreleased window that route their entry nowhere; omitted when none. */
247
266
  unroutedEntryScopes?: UnroutedEntryScope[];
248
- skipReason: string;
249
267
  }
250
268
  /**
251
- * Result of preparing a single workspace (package) for release.
252
- *
253
- * Discriminated by `status`: `ReleasedWorkspaceResult` for produced releases,
254
- * `SkippedWorkspaceResult` for skips.
269
+ * Result of a directory target that releases. A directory never propagates; `releaseType` and `parsedCommitCount` are
270
+ * absent for `--set-version`.
255
271
  */
256
- export type WorkspacePrepareResult = ReleasedWorkspaceResult | SkippedWorkspaceResult;
272
+ export interface ReleasedDirectoryResult extends DirectoryResultFields, ReleaseFields {
273
+ status: 'released';
274
+ /**
275
+ * Count of commits that yield at least one changelog item; `0` when the unreleased window does not contain any
276
+ * commits or when none does.
277
+ */
278
+ parsedCommitCount?: number;
279
+ releaseType?: ReleaseType;
280
+ /** Raw commits of the directory's unreleased window. */
281
+ commits: Commit[];
282
+ /** Present when the directory was written via `--set-version`; the explicit version that was applied. */
283
+ setVersion?: string;
284
+ }
285
+ /** Result of a directory target that skips: the diagnostic fields and a human-readable `skipReason`. */
286
+ export interface SkippedDirectoryResult extends DirectoryResultFields {
287
+ status: 'skipped';
288
+ /**
289
+ * Count of commits that yield at least one changelog item; `0` when the unreleased window does not contain any
290
+ * commits or when none does.
291
+ */
292
+ parsedCommitCount: number;
293
+ skipReason: string;
294
+ }
257
295
  /**
258
- * Result of preparing a project-level release when a release was produced.
259
- *
260
- * Mirrors `ReleasedWorkspaceResult` without the workspace-only fields. Project releases never propagate and never
261
- * use `--set-version`, so `releaseType`, `parsedCommitCount`, and `commits` are required.
296
+ * Result of a composite target that releases. A composite never propagates and never takes `--set-version`, so
297
+ * `releaseType`, `parsedCommitCount`, and `commits` are required.
262
298
  */
263
- export interface ReleasedProjectResult {
299
+ export interface ReleasedCompositeResult extends TargetResultFields, ReleaseFields {
264
300
  status: 'released';
265
- previousTag?: string;
266
- commitCount: number;
301
+ kind: 'composite';
267
302
  /**
268
303
  * Count of commits that yield at least one changelog item; `0` when the unreleased window does
269
- * not contain any commits or when none does. `bumpOverride`, not a zero count, signals that the
270
- * user supplied `--bump=X`.
304
+ * not contain any commits or when none does.
271
305
  */
272
306
  parsedCommitCount: number;
273
- /** Commits that do not yield any changelog item and are not accounted for by any exclusion or diagnostic. */
274
- unparseableCommits?: Commit[];
275
- /** Policy violations of the unreleased window's titles and change-record entries; omitted when none. */
276
- policyViolations?: PolicyViolation[];
277
- /** Commits of the unreleased window whose `change-record` block could not be read; omitted when none. */
278
- malformedBlocks?: MalformedChangeRecordBlock[];
279
- /** Change-record entries of the unreleased window whose type is undeclared; omitted when none. */
280
- undeclaredEntryTypes?: UndeclaredEntryType[];
281
307
  releaseType: ReleaseType;
282
- currentVersion: string;
283
- newVersion: string;
284
- tag: string;
285
- bumpedFiles: string[];
286
- changelogFiles: string[];
287
- /** Release-notes preview files; present only under `--with-release-notes`. */
288
- previewFiles?: string[];
289
- /**
290
- * Per `CHANGELOG.md`, the existing sections that were kept or dropped; omitted when `prepare` did not keep or drop
291
- * any.
292
- */
293
- changelogPreservation?: ChangelogPreservation[];
294
- /** Raw commits in the project's contributing-paths window since the last project tag. */
308
+ /** Raw commits of the composite's commit window since its last tag. */
295
309
  commits: Commit[];
296
- /**
297
- * Present when `--bump=X` was supplied and selected the release level for the project, which
298
- * distinguishes a bump-override release from a `--force` fallback or a natural-bump release.
299
- */
300
- bumpOverride?: ReleaseType;
301
310
  }
302
- /**
303
- * Result of preparing a project-level release when the release was skipped: the diagnostic fields and a
304
- * human-readable `skipReason`, without the release-only fields.
305
- */
306
- export interface SkippedProjectResult {
311
+ /** Result of a composite target that skips: the diagnostic fields and a human-readable `skipReason`. */
312
+ export interface SkippedCompositeResult extends TargetResultFields {
307
313
  status: 'skipped';
308
- previousTag?: string;
309
- commitCount: number;
314
+ kind: 'composite';
310
315
  /**
311
316
  * Count of commits that yield at least one changelog item; `0` when the unreleased window does not contain any
312
317
  * commits or when none does.
313
318
  */
314
319
  parsedCommitCount: number;
315
- /** Commits that do not yield any changelog item and are not accounted for by any exclusion or diagnostic. */
316
- unparseableCommits?: Commit[];
317
- /** Policy violations of the unreleased window's titles and change-record entries; omitted when none. */
318
- policyViolations?: PolicyViolation[];
319
- /** Commits of the unreleased window whose `change-record` block could not be read; omitted when none. */
320
- malformedBlocks?: MalformedChangeRecordBlock[];
321
- /** Change-record entries of the unreleased window whose type is undeclared; omitted when none. */
322
- undeclaredEntryTypes?: UndeclaredEntryType[];
323
320
  skipReason: string;
324
321
  }
325
- /**
326
- * Result of preparing a project-level release.
327
- *
328
- * Discriminated by `status`: `ReleasedProjectResult` for produced releases,
329
- * `SkippedProjectResult` for skips. `PrepareResult.project === undefined` means either that
330
- * the config does not declare a `project` block or that `--only` narrowed the run, which skips
331
- * the stage before it can produce a result; `prepare` reports the skip as a run warning instead.
332
- */
333
- export type ProjectPrepareResult = ReleasedProjectResult | SkippedProjectResult;
334
- /** Aggregate result of the prepare workflow for both single-package and monorepo modes. */
322
+ /** Result of preparing a package target, discriminated by `status`. */
323
+ export type PackagePrepareResult = ReleasedPackageResult | SkippedPackageResult;
324
+ /** Result of preparing a directory target, discriminated by `status`. */
325
+ export type DirectoryPrepareResult = ReleasedDirectoryResult | SkippedDirectoryResult;
326
+ /** Result of preparing a composite target, discriminated by `status`. */
327
+ export type CompositePrepareResult = ReleasedCompositeResult | SkippedCompositeResult;
328
+ /** Result of preparing one release target, discriminated by `kind` and by `status`. */
329
+ export type TargetPrepareResult = PackagePrepareResult | DirectoryPrepareResult | CompositePrepareResult;
330
+ /** Result of a target that releases, of any kind. */
331
+ export type ReleasedTargetResult = ReleasedPackageResult | ReleasedDirectoryResult | ReleasedCompositeResult;
332
+ /** Aggregate result of the prepare workflow over a run's targets. */
335
333
  export interface PrepareResult {
336
- workspaces: WorkspacePrepareResult[];
334
+ /** One result per target that the run prepared: the package targets in config order, then the composites. */
335
+ targets: TargetPrepareResult[];
337
336
  tags: string[];
338
337
  formatCommand?: {
339
338
  command: string;
@@ -341,8 +340,6 @@ export interface PrepareResult {
341
340
  } | undefined;
342
341
  /** Warnings reported during preparation (e.g., circular dependency detection). */
343
342
  warnings?: string[] | undefined;
344
- /** Result of the project-level release stage (present only when `config.project` is configured and the stage ran). */
345
- project?: ProjectPrepareResult | undefined;
346
343
  }
347
344
  /** Configuration for a single work type used in commit categorization. */
348
345
  export interface WorkTypeConfig {
@@ -416,12 +413,54 @@ export declare const projectConfigSchema: z.ZodObject<{
416
413
  }, z.core.$strict>;
417
414
  /** Consumer-facing project-release config (`project` block). Empty object opts in to project releases. */
418
415
  export type ProjectConfig = z.infer<typeof projectConfigSchema>;
416
+ /**
417
+ * Schema for a `releases` entry that names the target at `path`: the discovered workspace there, or otherwise the
418
+ * directory, whose `tagPrefix` defaults to its basename followed by `-v`.
419
+ */
420
+ export declare const pathReleaseSchema: z.ZodObject<{
421
+ path: z.ZodString;
422
+ tagPrefix: z.ZodOptional<z.ZodString>;
423
+ legacyIdentities: z.ZodOptional<z.ZodArray<z.ZodObject<{
424
+ name: z.ZodString;
425
+ tagPrefix: z.ZodString;
426
+ }, z.core.$strict>>>;
427
+ }, z.core.$strict>;
428
+ /** A `releases` entry that names the discovered workspace or the directory at `path`. */
429
+ export type PathRelease = z.infer<typeof pathReleaseSchema>;
430
+ /** Schema for a `releases` entry that declares a composite of the named targets. */
431
+ export declare const compositeReleaseSchema: z.ZodObject<{
432
+ includes: z.ZodArray<z.ZodString>;
433
+ tagPrefix: z.ZodOptional<z.ZodString>;
434
+ }, z.core.$strict>;
435
+ /** A `releases` entry that declares a composite of the named targets, versioned by the root `package.json`. */
436
+ export type CompositeRelease = z.infer<typeof compositeReleaseSchema>;
437
+ /**
438
+ * Schema for one `releases` entry: `false` excludes the discovered workspace of that name, and the object shapes name
439
+ * a workspace or a directory, or declare the composite. `validateConfig` relies on this branch order to report a failed entry.
440
+ */
441
+ export declare const releaseEntrySchema: z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
442
+ path: z.ZodString;
443
+ tagPrefix: z.ZodOptional<z.ZodString>;
444
+ legacyIdentities: z.ZodOptional<z.ZodArray<z.ZodObject<{
445
+ name: z.ZodString;
446
+ tagPrefix: z.ZodString;
447
+ }, z.core.$strict>>>;
448
+ }, z.core.$strict>, z.ZodObject<{
449
+ includes: z.ZodArray<z.ZodString>;
450
+ tagPrefix: z.ZodOptional<z.ZodString>;
451
+ }, z.core.$strict>]>;
452
+ /** One `releases` entry, keyed in the config by the target's name. */
453
+ export type ReleaseEntry = z.infer<typeof releaseEntrySchema>;
419
454
  /** Schema for the optional `changelogJson` block (input shape, all fields optional). */
420
455
  export declare const changelogJsonInputSchema: z.ZodObject<{
421
456
  enabled: z.ZodOptional<z.ZodBoolean>;
422
457
  outputPath: z.ZodOptional<z.ZodString>;
423
458
  devOnlySections: z.ZodOptional<z.ZodArray<z.ZodString>>;
424
459
  }, z.core.$strict>;
460
+ /** Schema for the optional `changelogMarkdown` block (input shape, all fields optional). */
461
+ export declare const changelogMarkdownInputSchema: z.ZodObject<{
462
+ keepVersions: z.ZodOptional<z.ZodNumber>;
463
+ }, z.core.$strict>;
425
464
  /** Schema for the optional `releaseNotes` block (input shape, all fields optional). */
426
465
  export declare const releaseNotesInputSchema: z.ZodObject<{
427
466
  shouldInjectIntoReadme: z.ZodOptional<z.ZodBoolean>;
@@ -446,13 +485,15 @@ export declare const breakingPolicyValueSchema: z.ZodEnum<{
446
485
  export declare const labelSpecSchema: z.ZodObject<{
447
486
  color: z.ZodString;
448
487
  description: z.ZodOptional<z.ZodString>;
488
+ aliases: z.ZodOptional<z.ZodArray<z.ZodString>>;
449
489
  archived: z.ZodOptional<z.ZodLiteral<true>>;
450
490
  }, z.core.$strict>;
451
491
  /**
452
- * A label's color, optional description, and optional archived mark; the name is the record key in
492
+ * A label's color, optional description, optional aliases, and optional archived mark; the name is the record key in
453
493
  * `repoLabels.labels`. An omitted description resolves to empty, which the generated labels file declares explicitly
454
- * so that a sync clears whatever description the label has on the repo. `archived: true` retires the label: The sync
455
- * archives it, keeping it on the issues and pull requests that have it.
494
+ * so that a sync clears whatever description the label has on the repo. Each alias names an existing label that the
495
+ * sync renames to this one in place, keeping it on the issues and pull requests that have it. `archived: true` retires
496
+ * the label: The sync archives it, keeping it on the issues and pull requests that have it.
456
497
  */
457
498
  export type LabelSpec = z.infer<typeof labelSpecSchema>;
458
499
  /**
@@ -462,14 +503,16 @@ export type LabelSpec = z.infer<typeof labelSpecSchema>;
462
503
  * Resolution is an ordered fold with last-writer-wins: presets in `extends` order, then the `labels` record,
463
504
  * in which an entry adds a label, replaces one that an earlier layer defined, or removes it (`null`). Names match
464
505
  * case-insensitively, as GitHub matches them, and the replacing layer's spelling wins.
465
- * Two misstatements are resolve-time errors (`resolveLabels`), not schema errors: `labels` keys that differ only in
466
- * case, and a `null` naming a label not defined by any earlier layer.
506
+ * Three misstatements are resolve-time errors (`resolveLabels`), not schema errors: `labels` keys that differ only in
507
+ * case, a `null` naming a label not defined by any earlier layer, and an alias that names a resolved label or repeats
508
+ * another alias.
467
509
  */
468
510
  export declare const repoLabelsSchema: z.ZodObject<{
469
511
  extends: z.ZodOptional<z.ZodArray<z.ZodString>>;
470
512
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodObject<{
471
513
  color: z.ZodString;
472
514
  description: z.ZodOptional<z.ZodString>;
515
+ aliases: z.ZodOptional<z.ZodArray<z.ZodString>>;
473
516
  archived: z.ZodOptional<z.ZodLiteral<true>>;
474
517
  }, z.core.$strict>>>>;
475
518
  }, z.core.$strict>;
@@ -486,6 +529,9 @@ export declare const releaseKitConfigSchema: z.ZodObject<{
486
529
  outputPath: z.ZodOptional<z.ZodString>;
487
530
  devOnlySections: z.ZodOptional<z.ZodArray<z.ZodString>>;
488
531
  }, z.core.$strict>>;
532
+ changelogMarkdown: z.ZodOptional<z.ZodObject<{
533
+ keepVersions: z.ZodOptional<z.ZodNumber>;
534
+ }, z.core.$strict>>;
489
535
  formatCommand: z.ZodOptional<z.ZodString>;
490
536
  project: z.ZodOptional<z.ZodObject<{
491
537
  paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -494,11 +540,23 @@ export declare const releaseKitConfigSchema: z.ZodObject<{
494
540
  releaseNotes: z.ZodOptional<z.ZodObject<{
495
541
  shouldInjectIntoReadme: z.ZodOptional<z.ZodBoolean>;
496
542
  }, z.core.$strict>>;
543
+ releases: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
544
+ path: z.ZodString;
545
+ tagPrefix: z.ZodOptional<z.ZodString>;
546
+ legacyIdentities: z.ZodOptional<z.ZodArray<z.ZodObject<{
547
+ name: z.ZodString;
548
+ tagPrefix: z.ZodString;
549
+ }, z.core.$strict>>>;
550
+ }, z.core.$strict>, z.ZodObject<{
551
+ includes: z.ZodArray<z.ZodString>;
552
+ tagPrefix: z.ZodOptional<z.ZodString>;
553
+ }, z.core.$strict>]>>>;
497
554
  repoLabels: z.ZodOptional<z.ZodObject<{
498
555
  extends: z.ZodOptional<z.ZodArray<z.ZodString>>;
499
556
  labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodObject<{
500
557
  color: z.ZodString;
501
558
  description: z.ZodOptional<z.ZodString>;
559
+ aliases: z.ZodOptional<z.ZodArray<z.ZodString>>;
502
560
  archived: z.ZodOptional<z.ZodLiteral<true>>;
503
561
  }, z.core.$strict>>>>;
504
562
  }, z.core.$strict>>;
@@ -555,10 +613,26 @@ export interface ParsedCommit {
555
613
  /** Whether this is a breaking change. */
556
614
  breaking: boolean;
557
615
  }
616
+ /** A directory that a `releases` entry declares as a release target, as config merging resolves it. */
617
+ export interface DirectoryConfig {
618
+ /** Name of the release target, its `releases` entry key. */
619
+ name: string;
620
+ /** Repo-relative POSIX path of the directory; `.` for the repo root. */
621
+ path: string;
622
+ /** Repo-relative JSON file whose `version` field the release bumps: the directory's `package.json` or `version.json`. */
623
+ versionFile: string;
624
+ /** Git pathspecs of the commit window; `undefined` for the repo root, whose window is the whole repo. */
625
+ paths?: string[];
626
+ tagPrefix: string;
627
+ /** Prior identities, whose tag prefixes are searched alongside `tagPrefix`; `undefined` equals the empty array. */
628
+ legacyIdentities?: LegacyIdentity[];
629
+ }
558
630
  /** Per-workspace configuration for monorepo releases. */
559
631
  export interface WorkspaceConfig {
560
- /** The package directory name (e.g., 'arrays'). Used for display and `--only` matching. */
632
+ /** The package directory name (e.g., 'arrays'), which names the workspace's release target by default. */
561
633
  dir: string;
634
+ /** Name of the workspace's release target when a `releases` entry renames it; `undefined` means `dir`. */
635
+ targetName?: string;
562
636
  /** The full scoped npm name from `package.json` (e.g., `'@williamthorsen/nmr-core'`). */
563
637
  name: string;
564
638
  /** The git tag prefix for this workspace (e.g., 'nmr-core-v'), derived from the unscoped `package.json` name. */
@@ -572,8 +646,6 @@ export interface WorkspaceConfig {
572
646
  isPublishable: boolean;
573
647
  /** Paths to package.json files to bump. */
574
648
  packageFiles: string[];
575
- /** Directories in which to generate changelogs. */
576
- changelogPaths: string[];
577
649
  /** Glob patterns passed to `git log -- <paths>` for commit filtering. */
578
650
  paths: string[];
579
651
  /**
@@ -583,52 +655,8 @@ export interface WorkspaceConfig {
583
655
  */
584
656
  legacyIdentities?: LegacyIdentity[];
585
657
  }
586
- /** Configuration for a monorepo release workflow with multiple workspaces. */
587
- export interface MonorepoReleaseConfig {
588
- /** Ordered list of workspace configurations. */
589
- workspaces: WorkspaceConfig[];
590
- /** Work type configurations shared across all workspaces. Defaults to `DEFAULT_WORK_TYPES`. */
591
- workTypes?: Record<string, WorkTypeConfig>;
592
- /** Version bump patterns. Defaults to `DEFAULT_VERSION_PATTERNS`. */
593
- versionPatterns?: VersionPatterns;
594
- /**
595
- * Per-canonical-type breaking-policy lookup. Defaults to `DEFAULT_BREAKING_POLICIES`.
596
- * When provided, replaces the default entirely.
597
- * Pass `{}` to disable enforcement (parser falls back to `'optional'` for missing types).
598
- */
599
- breakingPolicies?: Record<string, BreakingPolicy>;
600
- /**
601
- * Shell command to run after all changelogs are generated (e.g., 'pnpm run fmt').
602
- * Modified file paths (package.json files and CHANGELOGs) are appended as space-separated
603
- * arguments. Paths are repo-relative; file paths containing spaces are not supported.
604
- */
605
- formatCommand?: string;
606
- /**
607
- * Maps scope shorthand names to their canonical names.
608
- * When a commit uses `shorthand|type: description` or `type(shorthand): description`,
609
- * the shorthand is resolved to the canonical scope name before the parsed commit is returned.
610
- */
611
- scopeAliases?: Record<string, string>;
612
- /** Controls structured changelog JSON generation. */
613
- changelogJson: ChangelogJsonConfig;
614
- /** Controls release notes consumption (README injection). */
615
- releaseNotes: ReleaseNotesConfig;
616
- /**
617
- * Project-level release config. Present when the config declares a `project` block, in which case
618
- * `prepare` runs a project-release stage after the per-workspace loop.
619
- */
620
- project?: ResolvedProjectConfig;
621
- }
622
- /** Monorepo config as seen by the prepare workflow, which does not read release-notes configuration. */
623
- export type MonorepoPrepareConfig = Omit<MonorepoReleaseConfig, 'releaseNotes'>;
624
- /** Configuration for the release workflow. */
625
- export interface ReleaseConfig {
626
- /** The git tag prefix used to identify version tags (e.g., 'v'). */
627
- tagPrefix: string;
628
- /** Paths to package.json files to bump. */
629
- packageFiles: string[];
630
- /** Paths to directories in which to generate changelogs. */
631
- changelogPaths: string[];
658
+ /** Release settings that every target of a run shares, as config merging resolves them. */
659
+ export interface ReleaseSettings {
632
660
  /** Work type configurations. Defaults to `DEFAULT_WORK_TYPES`. */
633
661
  workTypes?: Record<string, WorkTypeConfig>;
634
662
  /** Version bump patterns. Defaults to `DEFAULT_VERSION_PATTERNS`. */
@@ -653,8 +681,64 @@ export interface ReleaseConfig {
653
681
  scopeAliases?: Record<string, string>;
654
682
  /** Controls structured changelog JSON generation. */
655
683
  changelogJson: ChangelogJsonConfig;
684
+ /** Bounds the rendered `CHANGELOG.md`; `undefined` renders every version. */
685
+ changelogMarkdown?: ChangelogMarkdownConfig;
656
686
  /** Controls release notes consumption (README injection). */
657
687
  releaseNotes: ReleaseNotesConfig;
658
688
  }
659
- /** Single-package config as seen by the prepare workflow, which does not read release-notes configuration. */
660
- export type PrepareConfig = Omit<ReleaseConfig, 'releaseNotes'>;
689
+ /** Fields that every kind of release target declares. */
690
+ interface ReleaseTargetBase {
691
+ /** Selects the target, as `--only` does; never a source of tag names. */
692
+ id: string;
693
+ /** Prefix of the target's version tags (e.g., `'nmr-core-v'`). */
694
+ tagPrefix: string;
695
+ /** Prior identities, whose tag prefixes are searched alongside `tagPrefix`; `undefined` equals the empty array. */
696
+ legacyIdentities?: LegacyIdentity[];
697
+ /** Repo-relative files whose `version` field the release bumps. */
698
+ versionFiles: string[];
699
+ /** Repo-relative directory that contains the target's `CHANGELOG.md` and changelog JSON. */
700
+ changelogDir: string;
701
+ /** Git pathspecs that bound the target's commit window; `undefined` reads the whole repo. */
702
+ paths?: string[];
703
+ /** Whether a release of the target publishes to a registry. */
704
+ isPublishable: boolean;
705
+ }
706
+ /** A releasable package: a workspace of a monorepo, or the root of a single-package repo. */
707
+ export interface PackageTarget extends ReleaseTargetBase {
708
+ kind: 'package';
709
+ /** The npm name from `package.json`; undefined for the single-package root. */
710
+ packageName?: string;
711
+ /** Repo-relative path to the package root (e.g., `packages/core`, or `.` for the single-package root). */
712
+ packagePath: string;
713
+ /** Whether the target is a monorepo workspace, whose change-record entries route by scope to its `id`. */
714
+ isWorkspace: boolean;
715
+ }
716
+ /** A releasable directory that isn't a workspace, versioned by its `package.json` or `version.json`. */
717
+ export interface DirectoryTarget extends ReleaseTargetBase {
718
+ kind: 'directory';
719
+ /** Repo-relative path to the directory; `.` for the repo root, whose window is the whole repo. */
720
+ directoryPath: string;
721
+ }
722
+ /** A release that rolls up other targets, such as the project release of a monorepo. */
723
+ export interface CompositeTarget extends ReleaseTargetBase {
724
+ kind: 'composite';
725
+ /** Ids of the package and directory targets that the composite rolls up. */
726
+ members: string[];
727
+ }
728
+ /** One releasable thing, whatever shape of config declared it. */
729
+ export type ReleaseTarget = PackageTarget | DirectoryTarget | CompositeTarget;
730
+ /** Configuration for a monorepo release workflow with multiple workspaces. */
731
+ export interface MonorepoReleaseConfig extends ReleaseSettings {
732
+ /** Ordered list of workspace configurations. */
733
+ workspaces: WorkspaceConfig[];
734
+ /** Discovered workspaces that the config excludes, which tag resolution still matches; `undefined` means none. */
735
+ excludedWorkspaces?: WorkspaceConfig[];
736
+ /** Directories that the `releases` block declares as targets, in config order; `undefined` means none. */
737
+ directories?: DirectoryConfig[];
738
+ /**
739
+ * Project-level release config. Present when the config declares a `project` block, in which case
740
+ * `prepare` runs a project-release stage after the per-workspace loop.
741
+ */
742
+ project?: ResolvedProjectConfig;
743
+ }
744
+ export {};
package/dist/esm/types.js CHANGED
@@ -25,6 +25,20 @@ export const projectConfigSchema = z
25
25
  tagPrefix: z.string().min(1).optional(),
26
26
  })
27
27
  .strict();
28
+ export const pathReleaseSchema = z
29
+ .object({
30
+ path: z.string().min(1),
31
+ tagPrefix: z.string().min(1).optional(),
32
+ legacyIdentities: z.array(legacyIdentitySchema).optional(),
33
+ })
34
+ .strict();
35
+ export const compositeReleaseSchema = z
36
+ .object({
37
+ includes: z.array(z.string().min(1)).min(1),
38
+ tagPrefix: z.string().min(1).optional(),
39
+ })
40
+ .strict();
41
+ export const releaseEntrySchema = z.union([z.literal(false), pathReleaseSchema, compositeReleaseSchema]);
28
42
  export const changelogJsonInputSchema = z
29
43
  .object({
30
44
  enabled: z.boolean().optional(),
@@ -32,6 +46,11 @@ export const changelogJsonInputSchema = z
32
46
  devOnlySections: z.array(z.string()).optional(),
33
47
  })
34
48
  .strict();
49
+ export const changelogMarkdownInputSchema = z
50
+ .object({
51
+ keepVersions: z.number().int().min(1).optional(),
52
+ })
53
+ .strict();
35
54
  export const releaseNotesInputSchema = z
36
55
  .object({
37
56
  shouldInjectIntoReadme: z.boolean().optional(),
@@ -55,6 +74,7 @@ export const labelSpecSchema = z
55
74
  .object({
56
75
  color: z.string().min(1),
57
76
  description: z.string().optional(),
77
+ aliases: z.array(z.string().min(1)).min(1).optional(),
58
78
  archived: z.literal(true).optional(),
59
79
  })
60
80
  .strict();
@@ -68,9 +88,11 @@ export const releaseKitConfigSchema = z
68
88
  .object({
69
89
  breakingPolicies: z.record(z.string(), breakingPolicyValueSchema).optional(),
70
90
  changelogJson: changelogJsonInputSchema.optional(),
91
+ changelogMarkdown: changelogMarkdownInputSchema.optional(),
71
92
  formatCommand: z.string().min(1).optional(),
72
93
  project: projectConfigSchema.optional(),
73
94
  releaseNotes: releaseNotesInputSchema.optional(),
95
+ releases: z.record(z.string().min(1), releaseEntrySchema).optional(),
74
96
  repoLabels: repoLabelsSchema.optional(),
75
97
  retiredPackages: z.array(retiredPackageSchema).optional(),
76
98
  scopeAliases: z.record(z.string(), z.string()).optional(),