@williamthorsen/release-kit 12.0.0 → 13.0.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.
- package/.meta/changelog.json +212 -0
- package/.readyup/kits/default.js +18 -17
- package/.readyup/kits/npm-auto-publish.js +24 -23
- package/.readyup/manifest.json +16 -11
- package/CHANGELOG.md +58 -0
- package/README.md +55 -48
- package/bin/release-kit.js +1 -1
- package/dist/esm/assertCleanWorkingTree.d.ts +1 -5
- package/dist/esm/assertTaggedBaseline.d.ts +29 -0
- package/dist/esm/assertTaggedBaseline.js +41 -0
- package/dist/esm/attachChangelogDiagnostics.d.ts +1 -1
- package/dist/esm/attachChangelogDiagnostics.js +3 -0
- package/dist/esm/bin/release-kit.js +85 -22
- package/dist/esm/buildChangelogEntries.d.ts +23 -13
- package/dist/esm/buildChangelogEntries.js +36 -17
- package/dist/esm/buildDependencyGraph.d.ts +6 -6
- package/dist/esm/buildEmptyReleaseEntry.d.ts +1 -8
- package/dist/esm/buildReleaseSummary.d.ts +2 -8
- package/dist/esm/buildSyntheticChangelogEntry.d.ts +3 -5
- package/dist/esm/buildSyntheticChangelogEntry.js +2 -2
- package/dist/esm/bumpVersion.d.ts +1 -8
- package/dist/esm/changelogJsonFile.d.ts +5 -7
- package/dist/esm/changelogJsonFile.js +2 -17
- package/dist/esm/changelogJsonUtils.d.ts +7 -10
- package/dist/esm/changelogOverrides.d.ts +59 -98
- package/dist/esm/classifyChangelogCommit.d.ts +7 -9
- package/dist/esm/classifyChangelogCommit.js +3 -2
- package/dist/esm/commitCommand.d.ts +2 -4
- package/dist/esm/compareVersions.d.ts +10 -4
- package/dist/esm/compareVersions.js +16 -0
- package/dist/esm/configFlagSchema.d.ts +1 -1
- package/dist/esm/createGithubRelease.d.ts +7 -19
- package/dist/esm/createGithubReleaseCommand.d.ts +5 -5
- package/dist/esm/createGithubReleaseCommand.js +9 -9
- package/dist/esm/createTags.d.ts +2 -3
- package/dist/esm/decideRelease.d.ts +2 -6
- package/dist/esm/defaults.d.ts +5 -24
- package/dist/esm/defaults.js +4 -5
- package/dist/esm/defineConfig.d.ts +1 -1
- package/dist/esm/deleteFileIfExists.d.ts +1 -1
- package/dist/esm/deriveReleaseNotesConfig.d.ts +20 -0
- package/dist/esm/deriveReleaseNotesConfig.js +21 -0
- package/dist/esm/deriveWorkspaceConfig.d.ts +3 -5
- package/dist/esm/detectPackageManager.d.ts +2 -4
- package/dist/esm/detectUndeclaredTagPrefixes.d.ts +4 -6
- package/dist/esm/detectUndeclaredTagPrefixes.js +1 -1
- package/dist/esm/determineBumpType.d.ts +1 -1
- package/dist/esm/discoverWorkspaces.d.ts +14 -15
- package/dist/esm/discoverWorkspaces.js +12 -12
- package/dist/esm/enterRepoRoot.d.ts +12 -0
- package/dist/esm/enterRepoRoot.js +16 -0
- package/dist/esm/enumerateReleaseWindows.d.ts +8 -8
- package/dist/esm/extractMigration.d.ts +6 -8
- package/dist/esm/findUnroutedEntryScopes.d.ts +16 -0
- package/dist/esm/findUnroutedEntryScopes.js +57 -0
- package/dist/esm/formatExcludedSkip.d.ts +3 -0
- package/dist/esm/formatExcludedSkip.js +3 -0
- package/dist/esm/formatPrivateSkip.d.ts +1 -6
- package/dist/esm/generateChangelogs.d.ts +10 -5
- package/dist/esm/glyphs.d.ts +1 -1
- package/dist/esm/help/prepareHelp.d.ts +3 -4
- package/dist/esm/help/prepareHelp.js +4 -3
- package/dist/esm/init/checks.d.ts +3 -3
- package/dist/esm/init/checks.js +4 -1
- package/dist/esm/init/detectRepoType.d.ts +2 -3
- package/dist/esm/init/hasProvenance.d.ts +2 -0
- package/dist/esm/init/hasProvenance.js +3 -0
- package/dist/esm/init/initCommand.d.ts +3 -6
- package/dist/esm/init/initCommand.js +10 -10
- package/dist/esm/init/parseJsonRecord.d.ts +1 -4
- package/dist/esm/init/scaffold.d.ts +1 -1
- package/dist/esm/init/templates.d.ts +9 -11
- package/dist/esm/init/templates.js +12 -11
- package/dist/esm/init/updateTemplatesCommand.d.ts +13 -0
- package/dist/esm/init/updateTemplatesCommand.js +64 -0
- package/dist/esm/injectReleaseNotesIntoReadme.d.ts +12 -17
- package/dist/esm/injectSection.d.ts +3 -3
- package/dist/esm/loadConfig.d.ts +16 -14
- package/dist/esm/loadConfig.js +2 -2
- package/dist/esm/loadValidatedConfig.d.ts +16 -19
- package/dist/esm/loadValidatedConfig.js +6 -1
- package/dist/esm/packsPath.d.ts +9 -9
- package/dist/esm/parseChangeRecordBlock.d.ts +2 -2
- package/dist/esm/parseCommitMessage.d.ts +17 -32
- package/dist/esm/parseCommitMessage.js +28 -37
- package/dist/esm/parseRequestedTags.d.ts +3 -3
- package/dist/esm/planReleaseNotesPreviews.d.ts +6 -6
- package/dist/esm/planVersionBump.d.ts +5 -3
- package/dist/esm/planVersionBump.js +3 -0
- package/dist/esm/prepareCommand.d.ts +4 -7
- package/dist/esm/prepareCommand.js +13 -6
- package/dist/esm/previewTagPrefixes.d.ts +8 -10
- package/dist/esm/propagateBumps.d.ts +6 -7
- package/dist/esm/publish.d.ts +1 -1
- package/dist/esm/publishCommand.d.ts +4 -3
- package/dist/esm/publishCommand.js +8 -8
- package/dist/esm/pushCommand.d.ts +4 -3
- package/dist/esm/pushCommand.js +8 -2
- package/dist/esm/pushRelease.d.ts +2 -2
- package/dist/esm/readChangelogSections.d.ts +33 -0
- package/dist/esm/readChangelogSections.js +80 -0
- package/dist/esm/releaseFiles.d.ts +5 -7
- package/dist/esm/releasePlan.d.ts +11 -13
- package/dist/esm/releasePrepare.d.ts +23 -22
- package/dist/esm/releasePrepare.js +31 -11
- package/dist/esm/releasePrepareMono.d.ts +9 -7
- package/dist/esm/releasePrepareMono.js +85 -33
- package/dist/esm/releasePrepareProject.d.ts +19 -29
- package/dist/esm/releasePrepareProject.js +31 -12
- package/dist/esm/renderChangelogMarkdown.d.ts +10 -4
- package/dist/esm/renderChangelogMarkdown.js +27 -2
- package/dist/esm/renderReleaseNotes.d.ts +3 -11
- package/dist/esm/renderReleaseNotes.js +2 -6
- package/dist/esm/reportPrepare.d.ts +4 -5
- package/dist/esm/reportPrepare.js +33 -19
- package/dist/esm/resolveCommandTags.d.ts +15 -11
- package/dist/esm/resolveCommandTags.js +35 -5
- package/dist/esm/resolveConfigFlag.d.ts +7 -0
- package/dist/esm/resolveConfigFlag.js +4 -0
- package/dist/esm/resolveReleaseTags.d.ts +6 -8
- package/dist/esm/resolveReleaseTags.js +1 -1
- package/dist/esm/resolveStylesOrExit.d.ts +2 -2
- package/dist/esm/showTagPrefixesCommand.d.ts +7 -10
- package/dist/esm/showTagPrefixesCommand.js +4 -4
- package/dist/esm/stripEmojiPrefix.d.ts +1 -0
- package/dist/esm/stripScope.d.ts +2 -2
- package/dist/esm/stripScope.js +3 -3
- package/dist/esm/sync-labels/generateCommand.d.ts +11 -10
- package/dist/esm/sync-labels/generateCommand.js +11 -8
- package/dist/esm/sync-labels/initCommand.d.ts +6 -7
- package/dist/esm/sync-labels/initCommand.js +2 -2
- package/dist/esm/sync-labels/presets.d.ts +5 -4
- package/dist/esm/sync-labels/presets.js +9 -9
- package/dist/esm/sync-labels/resolveLabels.d.ts +7 -7
- package/dist/esm/sync-labels/resolveLabels.js +1 -1
- package/dist/esm/sync-labels/retiredConfig.d.ts +4 -5
- package/dist/esm/sync-labels/syncCommand.d.ts +1 -4
- package/dist/esm/sync-labels/templates.d.ts +3 -3
- package/dist/esm/sync-labels/templates.js +3 -3
- package/dist/esm/sync-labels/typeLabels.d.ts +14 -0
- package/dist/esm/sync-labels/typeLabels.js +38 -0
- package/dist/esm/sync-labels/types.d.ts +1 -1
- package/dist/esm/tagCommand.d.ts +1 -1
- package/dist/esm/typeGuards.d.ts +2 -2
- package/dist/esm/types.d.ts +116 -91
- package/dist/esm/types.js +1 -1
- package/dist/esm/validateConfig.d.ts +2 -11
- package/dist/esm/validateConfig.js +2 -2
- package/dist/esm/validateOnlyExcludesStrandedDependents.d.ts +14 -12
- package/dist/esm/validateOverridesCommand.d.ts +17 -20
- package/dist/esm/validateOverridesCommand.js +1 -1
- package/docs/api.md +6 -6
- package/docs/changelogs.md +63 -40
- package/docs/configuration.md +29 -27
- package/docs/editorial-overrides.md +23 -23
- package/docs/labels.md +21 -19
- package/docs/project-releases.md +13 -13
- package/docs/publishing.md +5 -5
- package/docs/readiness-checks.md +3 -3
- package/docs/releasing.md +50 -25
- package/docs/work-types.md +41 -57
- package/package.json +7 -6
- package/presets/labels/common.yaml +1 -41
- package/dist/esm/resolveReleaseNotesConfig.d.ts +0 -26
- package/dist/esm/resolveReleaseNotesConfig.js +0 -29
- package/dist/esm/workTypesData.d.ts +0 -50
- package/dist/esm/workTypesData.js +0 -145
- package/schemas/label-map.json +0 -24
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type RawCommit } from './enumerateReleaseWindows.js';
|
|
2
2
|
import type { GenerateChangelogOptions } from './generateChangelogs.js';
|
|
3
|
-
import type { ChangelogEntry, ChangelogSection, MalformedChangeRecordBlock, PolicyViolation, ReleaseConfig, ReleaseType, UndeclaredEntryType } from './types.js';
|
|
3
|
+
import type { ChangelogEntry, ChangelogSection, MalformedChangeRecordBlock, PolicyViolation, ReleaseConfig, ReleaseType, UndeclaredEntryType, UnroutedEntryScope } from './types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Strips a section title down to its bare name.
|
|
6
6
|
*
|
|
7
|
-
* A default title
|
|
7
|
+
* A default title has a leading emoji (e.g. `"🐛 Bug fixes"`), while a consumer's
|
|
8
8
|
* `devOnlySections` or `workTypes` override may be written as a bare name. Comparing both sides
|
|
9
9
|
* through this helper lets the two forms match.
|
|
10
10
|
*/
|
|
@@ -12,8 +12,7 @@ export declare function stripGroupDecorations(group: string): string;
|
|
|
12
12
|
/**
|
|
13
13
|
* Builds structured changelog entries from the release windows of git history, naming the unreleased window `tag`.
|
|
14
14
|
*
|
|
15
|
-
* Composes `readReleaseHistory` and `toChangelogEntries` for a caller that knows the tag before it reads.
|
|
16
|
-
* `changelog.json` I/O; callers persist the entries via `renderChangelogJson`.
|
|
15
|
+
* Composes `readReleaseHistory` and `toChangelogEntries` for a caller that knows the tag before it reads.
|
|
17
16
|
*/
|
|
18
17
|
export declare function buildChangelogEntries(config: ReleaseHistoryConfig, tag: string, options: GenerateChangelogOptions): {
|
|
19
18
|
entries: ChangelogEntry[];
|
|
@@ -25,30 +24,35 @@ export interface ChangelogDiagnostics {
|
|
|
25
24
|
/** Breaking-policy violations of the window's titles and change-record entries. */
|
|
26
25
|
policyViolations: PolicyViolation[];
|
|
27
26
|
undeclaredEntryTypes: UndeclaredEntryType[];
|
|
27
|
+
/**
|
|
28
|
+
* Entry scopes that don't route to any workspace. A read leaves it empty: Only a pass over every workspace can fill
|
|
29
|
+
* it.
|
|
30
|
+
*/
|
|
31
|
+
unroutedEntryScopes: UnroutedEntryScope[];
|
|
28
32
|
}
|
|
29
33
|
/**
|
|
30
34
|
* Reads a scope's release windows once and returns the changelog items of every window, with what the unreleased
|
|
31
35
|
* window decides: its commits, its bump, and its diagnostics.
|
|
32
36
|
*
|
|
33
|
-
* A commit whose last `change-record` block records entries yields one item per entry
|
|
34
|
-
* classified by its title through `classifyChangelogCommit`. A `release:`
|
|
35
|
-
* way.
|
|
36
|
-
* prepared.
|
|
37
|
+
* A commit whose last `change-record` block records entries yields one item per entry routed to
|
|
38
|
+
* `options.workspaceDir`; any other commit is classified by its title through `classifyChangelogCommit`. A `release:`
|
|
39
|
+
* or merge subject yields nothing either way. The read records diagnostics only for the unreleased window, since the
|
|
40
|
+
* released windows were reported when they were prepared.
|
|
37
41
|
*/
|
|
38
42
|
export declare function readReleaseHistory(config: ReleaseHistoryConfig, options: GenerateChangelogOptions): ReleaseHistory;
|
|
39
43
|
/** The configuration that `readReleaseHistory` reads. */
|
|
40
|
-
export type ReleaseHistoryConfig = Pick<ReleaseConfig, 'breakingPolicies' | 'changelogJson' | 'versionPatterns' | 'workTypes'>;
|
|
44
|
+
export type ReleaseHistoryConfig = Pick<ReleaseConfig, 'breakingPolicies' | 'changelogJson' | 'scopeAliases' | 'versionPatterns' | 'workTypes'>;
|
|
41
45
|
/** One read of a scope's release windows. */
|
|
42
46
|
export interface ReleaseHistory {
|
|
43
47
|
/** The newest matching tag that HEAD reaches; undefined when none does. */
|
|
44
48
|
previousTag: string | undefined;
|
|
45
|
-
/** Entries of the released windows, newest first; a window that
|
|
49
|
+
/** Entries of the released windows, newest first; a window that doesn't yield any item contributes none. */
|
|
46
50
|
releasedEntries: ChangelogEntry[];
|
|
47
51
|
unreleased: UnreleasedWindowReading;
|
|
48
52
|
}
|
|
49
53
|
/** The unreleased window: its changelog sections and commits, and the bump and diagnostics that they determine. */
|
|
50
54
|
export interface UnreleasedWindowReading {
|
|
51
|
-
/** The highest bump that the window's items call for; undefined when the window
|
|
55
|
+
/** The highest bump that the window's items call for; undefined when the window doesn't yield any item. */
|
|
52
56
|
bump: ReleaseType | undefined;
|
|
53
57
|
/** The window's commits, newest first, without release commits. */
|
|
54
58
|
commits: RawCommit[];
|
|
@@ -59,10 +63,16 @@ export interface UnreleasedWindowReading {
|
|
|
59
63
|
parsedCommitCount: number;
|
|
60
64
|
sections: ChangelogSection[];
|
|
61
65
|
/**
|
|
62
|
-
* Commits that yield
|
|
63
|
-
* when none.
|
|
66
|
+
* Commits that don't yield any item and that neither an exclusion nor a diagnostic accounts for, newest first;
|
|
67
|
+
* undefined when none.
|
|
64
68
|
*/
|
|
65
69
|
unparseableCommits: RawCommit[] | undefined;
|
|
66
70
|
}
|
|
67
71
|
/** Labels the unreleased window of `history` with `tag` and returns the entries of every window, newest first. */
|
|
68
72
|
export declare function toChangelogEntries(history: ReleaseHistory, tag: string): ChangelogEntry[];
|
|
73
|
+
/**
|
|
74
|
+
* Returns the entries that a direct release tagged `tag` records: those of `toChangelogEntries`, or, when the
|
|
75
|
+
* unreleased window doesn't yield any item, the synthetic "Forced version bump." entry dated `today` ahead of the
|
|
76
|
+
* released entries.
|
|
77
|
+
*/
|
|
78
|
+
export declare function toReleaseEntries(history: ReleaseHistory, tag: string, today: string): ChangelogEntry[];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { chainError } from '@williamthorsen/toolbelt.errors/candidate';
|
|
2
|
+
import { buildEmptyReleaseEntry } from "./buildEmptyReleaseEntry.js";
|
|
2
3
|
import { extractVersion } from "./changelogJsonUtils.js";
|
|
3
4
|
import { classifyChangelogCommit, isNonChangeSubject, isReleaseSubject } from "./classifyChangelogCommit.js";
|
|
4
5
|
import { DEFAULT_BREAKING_POLICIES, DEFAULT_VERSION_PATTERNS, DEFAULT_WORK_TYPES } from "./defaults.js";
|
|
@@ -6,7 +7,7 @@ import { determineBumpType } from "./determineBumpType.js";
|
|
|
6
7
|
import { enumerateReleaseWindows } from "./enumerateReleaseWindows.js";
|
|
7
8
|
import { extractMigration } from "./extractMigration.js";
|
|
8
9
|
import { parseChangeRecordBlock, stripChangeRecordBlocks } from "./parseChangeRecordBlock.js";
|
|
9
|
-
import {
|
|
10
|
+
import { evaluateBreakingPolicy, parseSubject, resolveType } from "./parseCommitMessage.js";
|
|
10
11
|
import { stripEmojiPrefix } from "./stripEmojiPrefix.js";
|
|
11
12
|
const UNRELEASED_TAG = 'unreleased';
|
|
12
13
|
const CANONICAL_SECTION_ORDER = new Map(Object.values(DEFAULT_WORK_TYPES).map((config, index) => [stripGroupDecorations(config.header), index]));
|
|
@@ -31,6 +32,9 @@ export function readReleaseHistory(config, options) {
|
|
|
31
32
|
const context = {
|
|
32
33
|
breakingPolicies: config.breakingPolicies ?? DEFAULT_BREAKING_POLICIES,
|
|
33
34
|
devOnlySections: new Set(config.changelogJson.devOnlySections.map(stripGroupDecorations)),
|
|
35
|
+
...(options.workspaceDir !== undefined && {
|
|
36
|
+
routing: { workspaceDir: options.workspaceDir, scopeAliases: config.scopeAliases ?? {} },
|
|
37
|
+
}),
|
|
34
38
|
versionPatterns: config.versionPatterns ?? DEFAULT_VERSION_PATTERNS,
|
|
35
39
|
workTypes: config.workTypes ?? DEFAULT_WORK_TYPES,
|
|
36
40
|
};
|
|
@@ -50,9 +54,20 @@ export function toChangelogEntries(history, tag) {
|
|
|
50
54
|
...history.releasedEntries,
|
|
51
55
|
];
|
|
52
56
|
}
|
|
57
|
+
export function toReleaseEntries(history, tag, today) {
|
|
58
|
+
if (history.unreleased.sections.length === 0) {
|
|
59
|
+
return [buildEmptyReleaseEntry(extractVersion(tag), today), ...history.releasedEntries];
|
|
60
|
+
}
|
|
61
|
+
return toChangelogEntries(history, tag);
|
|
62
|
+
}
|
|
53
63
|
function transformReleases(windows, context) {
|
|
54
64
|
const [unreleasedWindow, baselineWindow] = windows;
|
|
55
|
-
const diagnostics = {
|
|
65
|
+
const diagnostics = {
|
|
66
|
+
malformedBlocks: [],
|
|
67
|
+
policyViolations: [],
|
|
68
|
+
undeclaredEntryTypes: [],
|
|
69
|
+
unroutedEntryScopes: [],
|
|
70
|
+
};
|
|
56
71
|
const signals = [];
|
|
57
72
|
const unparseable = [];
|
|
58
73
|
let parsedCommitCount = 0;
|
|
@@ -130,7 +145,7 @@ function readCommit(commit, context, diagnostics) {
|
|
|
130
145
|
if (classification.kind !== 'header') {
|
|
131
146
|
return { items: [], isUnparseable: classification.kind === 'unparseable' && reading.kind !== 'malformed' };
|
|
132
147
|
}
|
|
133
|
-
const item = buildTitleItem(commit, classification.breaking);
|
|
148
|
+
const item = buildTitleItem(commit, classification.breaking, context.workTypes);
|
|
134
149
|
return {
|
|
135
150
|
items: [
|
|
136
151
|
{ header: classification.header, item, signal: { type: classification.type, breaking: item.breaking === true } },
|
|
@@ -149,6 +164,15 @@ function buildSections(sectionMap, devOnlySections) {
|
|
|
149
164
|
}
|
|
150
165
|
return sections.toSorted((a, b) => canonicalSectionPriority(a.title) - canonicalSectionPriority(b.title));
|
|
151
166
|
}
|
|
167
|
+
function isRoutedTo(scopes, routing) {
|
|
168
|
+
if (scopes.length === 0) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
return scopes.some((scope) => {
|
|
172
|
+
const resolved = routing.scopeAliases[scope] ?? scope;
|
|
173
|
+
return resolved === '*' || resolved === routing.workspaceDir;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
152
176
|
function formatDate(timestamp) {
|
|
153
177
|
return new Date(timestamp * 1_000).toISOString().slice(0, 10);
|
|
154
178
|
}
|
|
@@ -161,7 +185,10 @@ function appendItem(sectionMap, header, item) {
|
|
|
161
185
|
items.push(item);
|
|
162
186
|
}
|
|
163
187
|
function buildEntryItem(commit, entry, position, prNumber, context, diagnostics) {
|
|
164
|
-
const { breakingPolicies, workTypes } = context;
|
|
188
|
+
const { breakingPolicies, routing, workTypes } = context;
|
|
189
|
+
if (routing !== undefined && !isRoutedTo(entry.scopes, routing)) {
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
165
192
|
const type = resolveType(entry.type, workTypes);
|
|
166
193
|
if (type === undefined) {
|
|
167
194
|
diagnostics?.undeclaredEntryTypes.push({
|
|
@@ -208,13 +235,13 @@ function buildEntryItem(commit, entry, position, prNumber, context, diagnostics)
|
|
|
208
235
|
item.entry = position;
|
|
209
236
|
return { header: config.header, item, signal: { type, breaking } };
|
|
210
237
|
}
|
|
211
|
-
function buildTitleItem(commit, isParsedBreaking) {
|
|
238
|
+
function buildTitleItem(commit, isParsedBreaking, workTypes) {
|
|
212
239
|
const body = extractBody(stripChangeRecordBlocks(commit.message));
|
|
213
240
|
const item = { description: extractDescription(commit.message) };
|
|
214
241
|
if (body !== undefined) {
|
|
215
242
|
item.body = body;
|
|
216
243
|
}
|
|
217
|
-
if (isParsedBreaking && subjectHasBreakingMarker(commit.message)) {
|
|
244
|
+
if (isParsedBreaking && subjectHasBreakingMarker(commit.message, workTypes)) {
|
|
218
245
|
item.breaking = true;
|
|
219
246
|
}
|
|
220
247
|
const migration = extractMigration(body);
|
|
@@ -224,21 +251,13 @@ function buildTitleItem(commit, isParsedBreaking) {
|
|
|
224
251
|
item.hash = commit.hash;
|
|
225
252
|
return item;
|
|
226
253
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
let subject = message.split('\n', 1)[0] ?? '';
|
|
230
|
-
for (const pattern of COMMIT_PREPROCESSOR_PATTERNS) {
|
|
231
|
-
subject = subject.replace(pattern, '');
|
|
232
|
-
}
|
|
233
|
-
return SUBJECT_BREAKING_MARKER_PATTERN.test(subject);
|
|
254
|
+
function subjectHasBreakingMarker(message, workTypes) {
|
|
255
|
+
return parseSubject(message.split('\n', 1)[0] ?? '', workTypes)?.breaking === true;
|
|
234
256
|
}
|
|
235
257
|
function extractDescription(message) {
|
|
236
258
|
const firstLine = message.split('\n', 1)[0] ?? message;
|
|
237
259
|
const afterColon = firstLine.split(': ').slice(1).join(': ');
|
|
238
|
-
|
|
239
|
-
return afterColon.charAt(0).toUpperCase() + afterColon.slice(1);
|
|
240
|
-
}
|
|
241
|
-
return firstLine;
|
|
260
|
+
return afterColon.charAt(0).toUpperCase() + afterColon.slice(1);
|
|
242
261
|
}
|
|
243
262
|
const TRAILER_PATTERNS = [
|
|
244
263
|
/^Change:/i,
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type { WorkspaceConfig } from './types.js';
|
|
2
2
|
/** Identities, current versions, and `workspace:` dependency edges of the workspaces' packages. */
|
|
3
3
|
export interface DependencyGraph {
|
|
4
|
-
/**
|
|
4
|
+
/** Maps a package name to its workspace `dir`. */
|
|
5
5
|
packageNameToDir: Map<string, string>;
|
|
6
|
-
/**
|
|
6
|
+
/** Maps a workspace `dir` to its package name (inverse of `packageNameToDir`). */
|
|
7
7
|
dirToPackageName: Map<string, string>;
|
|
8
|
-
/**
|
|
8
|
+
/** Maps a workspace `dir` to its current version; absent when its `package.json` doesn't have a string `version`. */
|
|
9
9
|
dirToVersion: Map<string, string>;
|
|
10
|
-
/**
|
|
10
|
+
/** Maps a package name to the workspaces that depend on it. */
|
|
11
11
|
dependentsOf: Map<string, WorkspaceConfig[]>;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* Maps a workspace `dir` to the `workspace:`-protocol package names that it declares in `dependencies` or
|
|
14
|
+
* `peerDependencies` (the forward counterpart of `dependentsOf`).
|
|
15
15
|
*/
|
|
16
16
|
dependenciesOf: Map<string, Set<string>>;
|
|
17
17
|
}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
1
|
import type { ChangelogEntry } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Build a synthetic changelog entry for a forced empty-range release.
|
|
4
|
-
*
|
|
5
|
-
* Produces a single `ChangelogEntry` with one `'Notes'` section (audience `'dev'`)
|
|
6
|
-
* containing a single `'Forced version bump.'` item. Used when `release-kit prepare`
|
|
7
|
-
* proceeds via `--force`, `--bump=X`, or `--set-version` against a unit with zero
|
|
8
|
-
* qualifying commits since its last tag. Pure function: no I/O.
|
|
9
|
-
*/
|
|
2
|
+
/** Builds the changelog entry of a forced release whose unreleased window doesn't yield any changelog item. */
|
|
10
3
|
export declare function buildEmptyReleaseEntry(version: string, date: string): ChangelogEntry;
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import type { PrepareResult } from './types.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Each released workspace with commits gets a section headed by its tag,
|
|
6
|
-
* followed by scope-stripped commit messages as bullet points. Sections
|
|
7
|
-
* are separated by blank lines. The project release (when present) is
|
|
8
|
-
* appended as a final section using the same format. Returns an empty
|
|
9
|
-
* string when no released workspaces have commits and there is no project
|
|
10
|
-
* release.
|
|
3
|
+
* Builds a release commit body from a prepare result: one section per released workspace or project that has commits,
|
|
4
|
+
* the project last, each headed by its tag and listing its scope-stripped commit subjects.
|
|
11
5
|
*/
|
|
12
6
|
export declare function buildReleaseSummary(result: Pick<PrepareResult, 'project' | 'workspaces'>): string;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import type { ChangelogEntry } from './types.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Produces a single `ChangelogEntry` with one `'Dependency updates'` section (audience `'dev'`)
|
|
6
|
-
* containing one item per propagated-from dependency. Pure function: no I/O.
|
|
3
|
+
* Builds the changelog entry of a propagation-only bump, with one item per dependency whose bump propagated, under
|
|
4
|
+
* `sectionTitle`, the resolved `deps` work type's header.
|
|
7
5
|
*/
|
|
8
6
|
export declare function buildSyntheticChangelogEntry(propagatedFrom: ReadonlyArray<{
|
|
9
7
|
packageName: string;
|
|
10
8
|
newVersion: string;
|
|
11
|
-
}>, version: string, date: string): ChangelogEntry;
|
|
9
|
+
}>, version: string, date: string, sectionTitle: string): ChangelogEntry;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export function buildSyntheticChangelogEntry(propagatedFrom, version, date) {
|
|
1
|
+
export function buildSyntheticChangelogEntry(propagatedFrom, version, date, sectionTitle) {
|
|
2
2
|
const items = propagatedFrom.map((dep) => ({
|
|
3
3
|
description: `Bumped \`${dep.packageName}\` to ${dep.newVersion}`,
|
|
4
4
|
}));
|
|
5
5
|
return {
|
|
6
6
|
version,
|
|
7
7
|
date,
|
|
8
|
-
sections: [{ title:
|
|
8
|
+
sections: [{ title: sectionTitle, audience: 'dev', items }],
|
|
9
9
|
};
|
|
10
10
|
}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
1
|
import type { ReleaseType } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Bumps a semver version string by the given release type.
|
|
4
|
-
*
|
|
5
|
-
* @param version - A semver version string (e.g., '1.2.3').
|
|
6
|
-
* @param releaseType - The type of release bump to apply.
|
|
7
|
-
* @returns The bumped version string.
|
|
8
|
-
* @throws If the version string is not a valid semver format.
|
|
9
|
-
*/
|
|
2
|
+
/** Bumps a `major.minor.patch` version by the release type; throws on a version of any other form. */
|
|
10
3
|
export declare function bumpVersion(version: string, releaseType: ReleaseType): string;
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import type { ChangelogEntry, ReleaseConfig } from './types.js';
|
|
2
|
-
/**
|
|
2
|
+
/** Resolves the path of the `changelog.json` file under a workspace's changelog directory. */
|
|
3
3
|
export declare function resolveChangelogJsonPath(config: Pick<ReleaseConfig, 'changelogJson'>, changelogPath: string): string;
|
|
4
4
|
/** Renders changelog entries as a `changelog.json` file's complete content, sorted newest-first. */
|
|
5
5
|
export declare function renderChangelogJson(entries: ChangelogEntry[]): string;
|
|
6
6
|
/**
|
|
7
|
-
* Merges `entries` with the on-disk entries at `filePath` and returns the merged set in
|
|
8
|
-
*
|
|
7
|
+
* Merges `entries` with the on-disk entries at `filePath` and returns the merged set in newest-first order, without
|
|
8
|
+
* writing.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* missing or malformed file as an empty existing set, so a malformed file does not abort the
|
|
13
|
-
* release.
|
|
10
|
+
* Keeps an on-disk entry that `entries` lacks, which preserves synthetic entries across propagation runs. A missing or
|
|
11
|
+
* malformed file counts as empty, so that a malformed file does not abort the release.
|
|
14
12
|
*/
|
|
15
13
|
export declare function mergeChangelogEntriesWithDisk(filePath: string, entries: ChangelogEntry[]): ChangelogEntry[];
|
|
@@ -2,8 +2,8 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
4
4
|
import stringify from 'json-stringify-pretty-compact';
|
|
5
|
-
import semver from 'semver';
|
|
6
5
|
import { isChangelogEntry } from "./changelogJsonUtils.js";
|
|
6
|
+
import { compareVersionsDescending } from "./compareVersions.js";
|
|
7
7
|
import { isUnknownArray } from "./typeGuards.js";
|
|
8
8
|
export function resolveChangelogJsonPath(config, changelogPath) {
|
|
9
9
|
return join(changelogPath, config.changelogJson.outputPath);
|
|
@@ -16,7 +16,7 @@ export function mergeChangelogEntriesWithDisk(filePath, entries) {
|
|
|
16
16
|
return mergeEntries(entries, existing);
|
|
17
17
|
}
|
|
18
18
|
function sortNewestFirst(entries) {
|
|
19
|
-
return [...entries].
|
|
19
|
+
return [...entries].toSorted((a, b) => compareVersionsDescending(a.version, b.version));
|
|
20
20
|
}
|
|
21
21
|
function readExistingEntries(filePath) {
|
|
22
22
|
if (!existsSync(filePath)) {
|
|
@@ -45,18 +45,3 @@ function mergeEntries(newEntries, existingEntries) {
|
|
|
45
45
|
}
|
|
46
46
|
return sortNewestFirst(versionMap.values());
|
|
47
47
|
}
|
|
48
|
-
function compareVersionsDescending(a, b) {
|
|
49
|
-
const aValid = semver.valid(a);
|
|
50
|
-
const bValid = semver.valid(b);
|
|
51
|
-
if (aValid && bValid)
|
|
52
|
-
return semver.rcompare(aValid, bValid);
|
|
53
|
-
if (aValid)
|
|
54
|
-
return -1;
|
|
55
|
-
if (bValid)
|
|
56
|
-
return 1;
|
|
57
|
-
if (a > b)
|
|
58
|
-
return -1;
|
|
59
|
-
if (a < b)
|
|
60
|
-
return 1;
|
|
61
|
-
return 0;
|
|
62
|
-
}
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import type { ChangelogEntry } from './types.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Reports whether a value parsed from JSON is a `ChangelogEntry`.
|
|
4
4
|
*
|
|
5
|
-
* Checks the entry's top level only: `sections`
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Checks the entry's top level only: `sections` must be an array, and its contents pass through unvalidated.
|
|
6
|
+
* `.meta/changelog.json` is written by release-kit and read tolerantly; strict validation applies to the
|
|
7
|
+
* human-authored `.meta/changelog-overrides.json`, in `changelogOverrides.ts`.
|
|
8
8
|
*/
|
|
9
9
|
export declare function isChangelogEntry(value: unknown): value is ChangelogEntry;
|
|
10
|
-
/**
|
|
10
|
+
/** Extracts the version from a tag: the text from its first `N.N.N` onward, or the whole tag when it contains none. */
|
|
11
11
|
export declare function extractVersion(tag: string): string;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* Returns `undefined` if the file cannot be read or does not contain a valid array.
|
|
16
|
-
* Silent on parse error — for the warn-and-treat-as-empty variant used by upsert callers,
|
|
17
|
-
* see `readExistingEntries` in `./changelogJsonFile.ts`.
|
|
13
|
+
* Reads the changelog entries in a JSON file; undefined when the file is missing or unreadable, or doesn't contain an
|
|
14
|
+
* array.
|
|
18
15
|
*/
|
|
19
16
|
export declare function readChangelogEntries(filePath: string): ChangelogEntry[] | undefined;
|