@williamthorsen/release-kit 11.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 +274 -2
- package/.readyup/kits/default.js +18 -33
- package/.readyup/kits/npm-auto-publish.js +24 -23
- package/.readyup/manifest.json +16 -11
- package/CHANGELOG.md +98 -0
- package/README.md +57 -69
- 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 +4 -0
- package/dist/esm/attachChangelogDiagnostics.js +14 -0
- package/dist/esm/bin/release-kit.js +88 -24
- package/dist/esm/buildChangelogEntries.d.ts +69 -17
- package/dist/esm/buildChangelogEntries.js +222 -120
- 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/buildReleaseSummary.js +2 -2
- 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 +79 -100
- package/dist/esm/changelogOverrides.js +138 -58
- package/dist/esm/classifyChangelogCommit.d.ts +36 -0
- package/dist/esm/classifyChangelogCommit.js +34 -0
- 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 +11 -41
- package/dist/esm/decideRelease.js +5 -27
- package/dist/esm/defaults.d.ts +5 -24
- package/dist/esm/defaults.js +7 -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 +11 -11
- package/dist/esm/determineBumpType.js +6 -7
- 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 +50 -0
- package/dist/esm/enumerateReleaseWindows.js +124 -0
- 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 +13 -26
- package/dist/esm/generateChangelogs.js +0 -14
- package/dist/esm/glyphs.d.ts +2 -2
- package/dist/esm/help/prepareHelp.d.ts +3 -4
- package/dist/esm/help/prepareHelp.js +7 -8
- package/dist/esm/index.d.ts +1 -1
- 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 +11 -11
- package/dist/esm/init/parseJsonRecord.d.ts +1 -4
- package/dist/esm/init/scaffold.d.ts +1 -3
- package/dist/esm/init/scaffold.js +2 -30
- 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 -5
- 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 +37 -0
- package/dist/esm/parseChangeRecordBlock.js +134 -0
- package/dist/esm/parseCommitMessage.d.ts +42 -32
- package/dist/esm/parseCommitMessage.js +33 -41
- 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 +17 -18
- 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 +25 -25
- package/dist/esm/releasePrepare.js +80 -80
- package/dist/esm/releasePrepareMono.d.ts +9 -7
- package/dist/esm/releasePrepareMono.js +114 -99
- package/dist/esm/releasePrepareProject.d.ts +19 -29
- package/dist/esm/releasePrepareProject.js +46 -45
- 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 +67 -42
- 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 +185 -116
- package/dist/esm/types.js +2 -2
- package/dist/esm/validateConfig.d.ts +2 -11
- package/dist/esm/validateConfig.js +5 -1
- package/dist/esm/validateOnlyExcludesStrandedDependents.d.ts +14 -12
- package/dist/esm/validateOverridesCommand.d.ts +19 -21
- package/dist/esm/validateOverridesCommand.js +16 -23
- package/docs/api.md +6 -6
- package/docs/changelogs.md +90 -28
- package/docs/configuration.md +30 -29
- package/docs/editorial-overrides.md +90 -31
- package/docs/labels.md +21 -19
- package/docs/project-releases.md +14 -14
- package/docs/publishing.md +5 -5
- package/docs/readiness-checks.md +3 -3
- package/docs/releasing.md +54 -24
- package/docs/work-types.md +46 -58
- package/package.json +7 -7
- package/presets/labels/common.yaml +1 -41
- package/schemas/changelog-overrides.json +39 -0
- package/cliff.toml.template +0 -65
- package/dist/esm/collectPolicyViolations.d.ts +0 -15
- package/dist/esm/collectPolicyViolations.js +0 -12
- package/dist/esm/determineBumpFromCommits.d.ts +0 -17
- package/dist/esm/determineBumpFromCommits.js +0 -28
- package/dist/esm/getCommitsSinceTarget.d.ts +0 -21
- package/dist/esm/getCommitsSinceTarget.js +0 -66
- package/dist/esm/resolveCliffConfigPath.d.ts +0 -11
- package/dist/esm/resolveCliffConfigPath.js +0 -20
- package/dist/esm/resolveReleaseNotesConfig.d.ts +0 -26
- package/dist/esm/resolveReleaseNotesConfig.js +0 -29
- package/dist/esm/runGitCliff.d.ts +0 -38
- package/dist/esm/runGitCliff.js +0 -25
- package/dist/esm/workTypesData.d.ts +0 -50
- package/dist/esm/workTypesData.js +0 -145
- package/schemas/label-map.json +0 -24
|
@@ -3,15 +3,7 @@ import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
|
3
3
|
import { hasPackageJson, isGitRepo, usesPnpm } from "./checks.js";
|
|
4
4
|
import { detectRepoType } from "./detectRepoType.js";
|
|
5
5
|
import { scaffoldFiles } from "./scaffold.js";
|
|
6
|
-
function
|
|
7
|
-
if (result.ok) {
|
|
8
|
-
printSuccess(label, styles.stdout);
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
printError(result.message ?? `${label} failed`, styles.stderr);
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
function checkEligibility(styles) {
|
|
6
|
+
export function checkEligibility(styles) {
|
|
15
7
|
printStep('Checking eligibility');
|
|
16
8
|
if (!runRequiredCheck('Git repository detected', isGitRepo(), styles))
|
|
17
9
|
return false;
|
|
@@ -62,14 +54,22 @@ export function initCommand({ dryRun, force, styles, withConfig }) {
|
|
|
62
54
|
}
|
|
63
55
|
printStep('Next steps');
|
|
64
56
|
const configHint = withConfig
|
|
65
|
-
? '1. (Optional) Customize .config/release-kit.config.ts
|
|
57
|
+
? '1. (Optional) Customize .config/release-kit.config.ts.'
|
|
66
58
|
: '1. (Optional) Run again with --with-config to scaffold config files.';
|
|
67
59
|
console.info(`
|
|
68
60
|
${configHint}
|
|
69
|
-
2. If this is a
|
|
61
|
+
2. If this is a private repo, remove provenance: true from .github/workflows/publish.yaml.
|
|
70
62
|
3. Test by running: npx @williamthorsen/release-kit prepare --dry-run
|
|
71
63
|
4. Commit the generated files.
|
|
72
64
|
5. Register each package as a trusted publisher on npmjs.com.
|
|
73
65
|
`);
|
|
74
66
|
return 0;
|
|
75
67
|
}
|
|
68
|
+
function runRequiredCheck(label, result, styles) {
|
|
69
|
+
if (result.ok) {
|
|
70
|
+
printSuccess(label, styles.stdout);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
printError(result.message ?? `${label} failed`, styles.stderr);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parse a JSON string and return the result if it is a plain object (Record<string, unknown>).
|
|
3
|
-
* Returns `undefined` if parsing fails or the result is not a plain object.
|
|
4
|
-
*/
|
|
1
|
+
/** Parses a JSON string, returning the result if it is a plain object and `undefined` otherwise. */
|
|
5
2
|
export declare function parseJsonRecord(raw: string): Record<string, unknown> | undefined;
|
|
@@ -6,8 +6,6 @@ interface ScaffoldOptions {
|
|
|
6
6
|
overwrite: boolean;
|
|
7
7
|
withConfig: boolean;
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
10
|
-
export declare function copyCliffTemplate(dryRun: boolean, overwrite: boolean): WriteResult;
|
|
11
|
-
/** Scaffold release-kit files for the target repo. Returns a result for each file attempted. */
|
|
9
|
+
/** Scaffolds release-kit files for the target repo, returning a result for each file attempted. */
|
|
12
10
|
export declare function scaffoldFiles({ repoType, dryRun, overwrite, withConfig }: ScaffoldOptions): WriteResult[];
|
|
13
11
|
export {};
|
|
@@ -1,33 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
import { findPackageRoot, writeFileWithCheck } from '@williamthorsen/nmr-core';
|
|
4
|
-
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
1
|
+
import { writeFileWithCheck } from '@williamthorsen/nmr-core';
|
|
5
2
|
import { createGithubReleaseWorkflow, publishWorkflow, releaseConfigScript, releaseWorkflow } from "./templates.js";
|
|
6
|
-
export function copyCliffTemplate(dryRun, overwrite) {
|
|
7
|
-
const destPath = '.config/git-cliff.toml';
|
|
8
|
-
let root;
|
|
9
|
-
try {
|
|
10
|
-
root = findPackageRoot(import.meta.url);
|
|
11
|
-
}
|
|
12
|
-
catch (error) {
|
|
13
|
-
const message = describeError(error);
|
|
14
|
-
return { filePath: destPath, outcome: 'failed', error: `Failed to resolve package root: ${message}` };
|
|
15
|
-
}
|
|
16
|
-
const templatePath = resolve(root, 'cliff.toml.template');
|
|
17
|
-
let content;
|
|
18
|
-
try {
|
|
19
|
-
content = readFileSync(templatePath, 'utf8');
|
|
20
|
-
}
|
|
21
|
-
catch (error) {
|
|
22
|
-
const message = describeError(error);
|
|
23
|
-
return {
|
|
24
|
-
filePath: destPath,
|
|
25
|
-
outcome: 'failed',
|
|
26
|
-
error: `Failed to read bundled template at ${templatePath}: ${message}`,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
return writeFileWithCheck(destPath, content, { dryRun, overwrite });
|
|
30
|
-
}
|
|
31
3
|
export function scaffoldFiles({ repoType, dryRun, overwrite, withConfig }) {
|
|
32
4
|
const results = [
|
|
33
5
|
writeFileWithCheck('.github/workflows/create-github-release.yaml', createGithubReleaseWorkflow(repoType), {
|
|
@@ -38,7 +10,7 @@ export function scaffoldFiles({ repoType, dryRun, overwrite, withConfig }) {
|
|
|
38
10
|
writeFileWithCheck('.github/workflows/release.yaml', releaseWorkflow(repoType), { dryRun, overwrite }),
|
|
39
11
|
];
|
|
40
12
|
if (withConfig) {
|
|
41
|
-
results.push(writeFileWithCheck('.config/release-kit.config.ts', releaseConfigScript(repoType), { dryRun, overwrite })
|
|
13
|
+
results.push(writeFileWithCheck('.config/release-kit.config.ts', releaseConfigScript(repoType), { dryRun, overwrite }));
|
|
42
14
|
}
|
|
43
15
|
return results;
|
|
44
16
|
}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import type { RepoType } from './detectRepoType.js';
|
|
2
|
-
/**
|
|
2
|
+
/** Generates the `.config/release-kit.config.ts` starter config, with commented-out options to customize. */
|
|
3
3
|
export declare function releaseConfigScript(repoType: RepoType): string;
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Generates the publish.yaml GitHub Actions entry-point workflow.
|
|
6
6
|
*
|
|
7
|
-
* The `permissions` block
|
|
8
|
-
*
|
|
9
|
-
*/
|
|
10
|
-
export declare function publishWorkflow(repoType: RepoType): string;
|
|
11
|
-
/**
|
|
12
|
-
* Generate the create-github-release.yaml GitHub Actions caller workflow.
|
|
13
|
-
*
|
|
14
|
-
* Fires on tag push and delegates to the reusable workflow under `contents: write`.
|
|
7
|
+
* The caller's `permissions` block caps what the reusable workflow receives, so it must grant the `id-token: write`
|
|
8
|
+
* that OIDC publishing needs. `provenance: false` omits the provenance input, which a private repo cannot use.
|
|
15
9
|
*/
|
|
10
|
+
export declare function publishWorkflow(repoType: RepoType, { provenance }?: {
|
|
11
|
+
provenance?: boolean;
|
|
12
|
+
}): string;
|
|
13
|
+
/** Generates the create-github-release.yaml GitHub Actions caller workflow. */
|
|
16
14
|
export declare function createGithubReleaseWorkflow(repoType: RepoType): string;
|
|
17
|
-
/**
|
|
15
|
+
/** Generates the release.yaml GitHub Actions workflow. */
|
|
18
16
|
export declare function releaseWorkflow(repoType: RepoType): string;
|
|
@@ -39,7 +39,7 @@ export default defineConfig({
|
|
|
39
39
|
});
|
|
40
40
|
`;
|
|
41
41
|
}
|
|
42
|
-
export function publishWorkflow(repoType) {
|
|
42
|
+
export function publishWorkflow(repoType, { provenance = true } = {}) {
|
|
43
43
|
const tagPattern = repoType === 'monorepo' ? "'*-v[0-9]*.[0-9]*.[0-9]*'" : "'v[0-9]*.[0-9]*.[0-9]*'";
|
|
44
44
|
return `# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
|
45
45
|
name: Publish
|
|
@@ -57,8 +57,7 @@ jobs:
|
|
|
57
57
|
publish:
|
|
58
58
|
uses: williamthorsen/node-monorepo-tools/.github/workflows/publish.reusable.yaml@workflow/publish-v1
|
|
59
59
|
with:
|
|
60
|
-
provenance: true
|
|
61
|
-
tags: \${{ github.ref_name }}
|
|
60
|
+
${provenance ? ' provenance: true\n' : ''} tags: \${{ github.ref_name }}
|
|
62
61
|
`;
|
|
63
62
|
}
|
|
64
63
|
export function createGithubReleaseWorkflow(repoType) {
|
|
@@ -94,16 +93,17 @@ on:
|
|
|
94
93
|
required: false
|
|
95
94
|
type: string
|
|
96
95
|
bump:
|
|
97
|
-
description: '
|
|
96
|
+
description: 'Version bump type (auto detects it from commits)'
|
|
98
97
|
required: false
|
|
99
98
|
type: choice
|
|
99
|
+
default: auto
|
|
100
100
|
options:
|
|
101
|
-
-
|
|
101
|
+
- auto
|
|
102
102
|
- patch
|
|
103
103
|
- minor
|
|
104
104
|
- major
|
|
105
105
|
force:
|
|
106
|
-
description: 'Force a release even when
|
|
106
|
+
description: 'Force a release even when there are not any commits, or any bump-worthy commits, since the last release (defaults to patch; combine with --bump for a different level)'
|
|
107
107
|
required: false
|
|
108
108
|
type: boolean
|
|
109
109
|
default: false
|
|
@@ -117,7 +117,7 @@ jobs:
|
|
|
117
117
|
uses: williamthorsen/node-monorepo-tools/.github/workflows/release.reusable.yaml@workflow/release-v1
|
|
118
118
|
with:
|
|
119
119
|
only: \${{ inputs.only }}
|
|
120
|
-
bump: \${{ inputs.bump }}
|
|
120
|
+
bump: \${{ inputs.bump != 'auto' && inputs.bump || '' }}
|
|
121
121
|
force: \${{ inputs.force }}
|
|
122
122
|
`;
|
|
123
123
|
}
|
|
@@ -128,16 +128,17 @@ on:
|
|
|
128
128
|
workflow_dispatch:
|
|
129
129
|
inputs:
|
|
130
130
|
bump:
|
|
131
|
-
description: '
|
|
131
|
+
description: 'Version bump type (auto detects it from commits)'
|
|
132
132
|
required: false
|
|
133
133
|
type: choice
|
|
134
|
+
default: auto
|
|
134
135
|
options:
|
|
135
|
-
-
|
|
136
|
+
- auto
|
|
136
137
|
- patch
|
|
137
138
|
- minor
|
|
138
139
|
- major
|
|
139
140
|
force:
|
|
140
|
-
description: 'Force a release even when
|
|
141
|
+
description: 'Force a release even when there are not any commits, or any bump-worthy commits, since the last release (defaults to patch; combine with --bump for a different level)'
|
|
141
142
|
required: false
|
|
142
143
|
type: boolean
|
|
143
144
|
default: false
|
|
@@ -150,7 +151,7 @@ jobs:
|
|
|
150
151
|
release:
|
|
151
152
|
uses: williamthorsen/node-monorepo-tools/.github/workflows/release.reusable.yaml@workflow/release-v1
|
|
152
153
|
with:
|
|
153
|
-
bump: \${{ inputs.bump }}
|
|
154
|
+
bump: \${{ inputs.bump != 'auto' && inputs.bump || '' }}
|
|
154
155
|
force: \${{ inputs.force }}
|
|
155
156
|
`;
|
|
156
157
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type StreamStyles } from '@williamthorsen/nmr-core';
|
|
2
|
+
interface UpdateTemplatesOptions {
|
|
3
|
+
dryRun: boolean;
|
|
4
|
+
styles: StreamStyles;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Runs the `release-kit update-templates` command and returns the process exit code.
|
|
8
|
+
*
|
|
9
|
+
* Brings each workflow that release-kit scaffolds up to date with the installed templates. The opt-in
|
|
10
|
+
* `sync-labels.yaml` is refreshed only when it exists, and config files are never read or written.
|
|
11
|
+
*/
|
|
12
|
+
export declare function updateTemplatesCommand({ dryRun, styles }: UpdateTemplatesOptions): number;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { printError, printStep, printSuccess, reportTemplateUpdate, updateManagedFile, } from '@williamthorsen/nmr-core';
|
|
3
|
+
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
4
|
+
import { syncLabelsWorkflow } from "../sync-labels/templates.js";
|
|
5
|
+
import { detectRepoType } from "./detectRepoType.js";
|
|
6
|
+
import { hasProvenance } from "./hasProvenance.js";
|
|
7
|
+
import { checkEligibility } from "./initCommand.js";
|
|
8
|
+
import { createGithubReleaseWorkflow, publishWorkflow, releaseWorkflow } from "./templates.js";
|
|
9
|
+
const PUBLISH_WORKFLOW_PATH = '.github/workflows/publish.yaml';
|
|
10
|
+
const SYNC_LABELS_WORKFLOW_PATH = '.github/workflows/sync-labels.yaml';
|
|
11
|
+
export function updateTemplatesCommand({ dryRun, styles }) {
|
|
12
|
+
if (dryRun) {
|
|
13
|
+
console.info('[dry-run mode]');
|
|
14
|
+
}
|
|
15
|
+
let eligible;
|
|
16
|
+
try {
|
|
17
|
+
eligible = checkEligibility(styles);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
printError(`Eligibility check failed: ${describeError(error)}`, styles.stderr);
|
|
21
|
+
return 1;
|
|
22
|
+
}
|
|
23
|
+
if (!eligible)
|
|
24
|
+
return 1;
|
|
25
|
+
printStep('Detecting repo type');
|
|
26
|
+
let repoType;
|
|
27
|
+
try {
|
|
28
|
+
repoType = detectRepoType();
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
printError(`Failed to detect repo type: ${describeError(error)}`, styles.stderr);
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
printSuccess(`Detected: ${repoType}`, styles.stdout);
|
|
35
|
+
printStep('Updating workflows');
|
|
36
|
+
let results;
|
|
37
|
+
try {
|
|
38
|
+
results = buildManagedFiles(repoType).map(([filePath, content]) => updateManagedFile(filePath, content, { dryRun }));
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
printError(`Failed to render workflows: ${describeError(error)}`, styles.stderr);
|
|
42
|
+
return 1;
|
|
43
|
+
}
|
|
44
|
+
for (const result of results) {
|
|
45
|
+
reportTemplateUpdate(result, dryRun, styles);
|
|
46
|
+
}
|
|
47
|
+
return results.some((result) => result.outcome === 'failed') ? 1 : 0;
|
|
48
|
+
}
|
|
49
|
+
function buildManagedFiles(repoType) {
|
|
50
|
+
const files = [
|
|
51
|
+
['.github/workflows/create-github-release.yaml', createGithubReleaseWorkflow(repoType)],
|
|
52
|
+
[PUBLISH_WORKFLOW_PATH, publishWorkflow(repoType, { provenance: readProvenanceSetting() })],
|
|
53
|
+
['.github/workflows/release.yaml', releaseWorkflow(repoType)],
|
|
54
|
+
];
|
|
55
|
+
if (existsSync(SYNC_LABELS_WORKFLOW_PATH)) {
|
|
56
|
+
files.push([SYNC_LABELS_WORKFLOW_PATH, syncLabelsWorkflow()]);
|
|
57
|
+
}
|
|
58
|
+
return files;
|
|
59
|
+
}
|
|
60
|
+
function readProvenanceSetting() {
|
|
61
|
+
if (!existsSync(PUBLISH_WORKFLOW_PATH))
|
|
62
|
+
return true;
|
|
63
|
+
return hasProvenance(readFileSync(PUBLISH_WORKFLOW_PATH, 'utf8'));
|
|
64
|
+
}
|
|
@@ -3,15 +3,11 @@ import type { ChangelogEntry } from './types.js';
|
|
|
3
3
|
export interface RenderedInjectedReadme {
|
|
4
4
|
/** The README with the release-notes section injected at the marker position. */
|
|
5
5
|
injectedReadme: string;
|
|
6
|
-
/**
|
|
7
|
-
* The standalone release-notes markdown for the target version (trimmed), prefixed with a
|
|
8
|
-
* labeled `## Release notes — v{version} ({date})` heading so the file is self-identifying.
|
|
9
|
-
* The GitHub-release body is rendered separately (without this heading) by `createGithubRelease`.
|
|
10
|
-
*/
|
|
6
|
+
/** The standalone release-notes markdown for the target version, trimmed and led by a `## Release notes` heading. */
|
|
11
7
|
releaseNotesMarkdown: string;
|
|
12
8
|
}
|
|
13
9
|
/**
|
|
14
|
-
* Discriminated reason
|
|
10
|
+
* Discriminated reason why release notes were not rendered for a tag.
|
|
15
11
|
*
|
|
16
12
|
* Shares the vocabulary of `CreateReleaseSkipReason` in `createGithubRelease.ts`, which classifies
|
|
17
13
|
* the same two conditions on the GitHub-release path.
|
|
@@ -30,11 +26,11 @@ export type RenderInjectedReadmeResult = {
|
|
|
30
26
|
* Renders a README with release notes injected at the marker position, and the standalone
|
|
31
27
|
* release-notes markdown, from an already-loaded README string and an in-memory entry set.
|
|
32
28
|
*
|
|
33
|
-
* This is the pure rendering core:
|
|
34
|
-
* caller
|
|
35
|
-
* rendering from a saved file, and each caller words a skip for its own output.
|
|
29
|
+
* This is the pure rendering core: It reads nothing, writes nothing, and reports nothing, so a
|
|
30
|
+
* caller that has entries that a release has computed but not yet written gets the same result as
|
|
31
|
+
* one rendering from a saved file, and each caller words a skip for its own output.
|
|
36
32
|
*
|
|
37
|
-
*
|
|
33
|
+
* Returns the version on a skip because both callers name it in their message and only this
|
|
38
34
|
* function has derived it from the tag.
|
|
39
35
|
*/
|
|
40
36
|
export declare function renderInjectedReadmeFromEntries(readme: string, entries: readonly ChangelogEntry[], tag: string, sectionOrder?: string[]): RenderInjectedReadmeResult;
|
|
@@ -42,16 +38,15 @@ export declare function renderInjectedReadmeFromEntries(readme: string, entries:
|
|
|
42
38
|
* Path-taking wrapper over {@link renderInjectedReadmeFromEntries} for callers rendering from a
|
|
43
39
|
* saved `changelog.json`, such as the publish-time injection flow.
|
|
44
40
|
*
|
|
45
|
-
* Adds the two skip conditions that only a file can present:
|
|
46
|
-
* not parse. Warns on every skip, its own and the renderer's alike, because the publish path
|
|
47
|
-
*
|
|
41
|
+
* Adds the two skip conditions that only a file can present: The changelog is missing, or it does
|
|
42
|
+
* not parse. Warns on every skip, its own and the renderer's alike, because the publish path does
|
|
43
|
+
* not have any other channel for the message.
|
|
48
44
|
*/
|
|
49
45
|
export declare function renderInjectedReadme(readme: string, changelogJsonPath: string, tag: string, sectionOrder?: string[]): RenderedInjectedReadme | undefined;
|
|
50
46
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* Returns the original README content, or `undefined` if injection was skipped.
|
|
47
|
+
* Injects release notes into a README file, returning the original content for restoration, or `undefined` when
|
|
48
|
+
* injection was skipped.
|
|
54
49
|
*/
|
|
55
50
|
export declare function injectReleaseNotesIntoReadme(readmePath: string, changelogJsonPath: string, tag: string, sectionOrder?: string[]): string | undefined;
|
|
56
|
-
/**
|
|
51
|
+
/** Returns the path of a workspace's `README.md`, or `undefined` when it has none. */
|
|
57
52
|
export declare function resolveReadmePath(workspacePath: string): string | undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Replaces or inserts a delimited section in file content.
|
|
3
3
|
*
|
|
4
|
-
* When markers exist, replaces the content between them.
|
|
5
|
-
* (with markers) at the top of the content.
|
|
4
|
+
* When both markers exist in order, replaces the content between them. Otherwise, prepends the
|
|
5
|
+
* section (with markers) at the top of the content.
|
|
6
6
|
*/
|
|
7
7
|
export declare function injectSection(content: string, key: string, injection: string): string;
|
package/dist/esm/loadConfig.d.ts
CHANGED
|
@@ -2,11 +2,12 @@ import type { MonorepoReleaseConfig, ReleaseConfig, ReleaseKitConfig, WorkTypeCo
|
|
|
2
2
|
/** Path of the root `package.json` consulted when validating a `project` block. */
|
|
3
3
|
export declare const ROOT_PACKAGE_JSON_PATH = "package.json";
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Reads the root `package.json` and returns its `version` field.
|
|
6
6
|
*
|
|
7
7
|
* Returns `{ exists: false }` when the file is missing, `{ exists: true, version: undefined }`
|
|
8
|
-
* when the file exists but
|
|
9
|
-
* are present
|
|
8
|
+
* when the file exists but does not have a `version` field, and `{ exists: true, version }`
|
|
9
|
+
* when both are present; `mergeMonorepoConfig` decides whether the situation is an error.
|
|
10
|
+
* Throws when the file cannot be read or parsed.
|
|
10
11
|
*/
|
|
11
12
|
export declare function readRootPackageVersion(): {
|
|
12
13
|
exists: boolean;
|
|
@@ -17,16 +18,17 @@ export declare const CONFIG_FILE_PATH = ".config/release-kit.config.ts";
|
|
|
17
18
|
/**
|
|
18
19
|
* Loads the config file, returning the raw config object.
|
|
19
20
|
*
|
|
20
|
-
* `configPath` is resolved against the working directory
|
|
21
|
-
*
|
|
21
|
+
* `configPath` is resolved against the working directory, which the CLI sets to the repo root, and defaults to
|
|
22
|
+
* `CONFIG_FILE_PATH`. The CLI resolves a `--config` value to an absolute path before passing it. An absent default
|
|
23
|
+
* path returns `undefined`, because a repo that does not declare a config is a supported state; an absent named path
|
|
22
24
|
* throws, because the caller asked for that file by name. Also throws when the file exists but cannot be
|
|
23
25
|
* imported, or exports neither a default nor a named `config`.
|
|
24
26
|
*/
|
|
25
27
|
export declare function loadConfig(configPath?: string): Promise<unknown>;
|
|
26
28
|
/**
|
|
27
29
|
* Information about the root `package.json` passed into `mergeMonorepoConfig` when a
|
|
28
|
-
* `project` block is configured.
|
|
29
|
-
*
|
|
30
|
+
* `project` block is configured. `readRootPackageVersion` performs the read, so that
|
|
31
|
+
* `mergeMonorepoConfig` does not perform any I/O.
|
|
30
32
|
*/
|
|
31
33
|
export interface RootPackageInfo {
|
|
32
34
|
exists: boolean;
|
|
@@ -36,12 +38,12 @@ export interface RootPackageInfo {
|
|
|
36
38
|
* Resolves a final monorepo config from discovered workspaces and an optional user config overlay.
|
|
37
39
|
*
|
|
38
40
|
* Merging rules:
|
|
39
|
-
* - `workspaces`:
|
|
41
|
+
* - `workspaces`: Match overlay entries by `dir` against discovered list; `shouldExclude: true`
|
|
40
42
|
* removes the workspace; unlisted packages keep defaults.
|
|
41
|
-
* - `workTypes`:
|
|
42
|
-
* - `versionPatterns`:
|
|
43
|
-
* -
|
|
44
|
-
* - `project`:
|
|
43
|
+
* - `workTypes`: Shallow merge; consumer entries override or add to defaults by key.
|
|
44
|
+
* - `versionPatterns`: Consumer value replaces defaults entirely.
|
|
45
|
+
* - Pass-through fields (see `applyOptionalPassthroughFields`): Consumer value wins.
|
|
46
|
+
* - `project`: Present iff `userConfig.project` is declared. Resolves `tagPrefix` to
|
|
45
47
|
* `DEFAULT_PROJECT_TAG_PREFIX` and `paths` to the union of the retained workspaces' `paths`
|
|
46
48
|
* when omitted. Requires `rootPackage` to be passed and to contain a valid `version` field;
|
|
47
49
|
* throws otherwise. The resolved prefix is included in the strict-prefix collision check
|
|
@@ -51,13 +53,13 @@ export declare function mergeMonorepoConfig(discoveredPaths: string[], userConfi
|
|
|
51
53
|
/**
|
|
52
54
|
* Resolves a final single-package config from an optional user config overlay.
|
|
53
55
|
*
|
|
54
|
-
* Rejects a configured `project` block:
|
|
56
|
+
* Rejects a configured `project` block: Project-level releases are a monorepo-only feature,
|
|
55
57
|
* since the implicit "all non-excluded workspaces contribute" rule is meaningless in a
|
|
56
58
|
* single-package repo.
|
|
57
59
|
*/
|
|
58
60
|
export declare function mergeSinglePackageConfig(userConfig: ReleaseKitConfig | undefined): ReleaseConfig;
|
|
59
61
|
/**
|
|
60
|
-
*
|
|
62
|
+
* Merges consumer work-type overrides onto `DEFAULT_WORK_TYPES`.
|
|
61
63
|
*
|
|
62
64
|
* Preserves the declaration order of defaults; net-new consumer keys append at the end.
|
|
63
65
|
*/
|
package/dist/esm/loadConfig.js
CHANGED
|
@@ -99,9 +99,6 @@ function applyOptionalPassthroughFields(result, userConfig) {
|
|
|
99
99
|
if (userConfig?.formatCommand !== undefined) {
|
|
100
100
|
result.formatCommand = userConfig.formatCommand;
|
|
101
101
|
}
|
|
102
|
-
if (userConfig?.cliffConfigPath !== undefined) {
|
|
103
|
-
result.cliffConfigPath = userConfig.cliffConfigPath;
|
|
104
|
-
}
|
|
105
102
|
if (userConfig?.scopeAliases !== undefined) {
|
|
106
103
|
result.scopeAliases = userConfig.scopeAliases;
|
|
107
104
|
}
|
|
@@ -172,7 +169,7 @@ function resolveProjectConfig(userProject, rootPackage, workspaces) {
|
|
|
172
169
|
throw new Error(`project block requires a root ${ROOT_PACKAGE_JSON_PATH}; create one with a 'version' field at the repo root`);
|
|
173
170
|
}
|
|
174
171
|
if (rootPackage.version === undefined) {
|
|
175
|
-
throw new Error(`project block requires root ${ROOT_PACKAGE_JSON_PATH} to have a 'version' field; add a 'version' field to
|
|
172
|
+
throw new Error(`project block requires root ${ROOT_PACKAGE_JSON_PATH} to have a 'version' field; add a 'version' field to the root package.json`);
|
|
176
173
|
}
|
|
177
174
|
return {
|
|
178
175
|
paths: userProject.paths ?? workspaces.flatMap((workspace) => workspace.paths),
|
|
@@ -215,7 +212,7 @@ function assertNoTagPrefixCollisions(workspaces, retiredPackages, project) {
|
|
|
215
212
|
if (isPrefixCollision(a.prefix, b.prefix)) {
|
|
216
213
|
throw new Error(`Tag prefix collision: '${a.prefix}' (${a.label}) and '${b.prefix}' (${b.label}). ` +
|
|
217
214
|
'One prefix is identical to or a strict prefix of the other; ' +
|
|
218
|
-
'
|
|
215
|
+
'a tag under the longer prefix can then match the shorter one and be counted among its releases.');
|
|
219
216
|
}
|
|
220
217
|
}
|
|
221
218
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type OutputStyle } from '@williamthorsen/nmr-core';
|
|
2
2
|
import type { ReleaseKitConfig } from './types.js';
|
|
3
3
|
/**
|
|
4
|
-
* Why a config file could not be used:
|
|
4
|
+
* Why a config file could not be used: The import threw, or the contents failed the schema.
|
|
5
5
|
*
|
|
6
6
|
* The distinction exists so that a caller can render the two differently. Every caller aborts on either.
|
|
7
7
|
*/
|
|
@@ -13,12 +13,12 @@ export type ConfigProblem = {
|
|
|
13
13
|
errors: string[];
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
|
-
* Outcome of loading and validating the consumer config file. `missing` is not an error
|
|
17
|
-
*
|
|
16
|
+
* Outcome of loading and validating the consumer config file. `missing` is not an error here; the caller decides
|
|
17
|
+
* whether an absent config file is one.
|
|
18
18
|
*
|
|
19
|
-
* `configFilePath` names the file the run read: the caller's `configPath`, or `CONFIG_FILE_PATH` when none was
|
|
20
|
-
* given.
|
|
21
|
-
* the same on every machine.
|
|
19
|
+
* `configFilePath` names the file that the run read: the caller's `configPath`, or `CONFIG_FILE_PATH` when none was
|
|
20
|
+
* given. The default stays relative to the working directory, so a message or a generated artifact that includes it
|
|
21
|
+
* reads the same on every machine.
|
|
22
22
|
*/
|
|
23
23
|
export type LoadValidatedConfigResult = {
|
|
24
24
|
status: 'invalid';
|
|
@@ -36,25 +36,22 @@ export type LoadValidatedConfigResult = {
|
|
|
36
36
|
/**
|
|
37
37
|
* Loads the consumer config file and validates it against the shared schema, returning the outcome.
|
|
38
38
|
*
|
|
39
|
-
* Writes nothing to any stream:
|
|
40
|
-
*
|
|
39
|
+
* Writes nothing to any stream: The caller picks the sink, which lets a command that must stay silent reuse this
|
|
40
|
+
* loader. `reportConfigProblem` and `reportConfigWarnings` render the stderr form.
|
|
41
41
|
*
|
|
42
|
-
* `configPath` defaults to `CONFIG_FILE_PATH`. A named path that does not exist is a load failure, so
|
|
43
|
-
* as `invalid` rather than `missing`.
|
|
42
|
+
* `configPath` defaults to `CONFIG_FILE_PATH`. A named path that does not exist is a load failure, so this function
|
|
43
|
+
* reports it as `invalid` rather than `missing`.
|
|
44
44
|
*/
|
|
45
45
|
export declare function loadValidatedConfig(configPath?: string): Promise<LoadValidatedConfigResult>;
|
|
46
46
|
/**
|
|
47
|
-
* Loads and validates the config
|
|
48
|
-
*
|
|
47
|
+
* Loads and validates the config for a CLI command, returning it, or `undefined` when the default config file does
|
|
48
|
+
* not exist.
|
|
49
49
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* a warning is not printed twice.
|
|
53
|
-
*
|
|
54
|
-
* The second load costs nothing: `import()` caches by URL and `validateConfig` is pure.
|
|
50
|
+
* Reports an unusable config to stderr and exits 1, whether the file failed to load or failed validation, and
|
|
51
|
+
* whether it was named by the caller or the default one. Validation warnings print to stderr.
|
|
55
52
|
*/
|
|
56
|
-
export declare function
|
|
57
|
-
/** Writes a config problem to stderr in the form every CLI command
|
|
53
|
+
export declare function loadUsableConfig(stderrStyle: OutputStyle, configPath?: string): Promise<ReleaseKitConfig | undefined>;
|
|
54
|
+
/** Writes a config problem to stderr in the form used by every CLI command. */
|
|
58
55
|
export declare function reportConfigProblem(problem: ConfigProblem, stderrStyle: OutputStyle): void;
|
|
59
56
|
/** Writes validation warnings to stderr as indented status lines. */
|
|
60
57
|
export declare function reportConfigWarnings(warnings: readonly string[], stderrStyle: OutputStyle): void;
|
|
@@ -20,12 +20,17 @@ export async function loadValidatedConfig(configPath) {
|
|
|
20
20
|
}
|
|
21
21
|
return { status: 'ok', config, configFilePath, warnings };
|
|
22
22
|
}
|
|
23
|
-
export async function
|
|
23
|
+
export async function loadUsableConfig(stderrStyle, configPath) {
|
|
24
24
|
const result = await loadValidatedConfig(configPath);
|
|
25
25
|
if (result.status === 'invalid') {
|
|
26
26
|
reportConfigProblem(result.problem, stderrStyle);
|
|
27
27
|
process.exit(1);
|
|
28
28
|
}
|
|
29
|
+
if (result.status === 'missing') {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
reportConfigWarnings(result.warnings, stderrStyle);
|
|
33
|
+
return result.config;
|
|
29
34
|
}
|
|
30
35
|
export function reportConfigProblem(problem, stderrStyle) {
|
|
31
36
|
if (problem.kind === 'load') {
|
package/dist/esm/packsPath.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reports whether npm would place `path` in the published tarball, given a package.json `files` value.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* everything beneath it, which is how `files: ["dist/*"]`
|
|
7
|
-
* of `path`
|
|
4
|
+
* npm packs everything when the `files` value is absent or malformed, and `packsPath` reports `true`; for an empty
|
|
5
|
+
* array, npm packs only the files that it always includes, and `packsPath` reports `false`. An entry naming an
|
|
6
|
+
* ancestor directory covers everything beneath it, which is how `files: ["dist/*"]` includes `dist/esm/index.js`, so
|
|
7
|
+
* `packsPath` tests every ancestor prefix of `path` rather than `path` alone.
|
|
8
8
|
*
|
|
9
|
-
* Two approximations of npm's packing rules remain, both failing toward a silent pass:
|
|
10
|
-
* (`!dist/*.map`) never counts toward inclusion, because gitignore-style ordered negation is not modeled; and a
|
|
11
|
-
* repo controlling its tarball through `.npmignore` alone
|
|
12
|
-
* without the ignore file
|
|
13
|
-
* a false one.
|
|
9
|
+
* Two approximations of npm's packing rules remain, both failing toward a silent pass: A negation entry
|
|
10
|
+
* (`!dist/*.map`) never counts toward inclusion, because gitignore-style ordered negation is not modeled; and for a
|
|
11
|
+
* repo controlling its tarball through `.npmignore` alone, which does not declare a `files` field, `packsPath`
|
|
12
|
+
* reports `true` without reading the ignore file. For a check that warns about an omission, a missed report does
|
|
13
|
+
* less harm than a false one.
|
|
14
14
|
*/
|
|
15
15
|
export declare function packsPath(filesField: unknown, path: string): boolean;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the last `change-record` block in a commit message into the change entries that it records.
|
|
3
|
+
*
|
|
4
|
+
* The block's grammar is codeassembly's `change-record.md`: a fence whose info string is exactly `change-record`,
|
|
5
|
+
* containing a YAML mapping. A merge commit's block contains `entries` plus the top-level `pr_number` and `ticket_ref`.
|
|
6
|
+
* A key that the grammar does not declare is ignored, and a declared key whose value is null reads as absent. Any
|
|
7
|
+
* defect makes the whole block malformed; `parseChangeRecordBlock` does not salvage any entry from a defective list.
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseChangeRecordBlock(message: string): ChangeRecordBlockReading;
|
|
10
|
+
/**
|
|
11
|
+
* Removes every `change-record` block from a message, fences included. A block that never closes runs to the end of
|
|
12
|
+
* the message, as a Markdown renderer reads it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function stripChangeRecordBlocks(message: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* What a commit's last `change-record` block reads as: absent, malformed with the defect named, or the entries that
|
|
17
|
+
* it records with the merge's pull-request number and ticket reference when the block declares them.
|
|
18
|
+
*/
|
|
19
|
+
export type ChangeRecordBlockReading = {
|
|
20
|
+
kind: 'absent';
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'malformed';
|
|
23
|
+
reason: string;
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'read';
|
|
26
|
+
entries: ChangeRecordEntry[];
|
|
27
|
+
prNumber?: number;
|
|
28
|
+
ticketRef?: string;
|
|
29
|
+
};
|
|
30
|
+
/** One outcome of a change, as the block records it. */
|
|
31
|
+
export interface ChangeRecordEntry {
|
|
32
|
+
breaking: boolean;
|
|
33
|
+
migration?: string;
|
|
34
|
+
scopes: string[];
|
|
35
|
+
text: string;
|
|
36
|
+
type: string;
|
|
37
|
+
}
|