@williamthorsen/release-kit 14.2.1 → 14.2.3
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 +77 -0
- package/.readyup/kits/default.js +142 -152
- package/.readyup/kits/npm-auto-publish.js +183 -184
- package/.readyup/manifest.json +83 -9
- package/CHANGELOG.md +24 -0
- package/README.md +7 -1
- package/dist/esm/applyChangelogOverrides.d.ts +50 -0
- package/dist/esm/applyChangelogOverrides.js +162 -0
- package/dist/esm/attachChangelogDiagnostics.d.ts +1 -1
- package/dist/esm/bin/release-kit.js +6 -238
- package/dist/esm/buildChangelogEntries.d.ts +20 -31
- package/dist/esm/buildChangelogEntries.js +71 -188
- package/dist/esm/buildChangelogItem.d.ts +56 -0
- package/dist/esm/buildChangelogItem.js +119 -0
- package/dist/esm/buildReleasedResult.d.ts +20 -0
- package/dist/esm/buildReleasedResult.js +78 -0
- package/dist/esm/changelogJsonUtils.d.ts +1 -1
- package/dist/esm/changelogOverrides.d.ts +29 -143
- package/dist/esm/changelogOverrides.js +35 -467
- package/dist/esm/configSchema.d.ts +225 -0
- package/dist/esm/configSchema.js +103 -0
- package/dist/esm/createGithubReleaseCommand.js +4 -3
- package/dist/esm/decideDirectReleases.d.ts +30 -0
- package/dist/esm/decideDirectReleases.js +66 -0
- package/dist/esm/defaults.js +1 -4
- package/dist/esm/defineConfig.d.ts +2 -2
- package/dist/esm/deriveReleaseNotesConfig.d.ts +2 -1
- package/dist/esm/deriveReleaseNotesConfig.js +1 -1
- package/dist/esm/determineBumpType.js +4 -3
- package/dist/esm/enumerateReleaseWindows.js +4 -4
- package/dist/esm/formatPrepareFiles.d.ts +11 -0
- package/dist/esm/formatPrepareFiles.js +55 -0
- package/dist/esm/formatPrepareWarnings.d.ts +26 -0
- package/dist/esm/formatPrepareWarnings.js +72 -0
- package/dist/esm/help/initHelp.d.ts +4 -0
- package/dist/esm/help/initHelp.js +31 -0
- package/dist/esm/help/overridesHelp.d.ts +4 -0
- package/dist/esm/help/overridesHelp.js +32 -0
- package/dist/esm/help/releaseStepsHelp.d.ts +12 -0
- package/dist/esm/help/releaseStepsHelp.js +91 -0
- package/dist/esm/help/syncLabelsHelp.d.ts +8 -0
- package/dist/esm/help/syncLabelsHelp.js +55 -0
- package/dist/esm/help/usage.d.ts +2 -0
- package/dist/esm/help/usage.js +29 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/init/initCommand.js +3 -7
- package/dist/esm/loadChangelogOverrides.d.ts +31 -0
- package/dist/esm/loadChangelogOverrides.js +138 -0
- package/dist/esm/loadConfig.d.ts +0 -40
- package/dist/esm/loadConfig.js +0 -242
- package/dist/esm/loadValidatedConfig.d.ts +1 -1
- package/dist/esm/mergeConfig.d.ts +41 -0
- package/dist/esm/mergeConfig.js +118 -0
- package/dist/esm/monorepoConfigAssertions.d.ts +49 -0
- package/dist/esm/monorepoConfigAssertions.js +126 -0
- package/dist/esm/planChangelogFiles.d.ts +16 -0
- package/dist/esm/planChangelogFiles.js +41 -0
- package/dist/esm/prepareArgs.d.ts +55 -0
- package/dist/esm/prepareArgs.js +69 -0
- package/dist/esm/prepareCommand.d.ts +0 -48
- package/dist/esm/prepareCommand.js +11 -77
- package/dist/esm/prepareComposite.d.ts +16 -0
- package/dist/esm/prepareComposite.js +39 -0
- package/dist/esm/prepareRunContext.d.ts +38 -0
- package/dist/esm/prepareRunContext.js +39 -0
- package/dist/esm/prepareTarget.d.ts +2 -7
- package/dist/esm/prepareTarget.js +2 -118
- package/dist/esm/previewTagPrefixes.d.ts +1 -1
- package/dist/esm/releasePrepareTargets.js +13 -207
- package/dist/esm/renderReleaseNotes.js +6 -5
- package/dist/esm/reportPrepare.js +3 -123
- package/dist/esm/resolveCommandTags.d.ts +1 -1
- package/dist/esm/resolveCommandTags.js +2 -1
- package/dist/esm/resolveReleaseDeclaration.d.ts +2 -1
- package/dist/esm/resolveReleaseTargets.d.ts +2 -1
- package/dist/esm/resolveReleaseTargets.js +2 -1
- package/dist/esm/stripScope.js +4 -3
- package/dist/esm/sync-labels/generateCommand.d.ts +1 -1
- package/dist/esm/sync-labels/resolveLabels.d.ts +1 -1
- package/dist/esm/topologicalSort.d.ts +12 -0
- package/dist/esm/topologicalSort.js +60 -0
- package/dist/esm/types.d.ts +1 -225
- package/dist/esm/types.js +1 -103
- package/dist/esm/validateAllChangelogOverrides.d.ts +56 -0
- package/dist/esm/validateAllChangelogOverrides.js +138 -0
- package/dist/esm/validateConfig.d.ts +1 -1
- package/dist/esm/validateConfig.js +7 -9
- package/dist/esm/validateOverridesCommand.d.ts +1 -1
- package/dist/esm/validateOverridesCommand.js +2 -1
- package/package.json +4 -4
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { formatStatusLine, truncateToWidth } from '@williamthorsen/nmr-core';
|
|
2
|
+
const SUBJECT_COLUMN_BUDGET = 72;
|
|
3
|
+
export function formatChangeRecordWarnings(lines, release, style, indent = '') {
|
|
4
|
+
const { malformedBlocks = [], undeclaredEntryTypes = [], unroutedEntryScopes = [] } = release;
|
|
5
|
+
if (malformedBlocks.length > 0) {
|
|
6
|
+
const count = malformedBlocks.length;
|
|
7
|
+
const header = `${count} change-record block${count === 1 ? '' : 's'} could not be read (item taken from the title)`;
|
|
8
|
+
lines.push(`${indent} ${formatStatusLine(style, 'warning', `${header}:`)}`);
|
|
9
|
+
for (const block of malformedBlocks) {
|
|
10
|
+
lines.push(`${indent} · ${block.commitHash.slice(0, 7)} '${truncateSubject(block.commitSubject)}': ${block.reason}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
if (undeclaredEntryTypes.length > 0) {
|
|
14
|
+
const count = undeclaredEntryTypes.length;
|
|
15
|
+
const header = `${count} change-record entr${count === 1 ? 'y has an' : 'ies have'} undeclared type${count === 1 ? '' : 's'} (no item)`;
|
|
16
|
+
lines.push(`${indent} ${formatStatusLine(style, 'warning', `${header}:`)}`);
|
|
17
|
+
for (const entry of undeclaredEntryTypes) {
|
|
18
|
+
const shortHash = entry.commitHash.slice(0, 7);
|
|
19
|
+
lines.push(`${indent} · ${shortHash} '${truncateSubject(entry.commitSubject)}': type '${entry.type}' at entry ${entry.entryPosition}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (unroutedEntryScopes.length === 0) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const count = unroutedEntryScopes.length;
|
|
26
|
+
const header = `${count} change-record entry scope${count === 1 ? ' does not match' : 's do not match'} any workspace in the commit's window (no item there)`;
|
|
27
|
+
lines.push(`${indent} ${formatStatusLine(style, 'warning', `${header}:`)}`);
|
|
28
|
+
for (const finding of unroutedEntryScopes) {
|
|
29
|
+
const shortHash = finding.commitHash.slice(0, 7);
|
|
30
|
+
lines.push(`${indent} · ${shortHash} '${truncateSubject(finding.commitSubject)}': scope '${finding.scope}' at entry ${finding.entryPosition}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function formatPolicyViolations(lines, violations, style, indent = '') {
|
|
34
|
+
if (violations === undefined || violations.length === 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const count = violations.length;
|
|
38
|
+
lines.push(`${indent} ${formatStatusLine(style, 'warning', `${count} policy violation${count === 1 ? '' : 's'}:`)}`);
|
|
39
|
+
for (const violation of violations) {
|
|
40
|
+
const shortHash = violation.commitHash.slice(0, 7);
|
|
41
|
+
const subject = violation.commitSubject;
|
|
42
|
+
const truncatedSubject = truncateSubject(subject);
|
|
43
|
+
const location = violation.surface === 'entry' ? `entry ${violation.entryPosition ?? '?'}` : `${violation.surface} surface`;
|
|
44
|
+
lines.push(`${indent} · ${shortHash} '${truncatedSubject}': type '${violation.type}' at ${location}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function formatUnparseableWarning(lines, release, style, indent = '') {
|
|
48
|
+
const unparseable = release.unparseableCommits;
|
|
49
|
+
if (unparseable === undefined || unparseable.length === 0) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const count = unparseable.length;
|
|
53
|
+
lines.push(`${indent} ${formatStatusLine(style, 'warning', `${count} commit${count === 1 ? '' : 's'} could not be parsed`)}`);
|
|
54
|
+
for (const commit of unparseable) {
|
|
55
|
+
const shortHash = commit.hash.slice(0, 7);
|
|
56
|
+
const truncatedSubject = truncateSubject(commit.subject);
|
|
57
|
+
lines.push(`${indent} · ${shortHash} ${truncatedSubject}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function formatWarnings(lines, result, style) {
|
|
61
|
+
const { warnings } = result;
|
|
62
|
+
if (warnings === undefined || warnings.length === 0) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
lines.push('');
|
|
66
|
+
for (const warning of warnings) {
|
|
67
|
+
lines.push(formatStatusLine(style, 'warning', warning));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function truncateSubject(subject) {
|
|
71
|
+
return truncateToWidth(subject, { width: SUBJECT_COLUMN_BUDGET });
|
|
72
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function showInitHelp() {
|
|
2
|
+
console.info(`
|
|
3
|
+
Usage: release-kit init [options]
|
|
4
|
+
|
|
5
|
+
Initialize release-kit in the current repository.
|
|
6
|
+
By default, scaffolds only the GitHub Actions workflow files. When every
|
|
7
|
+
package is private, skips publish.yaml and create-github-release.yaml.
|
|
8
|
+
|
|
9
|
+
Options:
|
|
10
|
+
--with-config Also scaffold .config/release-kit.config.ts
|
|
11
|
+
--force Overwrite existing files instead of skipping them
|
|
12
|
+
--dry-run Preview changes without writing files
|
|
13
|
+
--help, -h Show this help message
|
|
14
|
+
`);
|
|
15
|
+
}
|
|
16
|
+
export function showUpdateTemplatesHelp() {
|
|
17
|
+
console.info(`
|
|
18
|
+
Usage: release-kit update-templates [options]
|
|
19
|
+
|
|
20
|
+
Update the GitHub Actions workflows that release-kit scaffolds to the templates
|
|
21
|
+
of the installed version, showing what changed in each file. Creates a missing
|
|
22
|
+
workflow that \`init\` would create, and refreshes sync-labels.yaml only when it
|
|
23
|
+
exists. When every package is private, refreshes publish.yaml and
|
|
24
|
+
create-github-release.yaml only when they exist. Keeps publish.yaml's provenance
|
|
25
|
+
setting. Never touches config files.
|
|
26
|
+
|
|
27
|
+
Options:
|
|
28
|
+
--dry-run Preview changes without writing files
|
|
29
|
+
--help, -h Show this help message
|
|
30
|
+
`);
|
|
31
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export function showOverridesHelp() {
|
|
2
|
+
console.info(`
|
|
3
|
+
Usage: release-kit overrides <subcommand> [options]
|
|
4
|
+
|
|
5
|
+
Manage editorial changelog overrides.
|
|
6
|
+
|
|
7
|
+
Subcommands:
|
|
8
|
+
validate Validate every \`.meta/changelog-overrides.json\` file across all scopes
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
--help, -h Show this help message
|
|
12
|
+
`);
|
|
13
|
+
}
|
|
14
|
+
export function showOverridesValidateHelp() {
|
|
15
|
+
console.info(`
|
|
16
|
+
Usage: release-kit overrides validate
|
|
17
|
+
|
|
18
|
+
Validate every \`.meta/changelog-overrides.json\` file across the project and per-workspace
|
|
19
|
+
scopes. Reports schema/parse errors, ambiguous-prefix errors, conflicting-key errors, and
|
|
20
|
+
stale-key warnings.
|
|
21
|
+
|
|
22
|
+
Exit codes:
|
|
23
|
+
0 Clean: no errors, no stale keys
|
|
24
|
+
1 Stale-key warnings only (no errors)
|
|
25
|
+
2 Schema/parse, ambiguous-prefix, or conflicting-key errors (errors take precedence)
|
|
26
|
+
|
|
27
|
+
Options:
|
|
28
|
+
--config <path> Config file, relative to the current directory
|
|
29
|
+
(default: .config/release-kit.config.ts at the repo root)
|
|
30
|
+
--help, -h Show this help message
|
|
31
|
+
`);
|
|
32
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Prints the `commit` command's help text. */
|
|
2
|
+
export declare function showCommitHelp(): void;
|
|
3
|
+
/** Prints the `create-github-release` command's help text. */
|
|
4
|
+
export declare function showCreateGithubReleaseHelp(): void;
|
|
5
|
+
/** Prints the `publish` command's help text. */
|
|
6
|
+
export declare function showPublishHelp(): void;
|
|
7
|
+
/** Prints the `push` command's help text. */
|
|
8
|
+
export declare function showPushHelp(): void;
|
|
9
|
+
/** Prints the `show-tag-prefixes` command's help text. */
|
|
10
|
+
export declare function showShowTagPrefixesHelp(): void;
|
|
11
|
+
/** Prints the `tag` command's help text. */
|
|
12
|
+
export declare function showTagHelp(): void;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export function showCommitHelp() {
|
|
2
|
+
console.info(`
|
|
3
|
+
Usage: release-kit commit [options]
|
|
4
|
+
|
|
5
|
+
Stage all changes and create the release commit using tags and summary
|
|
6
|
+
produced by \`prepare\`.
|
|
7
|
+
|
|
8
|
+
Options:
|
|
9
|
+
--dry-run Preview the commit message without creating it
|
|
10
|
+
--help, -h Show this help message
|
|
11
|
+
`);
|
|
12
|
+
}
|
|
13
|
+
export function showCreateGithubReleaseHelp() {
|
|
14
|
+
console.info(`
|
|
15
|
+
Usage: release-kit create-github-release [options]
|
|
16
|
+
|
|
17
|
+
Create GitHub Releases from changelog.json for tags on HEAD. Private
|
|
18
|
+
(package.json#private) workspaces are skipped with a warning, and the command
|
|
19
|
+
doesn't create a Release for them. A project tag gets a Release even when the
|
|
20
|
+
root package is private.
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
--config <path> Config file, relative to the current directory
|
|
24
|
+
(default: .config/release-kit.config.ts at the repo root)
|
|
25
|
+
--dry-run Preview without creating releases
|
|
26
|
+
--tags=tag1,tag2 Only create releases for the named tags (comma-separated, full tag names)
|
|
27
|
+
--help, -h Show this help message
|
|
28
|
+
`);
|
|
29
|
+
}
|
|
30
|
+
export function showPublishHelp() {
|
|
31
|
+
console.info(`
|
|
32
|
+
Usage: release-kit publish [options]
|
|
33
|
+
|
|
34
|
+
Publish packages that have release tags on HEAD. Operates only on workspaces whose
|
|
35
|
+
package.json#private is absent or false. Without --tags, unpublishable workspaces are
|
|
36
|
+
silently filtered out. With --tags, an unpublishable tag is skipped with a warning while
|
|
37
|
+
any publishable tags are still published. A project tag is never published.
|
|
38
|
+
|
|
39
|
+
Options:
|
|
40
|
+
--config <path> Config file, relative to the current directory
|
|
41
|
+
(default: .config/release-kit.config.ts at the repo root)
|
|
42
|
+
--dry-run Preview without publishing
|
|
43
|
+
--no-git-checks Skip the clean-working-tree check
|
|
44
|
+
--tags=tag1,tag2 Only publish the named tags (comma-separated, full tag names)
|
|
45
|
+
--provenance Generate provenance statement (requires OIDC, not supported by classic yarn)
|
|
46
|
+
--help, -h Show this help message
|
|
47
|
+
`);
|
|
48
|
+
}
|
|
49
|
+
export function showPushHelp() {
|
|
50
|
+
console.info(`
|
|
51
|
+
Usage: release-kit push [options]
|
|
52
|
+
|
|
53
|
+
Push the release commit and each tag individually, so that GitHub Actions
|
|
54
|
+
starts a separate workflow run for each tag.
|
|
55
|
+
|
|
56
|
+
Options:
|
|
57
|
+
--config <path> Config file, relative to the current directory
|
|
58
|
+
(default: .config/release-kit.config.ts at the repo root)
|
|
59
|
+
--dry-run Preview without pushing
|
|
60
|
+
--tags=tag1,tag2 Only push the named tags (comma-separated, full tag names)
|
|
61
|
+
--tags-only Skip the branch push (push tags only)
|
|
62
|
+
--help, -h Show this help message
|
|
63
|
+
`);
|
|
64
|
+
}
|
|
65
|
+
export function showShowTagPrefixesHelp() {
|
|
66
|
+
console.info(`
|
|
67
|
+
Usage: release-kit show-tag-prefixes [options]
|
|
68
|
+
|
|
69
|
+
Print a per-workspace table of derived tag prefixes, tag counts, and declared
|
|
70
|
+
legacy tag prefixes. Reports any release-shaped tags whose prefix is neither a
|
|
71
|
+
derived prefix nor declared in \`legacyIdentities\`, with a copy-pasteable
|
|
72
|
+
config snippet.
|
|
73
|
+
|
|
74
|
+
Options:
|
|
75
|
+
--config <path> Config file, relative to the current directory
|
|
76
|
+
(default: .config/release-kit.config.ts at the repo root)
|
|
77
|
+
--help, -h Show this help message
|
|
78
|
+
`);
|
|
79
|
+
}
|
|
80
|
+
export function showTagHelp() {
|
|
81
|
+
console.info(`
|
|
82
|
+
Usage: release-kit tag [options]
|
|
83
|
+
|
|
84
|
+
Create annotated git tags from the tags file produced by \`prepare\`.
|
|
85
|
+
|
|
86
|
+
Options:
|
|
87
|
+
--dry-run Preview without creating tags
|
|
88
|
+
--no-git-checks Skip dirty working tree check
|
|
89
|
+
--help, -h Show this help message
|
|
90
|
+
`);
|
|
91
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Prints the `sync-labels generate` subcommand's help text. */
|
|
2
|
+
export declare function showSyncLabelsGenerateHelp(): void;
|
|
3
|
+
/** Prints the `sync-labels` command's help text. */
|
|
4
|
+
export declare function showSyncLabelsHelp(): void;
|
|
5
|
+
/** Prints the `sync-labels init` subcommand's help text. */
|
|
6
|
+
export declare function showSyncLabelsInitHelp(): void;
|
|
7
|
+
/** Prints the `sync-labels sync` subcommand's help text. */
|
|
8
|
+
export declare function showSyncLabelsSyncHelp(): void;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export function showSyncLabelsGenerateHelp() {
|
|
2
|
+
console.info(`
|
|
3
|
+
Usage: release-kit sync-labels generate [options]
|
|
4
|
+
|
|
5
|
+
Regenerate .github/labels.yaml from the repoLabels block of .config/release-kit.config.ts.
|
|
6
|
+
|
|
7
|
+
Options:
|
|
8
|
+
--check Report whether .github/labels.yaml is stale instead of writing it
|
|
9
|
+
--config <path> Config file, relative to the current directory
|
|
10
|
+
(default: .config/release-kit.config.ts at the repo root)
|
|
11
|
+
--help, -h Show this help message
|
|
12
|
+
`);
|
|
13
|
+
}
|
|
14
|
+
export function showSyncLabelsHelp() {
|
|
15
|
+
console.info(`
|
|
16
|
+
Usage: release-kit sync-labels <subcommand> [options]
|
|
17
|
+
|
|
18
|
+
Manage GitHub label synchronization via preset and custom label definitions.
|
|
19
|
+
|
|
20
|
+
Subcommands:
|
|
21
|
+
init Scaffold caller workflow and config, then generate labels
|
|
22
|
+
generate Regenerate .github/labels.yaml from config
|
|
23
|
+
sync Trigger the sync-labels workflow via gh CLI
|
|
24
|
+
|
|
25
|
+
Options:
|
|
26
|
+
--help, -h Show this help message
|
|
27
|
+
`);
|
|
28
|
+
}
|
|
29
|
+
export function showSyncLabelsInitHelp() {
|
|
30
|
+
console.info(`
|
|
31
|
+
Usage: release-kit sync-labels init [options]
|
|
32
|
+
|
|
33
|
+
Scaffold the sync-labels caller workflow and seed the repoLabels block of
|
|
34
|
+
.config/release-kit.config.ts with scope labels discovered from workspaces and
|
|
35
|
+
retired packages, then generate .github/labels.yaml. When the config file already
|
|
36
|
+
exists, print the block for manual paste instead of rewriting the file.
|
|
37
|
+
|
|
38
|
+
Options:
|
|
39
|
+
--config <path> Config file, relative to the current directory
|
|
40
|
+
(default: .config/release-kit.config.ts at the repo root)
|
|
41
|
+
--dry-run Preview changes without writing files
|
|
42
|
+
--force Overwrite existing files instead of skipping them
|
|
43
|
+
--help, -h Show this help message
|
|
44
|
+
`);
|
|
45
|
+
}
|
|
46
|
+
export function showSyncLabelsSyncHelp() {
|
|
47
|
+
console.info(`
|
|
48
|
+
Usage: release-kit sync-labels sync
|
|
49
|
+
|
|
50
|
+
Trigger the sync-labels GitHub Actions workflow via the gh CLI.
|
|
51
|
+
|
|
52
|
+
Options:
|
|
53
|
+
--help, -h Show this help message
|
|
54
|
+
`);
|
|
55
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { OUTPUT_STYLE_ENV_VAR } from "../resolveStylesOrExit.js";
|
|
2
|
+
export function showUsage() {
|
|
3
|
+
console.info(`
|
|
4
|
+
Usage: release-kit <command> [options]
|
|
5
|
+
|
|
6
|
+
Commands:
|
|
7
|
+
prepare Run release preparation (auto-discovers workspaces)
|
|
8
|
+
commit Stage changes and create the release commit
|
|
9
|
+
tag Create annotated git tags from the tags file
|
|
10
|
+
push Push release commit and tags (one push per tag)
|
|
11
|
+
publish Publish packages with release tags on HEAD
|
|
12
|
+
create-github-release Create GitHub Releases from changelog.json for tags on HEAD
|
|
13
|
+
show-tag-prefixes Show derived and declared legacy tag prefixes per workspace
|
|
14
|
+
init Initialize release-kit in the current repository
|
|
15
|
+
update-templates Update the scaffolded workflows to the current templates
|
|
16
|
+
overrides Manage editorial changelog overrides
|
|
17
|
+
sync-labels Manage GitHub label synchronization
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
--dry-run Preview changes without writing files
|
|
21
|
+
--help, -h Show this help message
|
|
22
|
+
--version, -V Show the version number
|
|
23
|
+
|
|
24
|
+
Environment:
|
|
25
|
+
${OUTPUT_STYLE_ENV_VAR}
|
|
26
|
+
Output style: auto (default), plain, or rich. auto prints plain,
|
|
27
|
+
without emoji, when CI is set or the stream is not a terminal.
|
|
28
|
+
`);
|
|
29
|
+
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { type ChangelogOverrideScope, type OverrideTargetItem, validateAllChangelogOverrides, type ValidateAllChangelogOverridesInputs, type ValidateAllChangelogOverridesResult, } from './
|
|
1
|
+
export { type ChangelogOverrideScope, type OverrideTargetItem, validateAllChangelogOverrides, type ValidateAllChangelogOverridesInputs, type ValidateAllChangelogOverridesResult, } from './validateAllChangelogOverrides.js';
|
|
2
2
|
export { formatValidateOverridesResult, type ValidateOverridesCommandResult } from './validateOverridesCommand.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { validateAllChangelogOverrides, } from "./
|
|
1
|
+
export { validateAllChangelogOverrides, } from "./validateAllChangelogOverrides.js";
|
|
2
2
|
export { formatValidateOverridesResult } from "./validateOverridesCommand.js";
|
|
@@ -6,13 +6,9 @@ import { formatPrivateWorkflowSkip, hasPublishablePackage } from "./hasPublishab
|
|
|
6
6
|
import { PUBLISHING_WORKFLOW_PATHS, scaffoldFiles } from "./scaffold.js";
|
|
7
7
|
export function checkEligibility(styles) {
|
|
8
8
|
printStep('Checking eligibility');
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return false;
|
|
13
|
-
if (!runRequiredCheck('pnpm detected', usesPnpm(), styles))
|
|
14
|
-
return false;
|
|
15
|
-
return true;
|
|
9
|
+
return (runRequiredCheck('Git repository detected', isGitRepo(), styles) &&
|
|
10
|
+
runRequiredCheck('package.json found', hasPackageJson(), styles) &&
|
|
11
|
+
runRequiredCheck('pnpm detected', usesPnpm(), styles));
|
|
16
12
|
}
|
|
17
13
|
export function initCommand({ dryRun, force, styles, withConfig }) {
|
|
18
14
|
if (dryRun) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ChangelogOverride } from './types.js';
|
|
2
|
+
/** Known fields on a single override entry; presence of any other field is a validation error. */
|
|
3
|
+
export declare const KNOWN_OVERRIDE_FIELDS: Set<string>;
|
|
4
|
+
/**
|
|
5
|
+
* Loads and validates the editorial overrides file at `path`. A missing file yields an empty map; an unreadable file,
|
|
6
|
+
* malformed JSON, a wrong top-level shape, or any per-entry validation failure yields errors.
|
|
7
|
+
*/
|
|
8
|
+
export declare function loadChangelogOverrides(path: string): LoadChangelogOverridesResult;
|
|
9
|
+
/** Result of loading an override file: either parsed overrides or a list of structured errors. */
|
|
10
|
+
export type LoadChangelogOverridesResult = {
|
|
11
|
+
overrides: Map<string, ChangelogOverride>;
|
|
12
|
+
} | {
|
|
13
|
+
errors: string[];
|
|
14
|
+
};
|
|
15
|
+
/** Form of an override key: a lowercase hex commit hash or prefix, optionally followed by `:<n>`, a 1-based entry position. */
|
|
16
|
+
export declare const OVERRIDE_KEY_PATTERN: RegExp;
|
|
17
|
+
/** Splits a valid override key into its hash prefix and, for an ordinal key, its 1-based entry position. */
|
|
18
|
+
export declare function parseOverrideKey(key: string): {
|
|
19
|
+
hashPrefix: string;
|
|
20
|
+
entry?: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Validates a parsed override record, returning the valid overrides and an error message for each problem.
|
|
24
|
+
*
|
|
25
|
+
* Each error names the offending key (e.g. `overrides['abc']: 'audience' must be one of …`) so that the user can find
|
|
26
|
+
* it in the override file.
|
|
27
|
+
*/
|
|
28
|
+
export declare function validateChangelogOverrides(raw: unknown): {
|
|
29
|
+
overrides: Map<string, ChangelogOverride>;
|
|
30
|
+
errors: string[];
|
|
31
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
3
|
+
import { isRecord } from "./typeGuards.js";
|
|
4
|
+
const VALID_AUDIENCE_VALUES = new Set(['all', 'dev', 'skip']);
|
|
5
|
+
const V1_SUPPORTED_AUDIENCE_VALUES = new Set(['skip']);
|
|
6
|
+
const SCHEMA_KEY = '$schema';
|
|
7
|
+
export const KNOWN_OVERRIDE_FIELDS = new Set(['audience', 'description', 'body', 'breaking']);
|
|
8
|
+
export function loadChangelogOverrides(path) {
|
|
9
|
+
if (!existsSync(path)) {
|
|
10
|
+
return { overrides: new Map() };
|
|
11
|
+
}
|
|
12
|
+
let content;
|
|
13
|
+
try {
|
|
14
|
+
content = readFileSync(path, 'utf8');
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
return {
|
|
18
|
+
errors: [`Failed to read override file ${path}: ${describeError(error)}`],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
let parsed;
|
|
22
|
+
try {
|
|
23
|
+
parsed = JSON.parse(content);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
return {
|
|
27
|
+
errors: [`Failed to parse override file ${path}: ${describeError(error)}`],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const result = validateChangelogOverrides(parsed);
|
|
31
|
+
if (result.errors.length > 0) {
|
|
32
|
+
return { errors: result.errors };
|
|
33
|
+
}
|
|
34
|
+
return { overrides: result.overrides };
|
|
35
|
+
}
|
|
36
|
+
export const OVERRIDE_KEY_PATTERN = /^[0-9a-f]+(:[1-9][0-9]*)?$/;
|
|
37
|
+
export function parseOverrideKey(key) {
|
|
38
|
+
const separatorIndex = key.indexOf(':');
|
|
39
|
+
if (separatorIndex === -1) {
|
|
40
|
+
return { hashPrefix: key };
|
|
41
|
+
}
|
|
42
|
+
return { hashPrefix: key.slice(0, separatorIndex), entry: Number(key.slice(separatorIndex + 1)) };
|
|
43
|
+
}
|
|
44
|
+
export function validateChangelogOverrides(raw) {
|
|
45
|
+
const overrides = new Map();
|
|
46
|
+
const errors = [];
|
|
47
|
+
if (!isRecord(raw)) {
|
|
48
|
+
errors.push('Override file: top-level value must be an object keyed by commit hash');
|
|
49
|
+
return { overrides, errors };
|
|
50
|
+
}
|
|
51
|
+
for (const [key, rawEntry] of Object.entries(raw)) {
|
|
52
|
+
if (key === SCHEMA_KEY) {
|
|
53
|
+
if (typeof rawEntry !== 'string') {
|
|
54
|
+
errors.push(`Override file: '${SCHEMA_KEY}' must be a string`);
|
|
55
|
+
}
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (!OVERRIDE_KEY_PATTERN.test(key)) {
|
|
59
|
+
errors.push(`overrides['${key}']: key must be a lowercase hex commit hash or prefix, optionally followed by ':<n>'`);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const validated = validateSingleOverride(key, rawEntry, errors);
|
|
63
|
+
if (validated !== undefined) {
|
|
64
|
+
overrides.set(key, validated);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { overrides, errors };
|
|
68
|
+
}
|
|
69
|
+
function validateAudience(key, value, errors) {
|
|
70
|
+
if (typeof value !== 'string' || !VALID_AUDIENCE_VALUES.has(value)) {
|
|
71
|
+
errors.push(`overrides['${key}']: 'audience' must be one of 'all' | 'dev' | 'skip'`);
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
if (!V1_SUPPORTED_AUDIENCE_VALUES.has(value)) {
|
|
75
|
+
errors.push(`overrides['${key}']: audience '${value}' is not yet supported; only 'skip' is currently accepted`);
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
return 'skip';
|
|
79
|
+
}
|
|
80
|
+
function validateSingleOverride(key, rawEntry, errors) {
|
|
81
|
+
if (!isRecord(rawEntry)) {
|
|
82
|
+
errors.push(`overrides['${key}']: must be an object`);
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
let entryValid = true;
|
|
86
|
+
for (const fieldName of Object.keys(rawEntry)) {
|
|
87
|
+
if (KNOWN_OVERRIDE_FIELDS.has(fieldName)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
errors.push(`overrides['${key}']: unknown field '${fieldName}'`);
|
|
91
|
+
entryValid = false;
|
|
92
|
+
}
|
|
93
|
+
const result = {};
|
|
94
|
+
if (rawEntry['audience'] !== undefined) {
|
|
95
|
+
const audienceResult = validateAudience(key, rawEntry['audience'], errors);
|
|
96
|
+
if (audienceResult === undefined) {
|
|
97
|
+
entryValid = false;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
result.audience = audienceResult;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (rawEntry['description'] !== undefined) {
|
|
104
|
+
if (typeof rawEntry['description'] !== 'string') {
|
|
105
|
+
errors.push(`overrides['${key}']: 'description' must be a string`);
|
|
106
|
+
entryValid = false;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
result.description = rawEntry['description'];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (rawEntry['body'] !== undefined) {
|
|
113
|
+
if (typeof rawEntry['body'] !== 'string') {
|
|
114
|
+
errors.push(`overrides['${key}']: 'body' must be a string`);
|
|
115
|
+
entryValid = false;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
result.body = rawEntry['body'];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (rawEntry['breaking'] !== undefined) {
|
|
122
|
+
if (typeof rawEntry['breaking'] !== 'boolean') {
|
|
123
|
+
errors.push(`overrides['${key}']: 'breaking' must be a boolean`);
|
|
124
|
+
entryValid = false;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
result.breaking = rawEntry['breaking'];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (Object.keys(result).length === 0 && entryValid) {
|
|
131
|
+
errors.push(`overrides['${key}']: at least one override field must be set`);
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
if (!entryValid) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
}
|
package/dist/esm/loadConfig.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { MonorepoReleaseConfig, ReleaseKitConfig, ReleaseSettings, WorkTypeConfig } from './types.js';
|
|
2
1
|
/** Path of the root `package.json` consulted when validating a `project` block. */
|
|
3
2
|
export declare const ROOT_PACKAGE_JSON_PATH = "package.json";
|
|
4
3
|
/**
|
|
@@ -25,42 +24,3 @@ export declare const CONFIG_FILE_PATH = ".config/release-kit.config.ts";
|
|
|
25
24
|
* imported, or exports neither a default nor a named `config`.
|
|
26
25
|
*/
|
|
27
26
|
export declare function loadConfig(configPath?: string): Promise<unknown>;
|
|
28
|
-
/**
|
|
29
|
-
* Information about the root `package.json` passed into `mergeMonorepoConfig` when a
|
|
30
|
-
* `project` block is configured. `readRootPackageVersion` performs the read, so that
|
|
31
|
-
* `mergeMonorepoConfig` does not perform any I/O.
|
|
32
|
-
*/
|
|
33
|
-
export interface RootPackageInfo {
|
|
34
|
-
exists: boolean;
|
|
35
|
-
version: string | undefined;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Resolves a final monorepo config from discovered workspaces and an optional user config overlay.
|
|
39
|
-
*
|
|
40
|
-
* Merging rules:
|
|
41
|
-
* - Release targets: `resolveReleaseDeclaration` projects the `releases` block, or the `workspaces` overrides and the
|
|
42
|
-
* `project` block, onto the discovered workspaces. Excluded workspaces move to `excludedWorkspaces`, and the
|
|
43
|
-
* directories that `releases` declares resolve through `deriveDirectoryConfig` into `directories`, which must not
|
|
44
|
-
* share a version file with any other target.
|
|
45
|
-
* - `workTypes`: Shallow merge; consumer entries override or add to defaults by key.
|
|
46
|
-
* - `versionPatterns`: Consumer value replaces defaults entirely.
|
|
47
|
-
* - Pass-through fields (see `applyOptionalPassthroughFields`): Consumer value wins.
|
|
48
|
-
* - `project`: Present iff the config declares a composite. Resolves `tagPrefix` to `DEFAULT_PROJECT_TAG_PREFIX` and
|
|
49
|
-
* `paths` to the union of its members' `paths` when omitted. Requires `rootPackage` to be passed and to contain a
|
|
50
|
-
* valid `version` field; throws otherwise. The resolved prefix is included in the strict-prefix collision check
|
|
51
|
-
* across all workspace and retired-package prefixes.
|
|
52
|
-
*/
|
|
53
|
-
export declare function mergeMonorepoConfig(discoveredPaths: string[], userConfig: ReleaseKitConfig | undefined, rootPackage?: RootPackageInfo): MonorepoReleaseConfig;
|
|
54
|
-
/**
|
|
55
|
-
* Resolves the release settings of a single-package repo from an optional user config overlay.
|
|
56
|
-
*
|
|
57
|
-
* Rejects a configured `project` or `releases` block: Both declare the targets of a monorepo, and a single-package
|
|
58
|
-
* repo has one target, its root package.
|
|
59
|
-
*/
|
|
60
|
-
export declare function mergeSinglePackageConfig(userConfig: ReleaseKitConfig | undefined): ReleaseSettings;
|
|
61
|
-
/**
|
|
62
|
-
* Merges consumer work-type overrides onto `DEFAULT_WORK_TYPES`.
|
|
63
|
-
*
|
|
64
|
-
* Preserves the declaration order of defaults; net-new consumer keys append at the end.
|
|
65
|
-
*/
|
|
66
|
-
export declare function resolveWorkTypes(userWorkTypes?: ReleaseKitConfig['workTypes']): Record<string, WorkTypeConfig>;
|