@williamthorsen/release-kit 15.0.3 → 16.1.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 +93 -0
- package/.readyup/kits/default.js +14 -14
- package/.readyup/kits/npm-auto-publish.js +4 -4
- package/.readyup/manifest.json +13 -13
- package/CHANGELOG.md +27 -0
- package/README.md +12 -3
- package/dist/esm/applyChangelogOverrides.js +6 -6
- package/dist/esm/assertReleasesOnNpm.js +11 -11
- package/dist/esm/assertTaggedBaseline.js +5 -5
- package/dist/esm/assertTarballsComplete.d.ts +9 -0
- package/dist/esm/assertTarballsComplete.js +52 -0
- package/dist/esm/bin/release-kit.js +16 -16
- package/dist/esm/buildChangelogEntries.d.ts +19 -19
- package/dist/esm/buildChangelogEntries.js +40 -36
- package/dist/esm/buildChangelogItem.js +24 -24
- package/dist/esm/buildDependencyGraph.js +23 -23
- package/dist/esm/buildReleasedResult.js +21 -19
- package/dist/esm/buildSyntheticChangelogEntry.js +2 -2
- package/dist/esm/bumpVersion.js +8 -8
- package/dist/esm/changelogArchive.d.ts +1 -1
- package/dist/esm/changelogArchive.js +2 -2
- package/dist/esm/changelogJsonFile.js +5 -5
- package/dist/esm/changelogJsonUtils.js +3 -3
- package/dist/esm/changelogOverrides.d.ts +5 -5
- package/dist/esm/changelogOverrides.js +23 -23
- package/dist/esm/classifyChangelogCommit.js +4 -4
- package/dist/esm/commitCommand.js +3 -3
- package/dist/esm/compareVersions.js +13 -13
- package/dist/esm/configSchema.d.ts +3 -2
- package/dist/esm/configSchema.js +2 -1
- package/dist/esm/createGithubRelease.d.ts +4 -4
- package/dist/esm/createGithubRelease.js +10 -10
- package/dist/esm/createGithubReleaseCommand.js +9 -9
- package/dist/esm/createTags.d.ts +2 -2
- package/dist/esm/createTags.js +8 -8
- package/dist/esm/decideDirectReleases.d.ts +5 -5
- package/dist/esm/decideDirectReleases.js +25 -25
- package/dist/esm/decideRelease.d.ts +1 -1
- package/dist/esm/decideRelease.js +2 -2
- package/dist/esm/deriveDirectoryConfig.d.ts +1 -1
- package/dist/esm/deriveDirectoryConfig.js +18 -18
- package/dist/esm/deriveWorkspaceConfig.js +4 -4
- package/dist/esm/detectPackageManager.d.ts +2 -0
- package/dist/esm/detectPackageManager.js +8 -5
- package/dist/esm/detectUndeclaredTagPrefixes.js +6 -6
- package/dist/esm/enumerateReleaseWindows.d.ts +1 -1
- package/dist/esm/enumerateReleaseWindows.js +7 -7
- package/dist/esm/findMissingManifestPaths.d.ts +14 -0
- package/dist/esm/findMissingManifestPaths.js +90 -0
- package/dist/esm/findTransitiveDependents.js +5 -5
- package/dist/esm/findUnroutedEntryScopes.js +11 -11
- package/dist/esm/format.d.ts +1 -1
- package/dist/esm/format.js +1 -1
- package/dist/esm/formatPrepareFiles.d.ts +3 -3
- package/dist/esm/formatPrepareFiles.js +10 -10
- package/dist/esm/formatPrepareWarnings.js +6 -6
- package/dist/esm/hasPrettierConfig.js +2 -2
- package/dist/esm/init/checks.js +5 -3
- package/dist/esm/init/detectRepoType.js +3 -3
- package/dist/esm/init/initCommand.d.ts +4 -4
- package/dist/esm/init/initCommand.js +7 -7
- package/dist/esm/init/parseJsonRecord.d.ts +1 -1
- package/dist/esm/init/parseJsonRecord.js +4 -4
- package/dist/esm/init/scaffold.d.ts +4 -4
- package/dist/esm/init/scaffold.js +15 -15
- package/dist/esm/init/templates.d.ts +10 -10
- package/dist/esm/init/templates.js +5 -5
- package/dist/esm/init/updateTemplatesCommand.d.ts +2 -2
- package/dist/esm/init/updateTemplatesCommand.js +14 -12
- package/dist/esm/injectReleaseNotesIntoReadme.d.ts +1 -1
- package/dist/esm/injectReleaseNotesIntoReadme.js +6 -6
- package/dist/esm/injectSection.js +8 -8
- package/dist/esm/loadChangelogOverrides.d.ts +1 -1
- package/dist/esm/loadChangelogOverrides.js +9 -9
- package/dist/esm/loadConfig.d.ts +3 -3
- package/dist/esm/loadConfig.js +10 -10
- package/dist/esm/loadValidatedConfig.js +4 -4
- package/dist/esm/mergeConfig.d.ts +1 -1
- package/dist/esm/mergeConfig.js +27 -27
- package/dist/esm/monorepoConfigAssertions.js +15 -15
- package/dist/esm/npmRegistry.js +4 -4
- package/dist/esm/packFromCleanCheckout.d.ts +11 -0
- package/dist/esm/packFromCleanCheckout.js +81 -0
- package/dist/esm/packsPath.js +3 -3
- package/dist/esm/parseChangeRecordBlock.js +33 -33
- package/dist/esm/parseCommitMessage.js +5 -5
- package/dist/esm/planChangelogFiles.js +8 -8
- package/dist/esm/planReleaseNotesPreviews.js +10 -10
- package/dist/esm/planVersionBump.js +24 -16
- package/dist/esm/prepareArgs.d.ts +9 -9
- package/dist/esm/prepareArgs.js +11 -11
- package/dist/esm/prepareCommand.js +27 -24
- package/dist/esm/prepareComposite.d.ts +4 -4
- package/dist/esm/prepareComposite.js +16 -16
- package/dist/esm/{releasePrepareTargets.d.ts → prepareReleaseTargets.d.ts} +9 -9
- package/dist/esm/{releasePrepareTargets.js → prepareReleaseTargets.js} +40 -40
- package/dist/esm/prepareRunContext.d.ts +1 -1
- package/dist/esm/prepareRunContext.js +5 -5
- package/dist/esm/prepareTarget.d.ts +3 -3
- package/dist/esm/prepareTarget.js +41 -39
- package/dist/esm/previewTagPrefixes.js +19 -19
- package/dist/esm/propagateBumps.js +8 -8
- package/dist/esm/publish.d.ts +3 -3
- package/dist/esm/publish.js +6 -11
- package/dist/esm/publishCommand.d.ts +3 -3
- package/dist/esm/publishCommand.js +28 -20
- package/dist/esm/pushCommand.js +8 -8
- package/dist/esm/pushRelease.d.ts +1 -1
- package/dist/esm/pushRelease.js +2 -2
- package/dist/esm/readChangelogSections.d.ts +1 -1
- package/dist/esm/readChangelogSections.js +16 -16
- package/dist/esm/releasePlan.js +25 -25
- package/dist/esm/renderChangelogMarkdown.d.ts +4 -4
- package/dist/esm/renderChangelogMarkdown.js +18 -15
- package/dist/esm/renderReleaseNotes.d.ts +1 -1
- package/dist/esm/renderReleaseNotes.js +16 -16
- package/dist/esm/reportPrepare.js +34 -34
- package/dist/esm/resolveCommandTags.js +9 -9
- package/dist/esm/resolveReleaseDeclaration.d.ts +2 -2
- package/dist/esm/resolveReleaseDeclaration.js +22 -22
- package/dist/esm/resolveReleaseTags.js +17 -15
- package/dist/esm/resolveReleaseTargets.js +2 -2
- package/dist/esm/showTagPrefixesCommand.js +4 -4
- package/dist/esm/sync-labels/generateCommand.d.ts +3 -3
- package/dist/esm/sync-labels/generateCommand.js +10 -10
- package/dist/esm/sync-labels/initCommand.d.ts +3 -3
- package/dist/esm/sync-labels/initCommand.js +15 -15
- package/dist/esm/sync-labels/presets.js +3 -3
- package/dist/esm/sync-labels/resolveLabels.js +13 -13
- package/dist/esm/sync-labels/templates.d.ts +2 -2
- package/dist/esm/sync-labels/templates.js +1 -1
- package/dist/esm/tagCommand.js +4 -4
- package/dist/esm/topologicalSort.d.ts +2 -2
- package/dist/esm/topologicalSort.js +7 -7
- package/dist/esm/types.d.ts +3 -3
- package/dist/esm/validateAllChangelogOverrides.js +9 -9
- package/dist/esm/validateConfig.d.ts +1 -1
- package/dist/esm/validateConfig.js +60 -50
- package/dist/esm/validateOverridesCommand.js +2 -2
- package/docs/changelogs.md +5 -5
- package/docs/configuration.md +16 -15
- package/docs/publishing.md +4 -0
- package/docs/releasing.md +6 -0
- package/docs/work-types.md +1 -1
- package/package.json +2 -2
- package/presets/labels/common.yaml +3 -0
|
@@ -5,12 +5,12 @@ import type { CompositeTarget, ReleaseType, TargetPrepareResult } from './types.
|
|
|
5
5
|
* prepares it: every run that `only` doesn't narrow, and every one that names it. A `project` block's composite
|
|
6
6
|
* cannot be named.
|
|
7
7
|
*/
|
|
8
|
-
export declare function describeCompositeSkip(
|
|
8
|
+
export declare function describeCompositeSkip(compositeTarget: CompositeTarget, onlyNames: readonly string[] | undefined): string | undefined;
|
|
9
9
|
/**
|
|
10
10
|
* Prepares a composite target: reads its history, asserts its baseline, and decides and plans its release, appending
|
|
11
11
|
* its tag, writes, and modified files to the run's collection and its preview warnings to `warnings`.
|
|
12
12
|
*/
|
|
13
|
-
export declare function prepareComposite(
|
|
14
|
-
|
|
13
|
+
export declare function prepareComposite(compositeTarget: CompositeTarget, context: RunContext, options: {
|
|
14
|
+
shouldForce?: boolean;
|
|
15
15
|
bumpOverride?: ReleaseType;
|
|
16
|
-
},
|
|
16
|
+
}, collectedReleases: CollectedReleases, warnings: string[]): TargetPrepareResult;
|
|
@@ -2,38 +2,38 @@ import { assertTaggedBaseline } from "./assertTaggedBaseline.js";
|
|
|
2
2
|
import { collect } from "./prepareRunContext.js";
|
|
3
3
|
import { buildSkippedTargetResult, decideTargetRelease, planTargetRelease, readTargetHistory, } from "./prepareTarget.js";
|
|
4
4
|
import { PROJECT_TARGET_ID } from "./resolveReleaseTargets.js";
|
|
5
|
-
export function describeCompositeSkip(
|
|
6
|
-
if (
|
|
5
|
+
export function describeCompositeSkip(compositeTarget, onlyNames) {
|
|
6
|
+
if (onlyNames === undefined || onlyNames.includes(compositeTarget.id)) {
|
|
7
7
|
return undefined;
|
|
8
8
|
}
|
|
9
|
-
if (
|
|
10
|
-
return (`Project release skipped: --only narrows this run to ${
|
|
9
|
+
if (compositeTarget.id === PROJECT_TARGET_ID) {
|
|
10
|
+
return (`Project release skipped: --only narrows this run to ${onlyNames.join(', ')}. ` +
|
|
11
11
|
'Run `release-kit prepare` without --only to include the project release.');
|
|
12
12
|
}
|
|
13
|
-
return `Release '${
|
|
13
|
+
return `Release '${compositeTarget.id}' skipped: --only does not name it. Add ${compositeTarget.id} to --only to include it.`;
|
|
14
14
|
}
|
|
15
|
-
export function prepareComposite(
|
|
16
|
-
const { history,
|
|
17
|
-
assertTaggedBaseline([
|
|
18
|
-
const decision = decideTargetRelease(
|
|
19
|
-
|
|
15
|
+
export function prepareComposite(compositeTarget, context, options, collectedReleases, warnings) {
|
|
16
|
+
const { history, untaggedBaseline } = readTargetHistory(compositeTarget, context.settings);
|
|
17
|
+
assertTaggedBaseline([untaggedBaseline]);
|
|
18
|
+
const decision = decideTargetRelease(compositeTarget, history, {
|
|
19
|
+
shouldForce: options.shouldForce === true,
|
|
20
20
|
bumpOverride: options.bumpOverride,
|
|
21
21
|
setVersion: undefined,
|
|
22
22
|
});
|
|
23
23
|
if (decision.outcome === 'skip') {
|
|
24
|
-
return buildSkippedTargetResult(
|
|
24
|
+
return buildSkippedTargetResult(compositeTarget, history, decision.skipReason);
|
|
25
25
|
}
|
|
26
26
|
if (decision.setVersion !== undefined) {
|
|
27
27
|
throw new Error('A composite target cannot take --set-version');
|
|
28
28
|
}
|
|
29
|
-
const
|
|
29
|
+
const plannedRelease = planTargetRelease({
|
|
30
30
|
...context,
|
|
31
|
-
target:
|
|
31
|
+
target: compositeTarget,
|
|
32
32
|
release: { releaseType: decision.releaseType },
|
|
33
33
|
decision,
|
|
34
34
|
history,
|
|
35
35
|
});
|
|
36
|
-
collect(
|
|
37
|
-
warnings.push(...
|
|
38
|
-
return
|
|
36
|
+
collect(collectedReleases, plannedRelease);
|
|
37
|
+
warnings.push(...plannedRelease.warnings);
|
|
38
|
+
return plannedRelease.result;
|
|
39
39
|
}
|
|
@@ -12,7 +12,7 @@ export interface TargetPrepareOptions {
|
|
|
12
12
|
* Release even when the range since the last tag doesn't contain any commits or any bump-worthy commits.
|
|
13
13
|
* Orthogonal to `bumpOverride`: When `bumpOverride` is not given, the release falls back to `patch`.
|
|
14
14
|
*/
|
|
15
|
-
|
|
15
|
+
shouldForce?: boolean;
|
|
16
16
|
/** Level of the release, in place of the level that the changelog items call for; it doesn't trigger a release. */
|
|
17
17
|
bumpOverride?: ReleaseType;
|
|
18
18
|
/**
|
|
@@ -20,28 +20,28 @@ export interface TargetPrepareOptions {
|
|
|
20
20
|
* `RELEASE_NOTES.v{version}.md`) from its changelog entries. Requires `changelogJson.enabled`; when disabled, the
|
|
21
21
|
* plan records a warning and doesn't plan any previews.
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
shouldIncludeReleaseNotes?: boolean;
|
|
24
24
|
/**
|
|
25
25
|
* Ids of the targets from which the release starts; the run plans the named package targets and their transitive
|
|
26
26
|
* dependents, and each named composite, which reads its own window. Present only for a narrowed run, which skips
|
|
27
27
|
* every composite that it doesn't name.
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
onlyTargetIds?: readonly string[];
|
|
30
30
|
/**
|
|
31
31
|
* Explicit versions (canonical `N.N.N`), keyed by package target id. Each named target starts the release and
|
|
32
|
-
* releases at its version, which takes precedence over `bumpOverride` and `
|
|
32
|
+
* releases at its version, which takes precedence over `bumpOverride` and `shouldForce`.
|
|
33
33
|
*/
|
|
34
|
-
|
|
34
|
+
versionOverridesById?: ReadonlyMap<string, string>;
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Plans a release over a list of targets, without writing any file.
|
|
38
38
|
*
|
|
39
|
-
* 1. Selects the planned package and directory targets: every one, or, under `
|
|
40
|
-
* dependents.
|
|
39
|
+
* 1. Selects the planned package and directory targets: every one, or, under `onlyTargetIds`, those named and their
|
|
40
|
+
* transitive dependents.
|
|
41
41
|
* 2. Reads each planned target's history and decides its direct release.
|
|
42
42
|
* 3. Propagates bumps to dependents, asserts the baselines that matter, and sorts the release set topologically.
|
|
43
43
|
* 4. Plans each release in dependency order.
|
|
44
|
-
* 5. Prepares each composite after every package target, unless `
|
|
44
|
+
* 5. Prepares each composite after every package target, unless `onlyTargetIds` narrowed the run without naming it.
|
|
45
45
|
* 6. Renders the format command over the modified files.
|
|
46
46
|
*/
|
|
47
|
-
export declare function
|
|
47
|
+
export declare function prepareReleaseTargets(config: TargetPrepareConfig, options: TargetPrepareOptions): ReleasePlan;
|
|
@@ -13,11 +13,11 @@ import { collect, describeStage, isRepoRootTarget, readHistory, runStage, } from
|
|
|
13
13
|
import { buildSkippedTargetResult, planTargetRelease } from "./prepareTarget.js";
|
|
14
14
|
import { propagateBumps } from "./propagateBumps.js";
|
|
15
15
|
import { isSinglePackageTargets } from "./resolveReleaseTargets.js";
|
|
16
|
-
import {
|
|
16
|
+
import { sortTopologically } from "./topologicalSort.js";
|
|
17
17
|
const PREVIEWS_REQUIRE_JSON_WARNING = '--with-release-notes requires changelogJson.enabled; skipping preview generation';
|
|
18
|
-
export function
|
|
18
|
+
export function prepareReleaseTargets(config, options) {
|
|
19
19
|
const { settings } = config;
|
|
20
|
-
const {
|
|
20
|
+
const { onlyTargetIds, shouldIncludeReleaseNotes } = options;
|
|
21
21
|
const isSinglePackage = isSinglePackageTargets(config.targets);
|
|
22
22
|
const memberTargets = config.targets.filter((target) => target.kind !== 'composite');
|
|
23
23
|
const compositeTargets = config.targets.filter((target) => target.kind === 'composite');
|
|
@@ -25,91 +25,91 @@ export function releasePrepareTargets(config, options) {
|
|
|
25
25
|
const graph = buildDependencyGraph(memberTargets.filter((target) => target.kind === 'package').filter((target) => target.isWorkspace));
|
|
26
26
|
const startIds = selectStartIds(memberTargets, options);
|
|
27
27
|
const plannedIds = findTransitiveDependents(graph, startIds);
|
|
28
|
-
const
|
|
29
|
-
const arePreviewsBlocked =
|
|
28
|
+
const plannedTargets = memberTargets.filter((target) => plannedIds.has(target.id));
|
|
29
|
+
const arePreviewsBlocked = shouldIncludeReleaseNotes === true && !settings.changelogJson.enabled;
|
|
30
30
|
if (arePreviewsBlocked && !isSinglePackage) {
|
|
31
31
|
warnings.push(PREVIEWS_REQUIRE_JSON_WARNING);
|
|
32
32
|
}
|
|
33
33
|
const workTypes = resolveWorkTypes(settings.workTypes);
|
|
34
34
|
const context = {
|
|
35
35
|
settings,
|
|
36
|
-
overrideContext: createOverrideContext(
|
|
36
|
+
overrideContext: createOverrideContext(plannedTargets.flatMap(listOverrideDirectory)),
|
|
37
37
|
sectionOrder: deriveSectionOrder(workTypes),
|
|
38
38
|
dependenciesHeader: deriveDependenciesHeader(workTypes),
|
|
39
|
-
shouldPlanPreviews:
|
|
39
|
+
shouldPlanPreviews: shouldIncludeReleaseNotes === true && settings.changelogJson.enabled,
|
|
40
40
|
today: new Date().toISOString().slice(0, 10),
|
|
41
41
|
};
|
|
42
|
-
const
|
|
42
|
+
const directReleases = decideDirectReleases(plannedTargets, settings, options, startIds);
|
|
43
43
|
if (!isSinglePackage) {
|
|
44
|
-
reportUnroutedEntryScopes(
|
|
44
|
+
reportUnroutedEntryScopes(plannedTargets, directReleases, settings, memberTargets);
|
|
45
45
|
}
|
|
46
|
-
const releaseSet = propagateBumps(
|
|
47
|
-
assertTaggedBaseline([...
|
|
48
|
-
.filter(([id]) =>
|
|
46
|
+
const releaseSet = propagateBumps(directReleases.bumps, graph);
|
|
47
|
+
assertTaggedBaseline([...directReleases.untaggedBaselines]
|
|
48
|
+
.filter(([id]) => directReleases.bumps.has(id) || !releaseSet.has(id))
|
|
49
49
|
.map(([, untagged]) => untagged));
|
|
50
|
-
const {
|
|
50
|
+
const { sortedIds, cyclicIds } = sortTopologically(releaseSet, graph);
|
|
51
51
|
if (cyclicIds.length > 0) {
|
|
52
52
|
warnings.push(`Circular workspace dependencies detected among: ${cyclicIds.join(', ')}. ` +
|
|
53
53
|
'Propagation metadata may be incomplete for these workspaces.');
|
|
54
54
|
}
|
|
55
55
|
const resultsById = new Map();
|
|
56
|
-
for (const target of
|
|
57
|
-
const decision =
|
|
56
|
+
for (const target of plannedTargets) {
|
|
57
|
+
const decision = directReleases.decisions.get(target.id);
|
|
58
58
|
if (decision?.outcome === 'skip' && !releaseSet.has(target.id)) {
|
|
59
|
-
resultsById.set(target.id, buildSkippedTargetResult(target, readHistory(
|
|
59
|
+
resultsById.set(target.id, buildSkippedTargetResult(target, readHistory(directReleases.readings, target), decision.skipReason));
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
const
|
|
62
|
+
const collectedReleases = { tags: [], writes: [], removals: [], modifiedFiles: [] };
|
|
63
63
|
for (const id of sortedIds) {
|
|
64
|
-
const target =
|
|
64
|
+
const target = plannedTargets.find((candidate) => candidate.id === id);
|
|
65
65
|
const release = releaseSet.get(id);
|
|
66
66
|
if (target === undefined || release === undefined) {
|
|
67
67
|
continue;
|
|
68
68
|
}
|
|
69
|
-
const decision =
|
|
69
|
+
const decision = directReleases.decisions.get(id);
|
|
70
70
|
const plannedRelease = runStage(describeStage(target), () => planTargetRelease({
|
|
71
71
|
...context,
|
|
72
72
|
target,
|
|
73
73
|
release,
|
|
74
74
|
decision: decision?.outcome === 'release' ? decision : undefined,
|
|
75
|
-
history: readHistory(
|
|
75
|
+
history: readHistory(directReleases.readings, target),
|
|
76
76
|
}));
|
|
77
|
-
collect(
|
|
77
|
+
collect(collectedReleases, plannedRelease);
|
|
78
78
|
warnings.push(...plannedRelease.warnings);
|
|
79
79
|
resultsById.set(id, plannedRelease.result);
|
|
80
80
|
}
|
|
81
|
-
const results =
|
|
81
|
+
const results = plannedTargets.flatMap((target) => resultsById.get(target.id) ?? []);
|
|
82
82
|
for (const composite of compositeTargets) {
|
|
83
|
-
const skipWarning = describeCompositeSkip(composite,
|
|
83
|
+
const skipWarning = describeCompositeSkip(composite, onlyTargetIds);
|
|
84
84
|
if (skipWarning !== undefined) {
|
|
85
85
|
warnings.push(skipWarning);
|
|
86
86
|
continue;
|
|
87
87
|
}
|
|
88
|
-
const result = runStage(describeStage(composite), () => prepareComposite(composite, context, options,
|
|
88
|
+
const result = runStage(describeStage(composite), () => prepareComposite(composite, context, options, collectedReleases, warnings));
|
|
89
89
|
results.push(result);
|
|
90
90
|
}
|
|
91
|
-
const formatCommand = planFormatCommand(settings.formatCommand,
|
|
91
|
+
const formatCommand = planFormatCommand(settings.formatCommand, collectedReleases);
|
|
92
92
|
const { overrideContext } = context;
|
|
93
|
-
for (const overrideKey of overrideContext.
|
|
93
|
+
for (const overrideKey of overrideContext.projectOverrides.keys()) {
|
|
94
94
|
if (!overrideContext.globalMatchedRootKeys.has(overrideKey)) {
|
|
95
95
|
overrideContext.overrideWarnings.push(formatStaleOverrideKeyWarning(overrideKey));
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
const allWarnings = isSinglePackage
|
|
99
|
-
? composeSinglePackageWarnings(
|
|
99
|
+
? composeSinglePackageWarnings(collectedReleases, overrideContext, arePreviewsBlocked, warnings)
|
|
100
100
|
: [...warnings, ...overrideContext.overrideWarnings];
|
|
101
101
|
return {
|
|
102
102
|
targets: results,
|
|
103
|
-
tags:
|
|
104
|
-
writes:
|
|
105
|
-
removals:
|
|
103
|
+
tags: collectedReleases.tags,
|
|
104
|
+
writes: collectedReleases.writes,
|
|
105
|
+
removals: collectedReleases.removals,
|
|
106
106
|
summary: buildReleaseSummary({ targets: results }),
|
|
107
107
|
formatCommand,
|
|
108
108
|
...(allWarnings.length > 0 && { warnings: allWarnings }),
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
|
-
function composeSinglePackageWarnings(
|
|
112
|
-
if (
|
|
111
|
+
function composeSinglePackageWarnings(collectedReleases, overrideContext, arePreviewsBlocked, previewWarnings) {
|
|
112
|
+
if (collectedReleases.tags.length === 0) {
|
|
113
113
|
return [];
|
|
114
114
|
}
|
|
115
115
|
return [
|
|
@@ -124,18 +124,18 @@ function listOverrideDirectory(target) {
|
|
|
124
124
|
}
|
|
125
125
|
return target.isWorkspace ? [target.packagePath] : [];
|
|
126
126
|
}
|
|
127
|
-
function planFormatCommand(configuredCommand,
|
|
128
|
-
const
|
|
129
|
-
if (
|
|
127
|
+
function planFormatCommand(configuredCommand, collectedReleases) {
|
|
128
|
+
const baseCommand = configuredCommand ?? (hasPrettierConfig() ? 'npx prettier --write' : undefined);
|
|
129
|
+
if (collectedReleases.tags.length === 0 || baseCommand === undefined) {
|
|
130
130
|
return undefined;
|
|
131
131
|
}
|
|
132
|
-
const files =
|
|
133
|
-
return { command: `${
|
|
132
|
+
const files = collectedReleases.modifiedFiles;
|
|
133
|
+
return { command: `${baseCommand} ${files.join(' ')}`, files };
|
|
134
134
|
}
|
|
135
135
|
function selectStartIds(memberTargets, options) {
|
|
136
|
-
const {
|
|
137
|
-
if (
|
|
136
|
+
const { onlyTargetIds, versionOverridesById } = options;
|
|
137
|
+
if (onlyTargetIds === undefined) {
|
|
138
138
|
return new Set(memberTargets.map((target) => target.id));
|
|
139
139
|
}
|
|
140
|
-
return new Set([...
|
|
140
|
+
return new Set([...onlyTargetIds, ...(versionOverridesById?.keys() ?? [])]);
|
|
141
141
|
}
|
|
@@ -4,7 +4,7 @@ import { type TargetPrepareSettings } from './prepareTarget.js';
|
|
|
4
4
|
import type { PlannedWrite } from './releasePlan.js';
|
|
5
5
|
import type { DirectoryTarget, PackageTarget, ReleaseTarget } from './types.js';
|
|
6
6
|
/** Appends one planned release's tag, writes, removals, and modified files to the run's collection. */
|
|
7
|
-
export declare function collect(
|
|
7
|
+
export declare function collect(collectedReleases: CollectedReleases, plannedRelease: {
|
|
8
8
|
tag: string;
|
|
9
9
|
writes: PlannedWrite[];
|
|
10
10
|
removals: string[];
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { chainError } from '@williamthorsen/toolbelt.errors/candidate';
|
|
2
2
|
import { isRepoRoot } from "./prepareTarget.js";
|
|
3
|
-
export function collect(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export function collect(collectedReleases, plannedRelease) {
|
|
4
|
+
collectedReleases.tags.push(plannedRelease.tag);
|
|
5
|
+
collectedReleases.writes.push(...plannedRelease.writes);
|
|
6
|
+
collectedReleases.removals.push(...plannedRelease.removals);
|
|
7
|
+
collectedReleases.modifiedFiles.push(...plannedRelease.modifiedFiles);
|
|
8
8
|
}
|
|
9
9
|
export function describeStage(target) {
|
|
10
10
|
switch (target.kind) {
|
|
@@ -10,7 +10,7 @@ export type TargetPrepareSettings = Omit<ReleaseSettings, 'releaseNotes'>;
|
|
|
10
10
|
/** One read of a target's release windows, and the untagged baseline that it found, if any. */
|
|
11
11
|
export interface TargetReading {
|
|
12
12
|
history: ReleaseHistory;
|
|
13
|
-
|
|
13
|
+
untaggedBaseline: UntaggedBaseline | undefined;
|
|
14
14
|
}
|
|
15
15
|
/** Outcome of {@link decideTargetRelease}: a release at a decided level or at an explicit version, or a skip. */
|
|
16
16
|
export type TargetDecision = {
|
|
@@ -76,10 +76,10 @@ export declare function readTargetHistory(target: ReleaseTarget, settings: Targe
|
|
|
76
76
|
export declare function describeHistoryWindow(target: ReleaseTarget): GenerateChangelogOptions;
|
|
77
77
|
/**
|
|
78
78
|
* Decides a target's direct release from its window: `setVersion` releases at that version, and otherwise the
|
|
79
|
-
* window's bump, `
|
|
79
|
+
* window's bump, `shouldForce`, and `bumpOverride` decide as {@link decideRelease} states.
|
|
80
80
|
*/
|
|
81
81
|
export declare function decideTargetRelease(target: ReleaseTarget, history: ReleaseHistory, options: {
|
|
82
|
-
|
|
82
|
+
shouldForce: boolean;
|
|
83
83
|
bumpOverride: ReleaseType | undefined;
|
|
84
84
|
setVersion: string | undefined;
|
|
85
85
|
}): TargetDecision;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { findUntaggedBaseline } from "./assertTaggedBaseline.js";
|
|
2
2
|
import { attachChangelogDiagnostics } from "./attachChangelogDiagnostics.js";
|
|
3
|
-
import {
|
|
3
|
+
import { convertToReleaseEntries, readReleaseHistory } from "./buildChangelogEntries.js";
|
|
4
4
|
import { buildPropagationEntries, buildReleasedResult } from "./buildReleasedResult.js";
|
|
5
5
|
import { applyWorkspaceOverrides } from "./changelogOverrides.js";
|
|
6
6
|
import { decideRelease } from "./decideRelease.js";
|
|
@@ -12,14 +12,14 @@ import { PROJECT_TARGET_ID } from "./resolveReleaseTargets.js";
|
|
|
12
12
|
export function readTargetHistory(target, settings) {
|
|
13
13
|
const options = describeHistoryWindow(target);
|
|
14
14
|
const history = readReleaseHistory(settings, options);
|
|
15
|
-
const
|
|
15
|
+
const untaggedBaseline = findUntaggedBaseline({
|
|
16
16
|
label: describeBaselineLabel(target),
|
|
17
17
|
packageFiles: target.versionFiles,
|
|
18
18
|
changelogPaths: [target.changelogDir],
|
|
19
19
|
tagPrefixes: options.tagPrefixes,
|
|
20
20
|
previousTag: history.previousTag,
|
|
21
21
|
}, settings);
|
|
22
|
-
return { history,
|
|
22
|
+
return { history, untaggedBaseline };
|
|
23
23
|
}
|
|
24
24
|
export function describeHistoryWindow(target) {
|
|
25
25
|
return {
|
|
@@ -29,21 +29,21 @@ export function describeHistoryWindow(target) {
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
export function decideTargetRelease(target, history, options) {
|
|
32
|
-
const {
|
|
32
|
+
const { shouldForce, bumpOverride, setVersion } = options;
|
|
33
33
|
if (setVersion !== undefined) {
|
|
34
34
|
return { outcome: 'release', releaseType: undefined, bumpOverride: undefined, setVersion };
|
|
35
35
|
}
|
|
36
36
|
const tag = history.previousTag;
|
|
37
|
-
const
|
|
37
|
+
const sinceClause = tag === undefined ? '(no previous release found)' : `since ${tag}`;
|
|
38
38
|
const subject = isScopeRouted(target) || target.kind === 'directory' ? ` for ${target.id}` : '';
|
|
39
39
|
const decision = decideRelease({
|
|
40
|
-
naturalBump: history.
|
|
41
|
-
commitCount: history.
|
|
42
|
-
|
|
40
|
+
naturalBump: history.unreleasedReading.bump,
|
|
41
|
+
commitCount: history.unreleasedReading.commits.length,
|
|
42
|
+
shouldForce,
|
|
43
43
|
bumpOverride,
|
|
44
44
|
skipReasons: {
|
|
45
|
-
noCommits: `No commits${subject} ${
|
|
46
|
-
noBumpWorthy: `No bump-worthy commits${subject} ${
|
|
45
|
+
noCommits: `No commits${subject} ${sinceClause}. Pass --force to release at patch. Skipping.`,
|
|
46
|
+
noBumpWorthy: `No bump-worthy commits${subject} ${sinceClause}. Pass --force to release at patch (or --force --bump=X for a different level). Skipping.`,
|
|
47
47
|
},
|
|
48
48
|
});
|
|
49
49
|
if (decision.outcome === 'skip') {
|
|
@@ -54,42 +54,42 @@ export function decideTargetRelease(target, history, options) {
|
|
|
54
54
|
export function planTargetRelease(args) {
|
|
55
55
|
const { target, settings, release, decision, history, overrideContext, sectionOrder, shouldPlanPreviews, today } = args;
|
|
56
56
|
const setVersion = decision?.setVersion;
|
|
57
|
-
const
|
|
57
|
+
const bumpPlan = setVersion === undefined
|
|
58
58
|
? planVersionBump(target.versionFiles, release.releaseType)
|
|
59
59
|
: planVersionSet(target.versionFiles, setVersion);
|
|
60
|
-
const tag = `${target.tagPrefix}${
|
|
61
|
-
const writes = [...
|
|
60
|
+
const tag = `${target.tagPrefix}${bumpPlan.newVersion}`;
|
|
61
|
+
const writes = [...bumpPlan.writes];
|
|
62
62
|
const entries = decision === undefined
|
|
63
|
-
? buildPropagationEntries(target, release,
|
|
64
|
-
:
|
|
63
|
+
? buildPropagationEntries(target, release, bumpPlan.newVersion, today, args.dependenciesHeader)
|
|
64
|
+
: convertToReleaseEntries(history, tag, today);
|
|
65
65
|
const overrideScope = describeOverrideScope(target);
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
writes.push(...
|
|
66
|
+
const appliedOverrides = applyWorkspaceOverrides(entries, overrideScope, overrideContext);
|
|
67
|
+
const changelogPlan = planChangelogFiles(target.changelogDir, appliedOverrides.entries, settings, sectionOrder);
|
|
68
|
+
writes.push(...changelogPlan.writes);
|
|
69
69
|
const warnings = [];
|
|
70
70
|
const previewFiles = [];
|
|
71
71
|
if (shouldPlanPreviews) {
|
|
72
|
-
const
|
|
72
|
+
const previewsPlan = planReleaseNotesPreviews({
|
|
73
73
|
workspacePath: target.changelogDir,
|
|
74
74
|
tag,
|
|
75
|
-
entries:
|
|
75
|
+
entries: changelogPlan.entries,
|
|
76
76
|
sectionOrder,
|
|
77
77
|
});
|
|
78
|
-
writes.push(...
|
|
79
|
-
warnings.push(...
|
|
80
|
-
previewFiles.push(...
|
|
78
|
+
writes.push(...previewsPlan.writes);
|
|
79
|
+
warnings.push(...previewsPlan.warnings);
|
|
80
|
+
previewFiles.push(...previewsPlan.writes.map((write) => write.path));
|
|
81
81
|
}
|
|
82
82
|
const releaseFields = {
|
|
83
83
|
targetId: target.id,
|
|
84
|
-
commitCount: history.
|
|
85
|
-
currentVersion:
|
|
86
|
-
newVersion:
|
|
84
|
+
commitCount: history.unreleasedReading.commits.length,
|
|
85
|
+
currentVersion: bumpPlan.currentVersion,
|
|
86
|
+
newVersion: bumpPlan.newVersion,
|
|
87
87
|
tag,
|
|
88
|
-
bumpedFiles:
|
|
89
|
-
changelogFiles:
|
|
90
|
-
...(
|
|
88
|
+
bumpedFiles: bumpPlan.writes.map((write) => write.path),
|
|
89
|
+
changelogFiles: changelogPlan.changelogFiles,
|
|
90
|
+
...(changelogPlan.removals.length > 0 && { removedChangelogFiles: changelogPlan.removals }),
|
|
91
91
|
...(previewFiles.length > 0 && { previewFiles }),
|
|
92
|
-
...(
|
|
92
|
+
...(changelogPlan.preservation !== undefined && { changelogPreservation: [changelogPlan.preservation] }),
|
|
93
93
|
...(history.previousTag !== undefined && { previousTag: history.previousTag }),
|
|
94
94
|
};
|
|
95
95
|
const result = buildReleasedResult(target, releaseFields, release, decision, history);
|
|
@@ -97,25 +97,27 @@ export function planTargetRelease(args) {
|
|
|
97
97
|
result,
|
|
98
98
|
tag,
|
|
99
99
|
writes,
|
|
100
|
-
removals:
|
|
101
|
-
modifiedFiles: [...target.versionFiles, ...
|
|
100
|
+
removals: changelogPlan.removals,
|
|
101
|
+
modifiedFiles: [...target.versionFiles, ...changelogPlan.changelogFiles, ...changelogPlan.changelogJsonFiles],
|
|
102
102
|
warnings,
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
export function buildSkippedTargetResult(target, history, skipReason) {
|
|
106
|
-
const {
|
|
106
|
+
const { unreleasedReading } = history;
|
|
107
107
|
const fields = {
|
|
108
108
|
targetId: target.id,
|
|
109
109
|
status: 'skipped',
|
|
110
|
-
commitCount:
|
|
111
|
-
parsedCommitCount:
|
|
110
|
+
commitCount: unreleasedReading.commits.length,
|
|
111
|
+
parsedCommitCount: unreleasedReading.parsedCommitCount,
|
|
112
112
|
skipReason,
|
|
113
113
|
...(history.previousTag !== undefined && { previousTag: history.previousTag }),
|
|
114
|
-
...(
|
|
114
|
+
...(unreleasedReading.unparseableCommits !== undefined && {
|
|
115
|
+
unparseableCommits: unreleasedReading.unparseableCommits,
|
|
116
|
+
}),
|
|
115
117
|
};
|
|
116
|
-
const
|
|
117
|
-
attachChangelogDiagnostics(
|
|
118
|
-
return
|
|
118
|
+
const skippedResult = labelSkippedResult(target, fields);
|
|
119
|
+
attachChangelogDiagnostics(skippedResult, unreleasedReading.diagnostics);
|
|
120
|
+
return skippedResult;
|
|
119
121
|
}
|
|
120
122
|
export function isRepoRoot(target) {
|
|
121
123
|
return target.directoryPath === '.';
|
|
@@ -47,19 +47,19 @@ function buildOverrideMap(config, workspacePaths) {
|
|
|
47
47
|
return map;
|
|
48
48
|
}
|
|
49
49
|
function buildDirectoryRows(config, workspacePaths, overridesByPath) {
|
|
50
|
-
const
|
|
50
|
+
const discoveredPaths = new Set(workspacePaths);
|
|
51
51
|
return Object.entries(config?.releases ?? {}).flatMap(([name, entry]) => {
|
|
52
52
|
if (entry === false || !('path' in entry))
|
|
53
53
|
return [];
|
|
54
54
|
const directoryPath = normalizeWorkspacePath(entry.path);
|
|
55
|
-
if (
|
|
55
|
+
if (discoveredPaths.has(directoryPath))
|
|
56
56
|
return [];
|
|
57
|
-
const
|
|
57
|
+
const declaredDirectory = {
|
|
58
58
|
name,
|
|
59
59
|
path: directoryPath,
|
|
60
60
|
...(entry.tagPrefix !== undefined && { tagPrefix: entry.tagPrefix }),
|
|
61
61
|
};
|
|
62
|
-
return [buildPreviewRow(directoryPath, () => deriveDirectoryConfig(
|
|
62
|
+
return [buildPreviewRow(directoryPath, () => deriveDirectoryConfig(declaredDirectory).tagPrefix, overridesByPath)];
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
function buildPreviewRow(workspacePath, derivePrefix, overridesByPath) {
|
|
@@ -105,12 +105,12 @@ function detectCollisions(rows) {
|
|
|
105
105
|
for (const row of rows) {
|
|
106
106
|
if (row.derivedPrefix === null)
|
|
107
107
|
continue;
|
|
108
|
-
const
|
|
109
|
-
if (
|
|
108
|
+
const existingPaths = pathsByPrefix.get(row.derivedPrefix);
|
|
109
|
+
if (existingPaths === undefined) {
|
|
110
110
|
pathsByPrefix.set(row.derivedPrefix, [row.workspacePath]);
|
|
111
111
|
}
|
|
112
112
|
else {
|
|
113
|
-
|
|
113
|
+
existingPaths.push(row.workspacePath);
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
const collisions = [];
|
|
@@ -122,27 +122,27 @@ function detectCollisions(rows) {
|
|
|
122
122
|
return collisions;
|
|
123
123
|
}
|
|
124
124
|
function collectKnownPrefixes(rows, retiredPackages, compositeTagPrefix) {
|
|
125
|
-
const
|
|
125
|
+
const knownPrefixes = new Set();
|
|
126
126
|
for (const row of rows) {
|
|
127
127
|
if (row.derivedPrefix !== null)
|
|
128
|
-
|
|
128
|
+
knownPrefixes.add(row.derivedPrefix);
|
|
129
129
|
for (const entry of row.legacyEntries) {
|
|
130
|
-
|
|
130
|
+
knownPrefixes.add(entry.prefix);
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
-
for (const
|
|
134
|
-
|
|
133
|
+
for (const retiredPackage of retiredPackages) {
|
|
134
|
+
knownPrefixes.add(retiredPackage.tagPrefix);
|
|
135
135
|
}
|
|
136
136
|
if (compositeTagPrefix !== undefined)
|
|
137
|
-
|
|
138
|
-
return [...
|
|
137
|
+
knownPrefixes.add(compositeTagPrefix);
|
|
138
|
+
return [...knownPrefixes];
|
|
139
139
|
}
|
|
140
140
|
function buildRetiredPreviewEntries(retiredPackages) {
|
|
141
|
-
return retiredPackages.map((
|
|
142
|
-
name:
|
|
143
|
-
tagPrefix:
|
|
144
|
-
tagCount: countTagsMatching(
|
|
145
|
-
...(
|
|
141
|
+
return retiredPackages.map((retiredPackage) => ({
|
|
142
|
+
name: retiredPackage.name,
|
|
143
|
+
tagPrefix: retiredPackage.tagPrefix,
|
|
144
|
+
tagCount: countTagsMatching(retiredPackage.tagPrefix),
|
|
145
|
+
...(retiredPackage.successor !== undefined && { successor: retiredPackage.successor }),
|
|
146
146
|
}));
|
|
147
147
|
}
|
|
148
148
|
function findCompositeTagPrefix(config) {
|
|
@@ -5,16 +5,16 @@ export function propagateBumps(directBumps, graph) {
|
|
|
5
5
|
result.set(dir, { ...entry });
|
|
6
6
|
}
|
|
7
7
|
const queue = directBumps.keys().toArray();
|
|
8
|
-
const
|
|
8
|
+
const visitedDirs = new Set();
|
|
9
9
|
while (queue.length > 0) {
|
|
10
10
|
const dir = queue.shift();
|
|
11
11
|
if (dir === undefined) {
|
|
12
12
|
break;
|
|
13
13
|
}
|
|
14
|
-
if (
|
|
14
|
+
if (visitedDirs.has(dir)) {
|
|
15
15
|
continue;
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
visitedDirs.add(dir);
|
|
18
18
|
const packageName = graph.dirToPackageName.get(dir);
|
|
19
19
|
if (packageName === undefined) {
|
|
20
20
|
continue;
|
|
@@ -31,19 +31,19 @@ export function propagateBumps(directBumps, graph) {
|
|
|
31
31
|
}
|
|
32
32
|
for (const dependent of dependents) {
|
|
33
33
|
const dependentDir = dependent.id;
|
|
34
|
-
const
|
|
34
|
+
const existingEntry = result.get(dependentDir);
|
|
35
35
|
const propagationInfo = { packageName, newVersion };
|
|
36
|
-
if (
|
|
36
|
+
if (existingEntry === undefined) {
|
|
37
37
|
result.set(dependentDir, {
|
|
38
38
|
releaseType: 'patch',
|
|
39
39
|
propagatedFrom: [propagationInfo],
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
43
|
-
const
|
|
44
|
-
|
|
43
|
+
const existingSources = existingEntry.propagatedFrom ?? [];
|
|
44
|
+
existingEntry.propagatedFrom = [...existingSources, propagationInfo];
|
|
45
45
|
}
|
|
46
|
-
if (!
|
|
46
|
+
if (!visitedDirs.has(dependentDir)) {
|
|
47
47
|
queue.push(dependentDir);
|
|
48
48
|
}
|
|
49
49
|
}
|
package/dist/esm/publish.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type PackageManager } from './detectPackageManager.js';
|
|
2
2
|
import type { ResolvedTag } from './resolveReleaseTags.js';
|
|
3
3
|
export interface PublishOptions {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
isDryRun: boolean;
|
|
5
|
+
shouldGenerateProvenance: boolean;
|
|
6
6
|
}
|
|
7
7
|
/** Publishes a single package by running `{pm} publish` from its workspace directory. */
|
|
8
8
|
export declare function publishPackage(resolvedTag: ResolvedTag, packageManager: PackageManager, options: PublishOptions): void;
|