@williamthorsen/release-kit 5.2.1 → 5.3.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.
- package/CHANGELOG.md +76 -26
- package/README.md +223 -31
- package/cliff.toml.template +4 -39
- package/dist/esm/.cache +1 -1
- package/dist/esm/bin/release-kit.js +59 -0
- package/dist/esm/buildChangelogEntries.js +6 -0
- package/dist/esm/buildEmptyReleaseEntry.d.ts +2 -0
- package/dist/esm/buildEmptyReleaseEntry.js +16 -0
- package/dist/esm/changelogJsonFile.d.ts +2 -0
- package/dist/esm/changelogJsonFile.js +11 -1
- package/dist/esm/changelogJsonUtils.d.ts +2 -1
- package/dist/esm/changelogJsonUtils.js +9 -0
- package/dist/esm/changelogOverrides.d.ts +53 -0
- package/dist/esm/changelogOverrides.js +424 -0
- package/dist/esm/checkWorkTypesDrift.js +3 -2
- package/dist/esm/defaults.js +1 -1
- package/dist/esm/generateChangelogs.d.ts +2 -3
- package/dist/esm/generateChangelogs.js +4 -34
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/loadConfig.d.ts +1 -1
- package/dist/esm/releasePrepare.js +68 -11
- package/dist/esm/releasePrepareMono.js +103 -59
- package/dist/esm/releasePrepareProject.d.ts +4 -1
- package/dist/esm/releasePrepareProject.js +74 -18
- package/dist/esm/renderChangelogMarkdown.d.ts +12 -0
- package/dist/esm/renderChangelogMarkdown.js +32 -0
- package/dist/esm/renderReleaseNotes.js +6 -1
- package/dist/esm/resolveReleaseNotesConfig.js +3 -1
- package/dist/esm/runGitCliff.d.ts +1 -0
- package/dist/esm/runGitCliff.js +7 -0
- package/dist/esm/syncWorkTypes.js +3 -2
- package/dist/esm/types.d.ts +98 -31
- package/dist/esm/types.js +60 -0
- package/dist/esm/validateConfig.js +84 -345
- package/dist/esm/validateOverridesCommand.d.ts +14 -0
- package/dist/esm/validateOverridesCommand.js +136 -0
- package/dist/esm/work-types.json +23 -17
- package/dist/esm/work-types.schema.json +28 -1
- package/dist/esm/workTypesData.d.ts +8 -0
- package/dist/esm/workTypesData.js +20 -17
- package/dist/esm/workTypesUtils.d.ts +1 -0
- package/dist/esm/workTypesUtils.js +8 -0
- package/package.json +5 -4
- package/dist/esm/writeSyntheticChangelog.d.ts +0 -9
- package/dist/esm/writeSyntheticChangelog.js +0 -27
package/cliff.toml.template
CHANGED
|
@@ -18,45 +18,10 @@
|
|
|
18
18
|
# unique group (not per parser entry) — all parsers routing to the same group
|
|
19
19
|
# share the same prefix.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
All notable changes to this project will be documented in this file."""
|
|
26
|
-
# Render each commit as a bullet with the description (stripped of ticket ID
|
|
27
|
-
# and scope|type prefix). If the commit has a body, render it as indented
|
|
28
|
-
# continuation paragraphs under the bullet.
|
|
29
|
-
body = """{%- if version %}
|
|
30
|
-
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
|
|
31
|
-
{%- else %}
|
|
32
|
-
## [unreleased]
|
|
33
|
-
{%- endif -%}
|
|
34
|
-
{%- set non_merge = commits | filter(attribute="merge_commit", value=false) -%}
|
|
35
|
-
{%- for group, group_commits in non_merge | group_by(attribute="group") %}
|
|
36
|
-
|
|
37
|
-
### {{ group | striptags | trim | upper_first }}
|
|
38
|
-
|
|
39
|
-
{% for commit in group_commits -%}
|
|
40
|
-
{%- set subject = commit.message | split(pat="\n") | first -%}
|
|
41
|
-
{%- set desc = subject | split(pat=": ") | slice(start=1) | join(sep=": ") -%}
|
|
42
|
-
{%- set body_lines = commit.message | split(pat="\n") | slice(start=2) -%}
|
|
43
|
-
{%- set body_text = body_lines | join(sep="\n") | trim -%}
|
|
44
|
-
{%- if not loop.first %}
|
|
45
|
-
|
|
46
|
-
{% endif -%}
|
|
47
|
-
- {{ desc | upper_first }}
|
|
48
|
-
{%- if body_text %}
|
|
49
|
-
|
|
50
|
-
{{ body_text | split(pat="\n") | join(sep="\n ") }}
|
|
51
|
-
{%- endif -%}
|
|
52
|
-
{%- endfor -%}
|
|
53
|
-
{%- endfor %}
|
|
54
|
-
"""
|
|
55
|
-
footer = """
|
|
56
|
-
|
|
57
|
-
<!-- generated by git-cliff -->
|
|
58
|
-
"""
|
|
59
|
-
trim = false
|
|
21
|
+
# Markdown rendering is handled in-process by `renderChangelogMarkdown.ts`. cliff is invoked
|
|
22
|
+
# only for `--context` JSON output (see `buildChangelogEntries.ts`), so no `[changelog]` block
|
|
23
|
+
# is needed. The `[git].commit_parsers` section below remains load-bearing for group
|
|
24
|
+
# assignment in the `--context` payload.
|
|
60
25
|
|
|
61
26
|
[git]
|
|
62
27
|
conventional_commits = false
|
package/dist/esm/.cache
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
376cb01707ee2fb8afe186dfa7baa15e2a0c982201fae4c30632cf598d87d09c
|
|
@@ -13,6 +13,7 @@ import { syncLabelsInitCommand } from "../sync-labels/initCommand.js";
|
|
|
13
13
|
import { syncLabelsCommand } from "../sync-labels/syncCommand.js";
|
|
14
14
|
import { syncWorkTypes } from "../syncWorkTypes.js";
|
|
15
15
|
import { tagCommand } from "../tagCommand.js";
|
|
16
|
+
import { validateOverridesCommand } from "../validateOverridesCommand.js";
|
|
16
17
|
const VERSION = readPackageVersion(import.meta.url);
|
|
17
18
|
function showUsage() {
|
|
18
19
|
console.info(`
|
|
@@ -27,6 +28,7 @@ Commands:
|
|
|
27
28
|
create-github-release Create GitHub Releases from changelog.json for tags on HEAD
|
|
28
29
|
show-tag-prefixes Show derived and declared legacy tag prefixes per workspace
|
|
29
30
|
init Initialize release-kit in the current repository
|
|
31
|
+
overrides Manage editorial changelog overrides
|
|
30
32
|
sync-labels Manage GitHub label synchronization
|
|
31
33
|
work-types Check for or sync work-type taxonomy drift against the upstream canonical
|
|
32
34
|
|
|
@@ -174,6 +176,35 @@ legacy tag prefixes. Surfaces any release-shaped tags whose prefix is neither a
|
|
|
174
176
|
derived prefix nor declared in \`legacyIdentities\`, with a copy-pasteable
|
|
175
177
|
config snippet.
|
|
176
178
|
|
|
179
|
+
Options:
|
|
180
|
+
--help, -h Show this help message
|
|
181
|
+
`);
|
|
182
|
+
}
|
|
183
|
+
function showOverridesHelp() {
|
|
184
|
+
console.info(`
|
|
185
|
+
Usage: release-kit overrides <subcommand> [options]
|
|
186
|
+
|
|
187
|
+
Manage editorial changelog overrides.
|
|
188
|
+
|
|
189
|
+
Subcommands:
|
|
190
|
+
validate Validate every \`.meta/changelog-overrides.json\` file across all scopes
|
|
191
|
+
|
|
192
|
+
Options:
|
|
193
|
+
--help, -h Show this help message
|
|
194
|
+
`);
|
|
195
|
+
}
|
|
196
|
+
function showOverridesValidateHelp() {
|
|
197
|
+
console.info(`
|
|
198
|
+
Usage: release-kit overrides validate
|
|
199
|
+
|
|
200
|
+
Validate every \`.meta/changelog-overrides.json\` file across the project and per-workspace
|
|
201
|
+
scopes. Reports schema/parse errors, ambiguous-prefix errors, and stale-key warnings.
|
|
202
|
+
|
|
203
|
+
Exit codes:
|
|
204
|
+
0 Clean \u2014 no errors, no stale keys
|
|
205
|
+
1 Stale-key warnings only (no errors)
|
|
206
|
+
2 Schema/parse or ambiguous-prefix errors (errors dominate)
|
|
207
|
+
|
|
177
208
|
Options:
|
|
178
209
|
--help, -h Show this help message
|
|
179
210
|
`);
|
|
@@ -389,6 +420,34 @@ if (command === "sync-labels") {
|
|
|
389
420
|
showSyncLabelsHelp();
|
|
390
421
|
process.exit(1);
|
|
391
422
|
}
|
|
423
|
+
if (command === "overrides") {
|
|
424
|
+
const subcommand = flags[0];
|
|
425
|
+
const subflags = flags.slice(1);
|
|
426
|
+
if (subcommand === "--help" || subcommand === "-h" || subcommand === void 0) {
|
|
427
|
+
showOverridesHelp();
|
|
428
|
+
process.exit(0);
|
|
429
|
+
}
|
|
430
|
+
if (subcommand === "validate") {
|
|
431
|
+
if (subflags.some((f) => f === "--help" || f === "-h")) {
|
|
432
|
+
showOverridesValidateHelp();
|
|
433
|
+
process.exit(0);
|
|
434
|
+
}
|
|
435
|
+
if (subflags.length > 0) {
|
|
436
|
+
console.error(`Error: Unknown option: ${subflags[0]}`);
|
|
437
|
+
process.exit(1);
|
|
438
|
+
}
|
|
439
|
+
const result = await validateOverridesCommand();
|
|
440
|
+
if (result.exitCode === 0) {
|
|
441
|
+
console.info(result.message);
|
|
442
|
+
} else {
|
|
443
|
+
console.error(result.message);
|
|
444
|
+
}
|
|
445
|
+
process.exit(result.exitCode);
|
|
446
|
+
}
|
|
447
|
+
console.error(`Error: Unknown subcommand: ${subcommand}`);
|
|
448
|
+
showOverridesHelp();
|
|
449
|
+
process.exit(1);
|
|
450
|
+
}
|
|
392
451
|
if (command === "work-types") {
|
|
393
452
|
const subcommand = flags[0];
|
|
394
453
|
const subflags = flags.slice(1);
|
|
@@ -69,6 +69,9 @@ function toCliffContextCommit(value) {
|
|
|
69
69
|
if (typeof value.group === "string") {
|
|
70
70
|
commit.group = value.group;
|
|
71
71
|
}
|
|
72
|
+
if (typeof value.id === "string") {
|
|
73
|
+
commit.id = value.id;
|
|
74
|
+
}
|
|
72
75
|
return commit;
|
|
73
76
|
}
|
|
74
77
|
function transformReleases(releases, devOnlySections) {
|
|
@@ -98,6 +101,9 @@ function transformReleases(releases, devOnlySections) {
|
|
|
98
101
|
if (breaking) {
|
|
99
102
|
item.breaking = true;
|
|
100
103
|
}
|
|
104
|
+
if (commit.id !== void 0 && commit.id !== "") {
|
|
105
|
+
item.hash = commit.id;
|
|
106
|
+
}
|
|
101
107
|
items.push(item);
|
|
102
108
|
}
|
|
103
109
|
const sections = [];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
function buildEmptyReleaseEntry(version, date) {
|
|
2
|
+
return {
|
|
3
|
+
version,
|
|
4
|
+
date,
|
|
5
|
+
sections: [
|
|
6
|
+
{
|
|
7
|
+
title: "Notes",
|
|
8
|
+
audience: "dev",
|
|
9
|
+
items: [{ description: "Forced version bump." }]
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
buildEmptyReleaseEntry
|
|
16
|
+
};
|
|
@@ -2,3 +2,5 @@ import type { ChangelogEntry, ReleaseConfig } from './types.ts';
|
|
|
2
2
|
export declare function resolveChangelogJsonPath(config: Pick<ReleaseConfig, 'changelogJson'>, changelogPath: string): string;
|
|
3
3
|
export declare function writeChangelogJson(filePath: string, entries: ChangelogEntry[]): string;
|
|
4
4
|
export declare function upsertChangelogJson(filePath: string, entries: ChangelogEntry[]): string;
|
|
5
|
+
export declare function upsertChangelogJsonAndReturn(filePath: string, entries: ChangelogEntry[]): ChangelogEntry[];
|
|
6
|
+
export declare function mergeChangelogEntriesWithDisk(filePath: string, entries: ChangelogEntry[]): ChangelogEntry[];
|
|
@@ -14,11 +14,19 @@ function writeChangelogJson(filePath, entries) {
|
|
|
14
14
|
return filePath;
|
|
15
15
|
}
|
|
16
16
|
function upsertChangelogJson(filePath, entries) {
|
|
17
|
+
upsertChangelogJsonAndReturn(filePath, entries);
|
|
18
|
+
return filePath;
|
|
19
|
+
}
|
|
20
|
+
function upsertChangelogJsonAndReturn(filePath, entries) {
|
|
17
21
|
const existing = readExistingEntries(filePath);
|
|
18
22
|
const merged = mergeEntries(entries, existing);
|
|
19
23
|
mkdirSync(dirname(filePath), { recursive: true });
|
|
20
24
|
writeFileSync(filePath, stringify(merged, { maxLength: 100 }) + "\n", "utf8");
|
|
21
|
-
return
|
|
25
|
+
return merged;
|
|
26
|
+
}
|
|
27
|
+
function mergeChangelogEntriesWithDisk(filePath, entries) {
|
|
28
|
+
const existing = readExistingEntries(filePath);
|
|
29
|
+
return mergeEntries(entries, existing);
|
|
22
30
|
}
|
|
23
31
|
function sortNewestFirst(entries) {
|
|
24
32
|
return [...entries].sort((a, b) => compareVersionsDescending(a.version, b.version));
|
|
@@ -62,7 +70,9 @@ function compareVersionsDescending(a, b) {
|
|
|
62
70
|
return 0;
|
|
63
71
|
}
|
|
64
72
|
export {
|
|
73
|
+
mergeChangelogEntriesWithDisk,
|
|
65
74
|
resolveChangelogJsonPath,
|
|
66
75
|
upsertChangelogJson,
|
|
76
|
+
upsertChangelogJsonAndReturn,
|
|
67
77
|
writeChangelogJson
|
|
68
78
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ChangelogEntry } from './types.ts';
|
|
1
|
+
import type { ChangelogEntry, ChangelogItem } from './types.ts';
|
|
2
|
+
export declare function isChangelogItem(value: unknown): value is ChangelogItem;
|
|
2
3
|
export declare function isChangelogEntry(value: unknown): value is ChangelogEntry;
|
|
3
4
|
export declare function extractVersion(tag: string): string;
|
|
4
5
|
export declare function readChangelogEntries(filePath: string): ChangelogEntry[] | undefined;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { isRecord, isUnknownArray } from "./typeGuards.js";
|
|
3
|
+
function isChangelogItem(value) {
|
|
4
|
+
if (!isRecord(value)) return false;
|
|
5
|
+
if (typeof value.description !== "string") return false;
|
|
6
|
+
if (value.body !== void 0 && typeof value.body !== "string") return false;
|
|
7
|
+
if (value.breaking !== void 0 && typeof value.breaking !== "boolean") return false;
|
|
8
|
+
if (value.hash !== void 0 && typeof value.hash !== "string") return false;
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
3
11
|
function isChangelogEntry(value) {
|
|
4
12
|
return isRecord(value) && typeof value.version === "string" && typeof value.date === "string" && isUnknownArray(value.sections);
|
|
5
13
|
}
|
|
@@ -25,5 +33,6 @@ function readChangelogEntries(filePath) {
|
|
|
25
33
|
export {
|
|
26
34
|
extractVersion,
|
|
27
35
|
isChangelogEntry,
|
|
36
|
+
isChangelogItem,
|
|
28
37
|
readChangelogEntries
|
|
29
38
|
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { ChangelogEntry, ChangelogOverride, WorkspaceConfig } from './types.ts';
|
|
2
|
+
export type LoadChangelogOverridesResult = {
|
|
3
|
+
overrides: Map<string, ChangelogOverride>;
|
|
4
|
+
} | {
|
|
5
|
+
errors: string[];
|
|
6
|
+
};
|
|
7
|
+
export declare function loadChangelogOverrides(path: string): LoadChangelogOverridesResult;
|
|
8
|
+
export declare function validateChangelogOverrides(raw: unknown): {
|
|
9
|
+
overrides: Map<string, ChangelogOverride>;
|
|
10
|
+
errors: string[];
|
|
11
|
+
};
|
|
12
|
+
export declare function formatStaleOverrideKeyWarning(key: string): string;
|
|
13
|
+
export declare function applyChangelogOverrides(entries: ChangelogEntry[], overrides: Map<string, ChangelogOverride>): {
|
|
14
|
+
entries: ChangelogEntry[];
|
|
15
|
+
warnings: string[];
|
|
16
|
+
errors: string[];
|
|
17
|
+
matchedKeys: string[];
|
|
18
|
+
};
|
|
19
|
+
export declare function resolveOverridePath(scopeRoot: string): string;
|
|
20
|
+
export interface LoadOverridesForScopesResult {
|
|
21
|
+
project: Map<string, ChangelogOverride>;
|
|
22
|
+
perWorkspace: Map<string, Map<string, ChangelogOverride>>;
|
|
23
|
+
errors: string[];
|
|
24
|
+
}
|
|
25
|
+
export declare function loadOverridesForScopes(scopes: {
|
|
26
|
+
project?: string;
|
|
27
|
+
workspaces?: string[];
|
|
28
|
+
}): LoadOverridesForScopesResult;
|
|
29
|
+
export declare function composeOverrides(rootEntries: Map<string, ChangelogOverride>, workspaceEntries: Map<string, ChangelogOverride> | undefined): Map<string, ChangelogOverride>;
|
|
30
|
+
export interface OverrideContext {
|
|
31
|
+
project: Map<string, ChangelogOverride>;
|
|
32
|
+
perWorkspace: Map<string, Map<string, ChangelogOverride>>;
|
|
33
|
+
overrideWarnings: string[];
|
|
34
|
+
globalMatchedRootKeys: Set<string>;
|
|
35
|
+
}
|
|
36
|
+
export declare function createOverrideContext(workspaces: WorkspaceConfig[]): OverrideContext;
|
|
37
|
+
export interface ChangelogOverrideScope {
|
|
38
|
+
filePath: string;
|
|
39
|
+
hashes: readonly string[];
|
|
40
|
+
}
|
|
41
|
+
export interface ValidateAllChangelogOverridesInputs {
|
|
42
|
+
project?: {
|
|
43
|
+
filePath: string;
|
|
44
|
+
hashes?: readonly string[];
|
|
45
|
+
};
|
|
46
|
+
workspaces?: readonly ChangelogOverrideScope[];
|
|
47
|
+
}
|
|
48
|
+
export interface ValidateAllChangelogOverridesResult {
|
|
49
|
+
errors: string[];
|
|
50
|
+
warnings: string[];
|
|
51
|
+
}
|
|
52
|
+
export declare function validateAllChangelogOverrides(inputs: ValidateAllChangelogOverridesInputs): ValidateAllChangelogOverridesResult;
|
|
53
|
+
export declare function applyWorkspaceOverrides(newEntries: ChangelogEntry[], workspacePath: string, overrideContext: OverrideContext): ReturnType<typeof applyChangelogOverrides>;
|