versionary 0.32.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action/index.js +2 -2
- package/dist/cli/index.js +18 -9
- package/dist/config/schema.d.ts +4 -7
- package/dist/config/schema.js +8 -18
- package/dist/release/artifact-rules.d.ts +2 -2
- package/dist/release/artifact-rules.js +4 -4
- package/dist/release/changelog.d.ts +1 -3
- package/dist/release/changelog.js +37 -14
- package/dist/release/plan.d.ts +25 -5
- package/dist/release/plan.js +252 -64
- package/dist/release/pr.d.ts +7 -26
- package/dist/release/pr.js +11 -65
- package/dist/release/release-as.d.ts +29 -0
- package/dist/release/release-as.js +70 -0
- package/dist/release/release.d.ts +0 -8
- package/dist/release/release.js +0 -8
- package/dist/release/state.js +3 -12
- package/dist/strategy/composite.js +11 -0
- package/dist/strategy/node.js +15 -0
- package/dist/strategy/rust.js +50 -3
- package/dist/strategy/types.d.ts +11 -0
- package/dist/types/config.d.ts +1 -3
- package/package.json +2 -2
package/dist/action/index.js
CHANGED
|
@@ -57,9 +57,9 @@ function setOutput(name, value) {
|
|
|
57
57
|
appendFileSync(outputPath, `${name}<<${delimiter}\n${value}\n${delimiter}\n`, "utf8");
|
|
58
58
|
}
|
|
59
59
|
function main() {
|
|
60
|
-
const token = getInput("token")
|
|
60
|
+
const token = getInput("token");
|
|
61
61
|
if (!token) {
|
|
62
|
-
throw new Error("Input required and not supplied: token
|
|
62
|
+
throw new Error("Input required and not supplied: token.");
|
|
63
63
|
}
|
|
64
64
|
const versionaryVersion = getInput("versionary-version") || "0.7.0";
|
|
65
65
|
const cwd = getInput("working-directory") || ".";
|
package/dist/cli/index.js
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
|
-
import { loadConfig } from "../config/load-config.js";
|
|
4
3
|
import { prependChangelog, renderReleasePlanChangelog, } from "../release/changelog.js";
|
|
5
4
|
import { createReleasePlan } from "../release/plan.js";
|
|
6
|
-
import { closeStaleReviewRequestIfExists,
|
|
5
|
+
import { closeStaleReviewRequestIfExists, isReleaseCommitMessage, openOrUpdateReviewRequest, prepareReleasePr, pushReleaseBranch, resolveReleaseHighlights, } from "../release/pr.js";
|
|
7
6
|
import { runRelease, runReleaseDetailed } from "../release/release.js";
|
|
8
7
|
import { verifyProject } from "../release/verify-project.js";
|
|
8
|
+
/**
|
|
9
|
+
* What a dry run would actually release. `plan.nextVersion` is the repository
|
|
10
|
+
* aggregate, which in a monorepo names no real release, so prefer the
|
|
11
|
+
* per-package versions whenever the plan has them.
|
|
12
|
+
*/
|
|
13
|
+
function formatDryRunReleaseSubject(plan) {
|
|
14
|
+
const releasing = (plan.packages ?? []).filter((pkg) => pkg.nextVersion);
|
|
15
|
+
if (releasing.length === 0) {
|
|
16
|
+
return plan.nextVersion ?? "";
|
|
17
|
+
}
|
|
18
|
+
return releasing
|
|
19
|
+
.map((pkg) => `${pkg.path === "." ? plan.packageName : pkg.path} ${pkg.nextVersion}`)
|
|
20
|
+
.join(", ");
|
|
21
|
+
}
|
|
9
22
|
function printVerifyResult() {
|
|
10
23
|
const result = verifyProject();
|
|
11
24
|
const categories = [
|
|
@@ -115,7 +128,7 @@ async function main() {
|
|
|
115
128
|
return 0;
|
|
116
129
|
}
|
|
117
130
|
if (flags["dry-run"]) {
|
|
118
|
-
const dryRunMessage = `Dry run: would prepare release PR branch ${plan.releaseBranchPrefix} for ${plan
|
|
131
|
+
const dryRunMessage = `Dry run: would prepare release PR branch ${plan.releaseBranchPrefix} for ${formatDryRunReleaseSubject(plan)}`;
|
|
119
132
|
if (flags.json) {
|
|
120
133
|
emitJson({
|
|
121
134
|
action: "pr-dry-run",
|
|
@@ -195,8 +208,7 @@ async function main() {
|
|
|
195
208
|
console.log("No releasable commits found.");
|
|
196
209
|
return 0;
|
|
197
210
|
}
|
|
198
|
-
const
|
|
199
|
-
const highlightsResult = resolveReleaseHighlights(process.cwd(), loaded.config, plan.changelogFile, plan.changelogFormat, logger);
|
|
211
|
+
const highlightsResult = resolveReleaseHighlights(process.cwd(), plan.changelogFile, plan.changelogFormat);
|
|
200
212
|
const section = renderReleasePlanChangelog(plan, {
|
|
201
213
|
highlights: highlightsResult.highlights,
|
|
202
214
|
});
|
|
@@ -205,9 +217,6 @@ async function main() {
|
|
|
205
217
|
return 0;
|
|
206
218
|
}
|
|
207
219
|
prependChangelog(process.cwd(), plan.changelogFile, section, plan.changelogFormat);
|
|
208
|
-
if (highlightsResult.source === "file" && highlightsResult.filePath) {
|
|
209
|
-
consumeNextReleaseFile(process.cwd(), highlightsResult.filePath);
|
|
210
|
-
}
|
|
211
220
|
console.log(`Updated ${plan.changelogFile}`);
|
|
212
221
|
return 0;
|
|
213
222
|
}
|
|
@@ -223,7 +232,7 @@ async function main() {
|
|
|
223
232
|
return 0;
|
|
224
233
|
}
|
|
225
234
|
if (flags["dry-run"]) {
|
|
226
|
-
console.log(`Dry run: would prepare release PR branch ${plan.releaseBranchPrefix} for ${plan
|
|
235
|
+
console.log(`Dry run: would prepare release PR branch ${plan.releaseBranchPrefix} for ${formatDryRunReleaseSubject(plan)}`);
|
|
227
236
|
return 0;
|
|
228
237
|
}
|
|
229
238
|
const pr = prepareReleasePr(process.cwd(), { logger: console });
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ export declare const configSchema: z.ZodObject<{
|
|
|
5
5
|
"review-mode": z.ZodOptional<z.ZodEnum<{
|
|
6
6
|
direct: "direct";
|
|
7
7
|
pr: "pr";
|
|
8
|
-
review: "review";
|
|
9
8
|
}>>;
|
|
10
9
|
"version-file": z.ZodOptional<z.ZodString>;
|
|
11
10
|
"changelog-file": z.ZodOptional<z.ZodString>;
|
|
@@ -15,17 +14,16 @@ export declare const configSchema: z.ZodObject<{
|
|
|
15
14
|
}>>;
|
|
16
15
|
"release-draft": z.ZodOptional<z.ZodBoolean>;
|
|
17
16
|
"release-reference-comments": z.ZodOptional<z.ZodEnum<{
|
|
18
|
-
off: "off";
|
|
19
17
|
"best-effort": "best-effort";
|
|
18
|
+
off: "off";
|
|
20
19
|
strict: "strict";
|
|
21
20
|
}>>;
|
|
22
21
|
"release-branch": z.ZodOptional<z.ZodString>;
|
|
23
22
|
"baseline-file": z.ZodOptional<z.ZodString>;
|
|
24
|
-
"next-release-file": z.ZodOptional<z.ZodString>;
|
|
25
23
|
"bootstrap-sha": z.ZodOptional<z.ZodString>;
|
|
26
24
|
"monorepo-mode": z.ZodOptional<z.ZodEnum<{
|
|
27
|
-
independent: "independent";
|
|
28
25
|
fixed: "fixed";
|
|
26
|
+
independent: "independent";
|
|
29
27
|
}>>;
|
|
30
28
|
"bump-minor-pre-major": z.ZodOptional<z.ZodBoolean>;
|
|
31
29
|
"allow-stable-major": z.ZodOptional<z.ZodBoolean>;
|
|
@@ -45,14 +43,13 @@ export declare const configSchema: z.ZodObject<{
|
|
|
45
43
|
"extra-files": z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
46
44
|
type: z.ZodEnum<{
|
|
47
45
|
json: "json";
|
|
48
|
-
toml: "toml";
|
|
49
|
-
yaml: "yaml";
|
|
50
46
|
nix: "nix";
|
|
51
47
|
regex: "regex";
|
|
48
|
+
toml: "toml";
|
|
49
|
+
yaml: "yaml";
|
|
52
50
|
}>;
|
|
53
51
|
path: z.ZodString;
|
|
54
52
|
"field-path": z.ZodOptional<z.ZodString>;
|
|
55
|
-
jsonpath: z.ZodOptional<z.ZodString>;
|
|
56
53
|
pattern: z.ZodOptional<z.ZodString>;
|
|
57
54
|
replacement: z.ZodOptional<z.ZodString>;
|
|
58
55
|
}, z.core.$strip>>>;
|
package/dist/config/schema.js
CHANGED
|
@@ -4,44 +4,35 @@ const artifactRuleSchema = z
|
|
|
4
4
|
type: z.enum(["json", "toml", "yaml", "nix", "regex"]),
|
|
5
5
|
path: z.string().min(1),
|
|
6
6
|
"field-path": z.string().optional(),
|
|
7
|
-
jsonpath: z.string().optional(),
|
|
8
7
|
pattern: z.string().optional(),
|
|
9
8
|
replacement: z.string().optional(),
|
|
10
9
|
})
|
|
11
10
|
.superRefine((value, ctx) => {
|
|
12
|
-
const
|
|
11
|
+
const needsFieldPath = value.type === "json" ||
|
|
13
12
|
value.type === "toml" ||
|
|
14
13
|
value.type === "yaml" ||
|
|
15
14
|
value.type === "nix";
|
|
16
|
-
|
|
17
|
-
if (needsJsonPath && !hasFieldPath) {
|
|
15
|
+
if (needsFieldPath && !value["field-path"]) {
|
|
18
16
|
ctx.addIssue({
|
|
19
17
|
code: z.ZodIssueCode.custom,
|
|
20
|
-
message: `${value.type} artifact rules require "field-path"
|
|
18
|
+
message: `${value.type} artifact rules require "field-path".`,
|
|
21
19
|
path: ["field-path"],
|
|
22
20
|
});
|
|
23
21
|
}
|
|
24
|
-
if (
|
|
22
|
+
if (needsFieldPath && value.pattern) {
|
|
25
23
|
ctx.addIssue({
|
|
26
24
|
code: z.ZodIssueCode.custom,
|
|
27
25
|
message: `${value.type} artifact rules do not support "pattern".`,
|
|
28
26
|
path: ["pattern"],
|
|
29
27
|
});
|
|
30
28
|
}
|
|
31
|
-
if (
|
|
29
|
+
if (needsFieldPath && value.replacement) {
|
|
32
30
|
ctx.addIssue({
|
|
33
31
|
code: z.ZodIssueCode.custom,
|
|
34
32
|
message: `${value.type} artifact rules do not support "replacement".`,
|
|
35
33
|
path: ["replacement"],
|
|
36
34
|
});
|
|
37
35
|
}
|
|
38
|
-
if (value["field-path"] && value.jsonpath) {
|
|
39
|
-
ctx.addIssue({
|
|
40
|
-
code: z.ZodIssueCode.custom,
|
|
41
|
-
message: 'Specify only one of "field-path" or deprecated "jsonpath".',
|
|
42
|
-
path: ["field-path"],
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
36
|
if (value.type === "regex" && !value.pattern) {
|
|
46
37
|
ctx.addIssue({
|
|
47
38
|
code: z.ZodIssueCode.custom,
|
|
@@ -49,10 +40,10 @@ const artifactRuleSchema = z
|
|
|
49
40
|
path: ["pattern"],
|
|
50
41
|
});
|
|
51
42
|
}
|
|
52
|
-
if (value.type === "regex" &&
|
|
43
|
+
if (value.type === "regex" && value["field-path"]) {
|
|
53
44
|
ctx.addIssue({
|
|
54
45
|
code: z.ZodIssueCode.custom,
|
|
55
|
-
message: 'regex artifact rules do not support "field-path"
|
|
46
|
+
message: 'regex artifact rules do not support "field-path".',
|
|
56
47
|
path: ["field-path"],
|
|
57
48
|
});
|
|
58
49
|
}
|
|
@@ -75,7 +66,7 @@ export const configSchema = z
|
|
|
75
66
|
.object({
|
|
76
67
|
$schema: z.string().optional(),
|
|
77
68
|
version: z.literal(1),
|
|
78
|
-
"review-mode": z.enum(["direct", "pr"
|
|
69
|
+
"review-mode": z.enum(["direct", "pr"]).optional(),
|
|
79
70
|
"version-file": z.string().optional(),
|
|
80
71
|
"changelog-file": z.string().optional(),
|
|
81
72
|
"changelog-format": z.enum(["markdown-changelog", "r-news"]).optional(),
|
|
@@ -85,7 +76,6 @@ export const configSchema = z
|
|
|
85
76
|
.optional(),
|
|
86
77
|
"release-branch": z.string().optional(),
|
|
87
78
|
"baseline-file": z.string().optional(),
|
|
88
|
-
"next-release-file": z.string().optional(),
|
|
89
79
|
"bootstrap-sha": z.string().optional(),
|
|
90
80
|
"monorepo-mode": z.enum(["independent", "fixed"]).optional(),
|
|
91
81
|
"bump-minor-pre-major": z.boolean().optional(),
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { VersionaryConfig } from "../types/config.js";
|
|
2
|
-
import type {
|
|
3
|
-
export declare function applyConfiguredArtifactRules(cwd: string, config: VersionaryConfig, plan:
|
|
2
|
+
import type { ReleasePlan } from "./plan.js";
|
|
3
|
+
export declare function applyConfiguredArtifactRules(cwd: string, config: VersionaryConfig, plan: ReleasePlan): string[];
|
|
@@ -143,9 +143,9 @@ function setVersionAtJsonPath(document, fieldPath, version) {
|
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
function resolveFieldPath(rule) {
|
|
146
|
-
const fieldPath = rule["field-path"]
|
|
146
|
+
const fieldPath = rule["field-path"];
|
|
147
147
|
if (!fieldPath) {
|
|
148
|
-
throw new Error(`${rule.type} artifact rules require "field-path"
|
|
148
|
+
throw new Error(`${rule.type} artifact rules require "field-path".`);
|
|
149
149
|
}
|
|
150
150
|
return fieldPath;
|
|
151
151
|
}
|
|
@@ -207,8 +207,8 @@ function applyRegexRule(content, pattern, version, replacementTemplate) {
|
|
|
207
207
|
const rendered = renderReplacementTemplate(replacementTemplate, version);
|
|
208
208
|
return `${content.slice(0, start)}${rendered}${content.slice(start + full.length)}`;
|
|
209
209
|
}
|
|
210
|
-
//
|
|
211
|
-
// leaving the rest of the match intact. Splice by group indices rather than
|
|
210
|
+
// Without a template: substitute the full version into the first capture
|
|
211
|
+
// group, leaving the rest of the match intact. Splice by group indices rather than
|
|
212
212
|
// `String.replace` so literal `$` sequences and repeated group content are
|
|
213
213
|
// handled correctly.
|
|
214
214
|
const groupIndices = match.indices?.[1];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ParsedCommit } from "../git/commits.js";
|
|
2
2
|
import type { VersionaryChangelogFormat } from "../types/config.js";
|
|
3
|
-
import { type ReleasePlan
|
|
3
|
+
import { type ReleasePlan } from "./plan.js";
|
|
4
4
|
export declare function renderReleaseNotesSection(input: {
|
|
5
5
|
currentVersion: string;
|
|
6
6
|
nextVersion: string;
|
|
@@ -23,8 +23,6 @@ export declare function renderReleasePlanChangelog(plan: ReleasePlan, options?:
|
|
|
23
23
|
cwd?: string;
|
|
24
24
|
highlights?: string;
|
|
25
25
|
}): string;
|
|
26
|
-
/** @deprecated Use renderReleasePlanChangelog. */
|
|
27
|
-
export declare function renderSimpleChangelog(plan: SimplePlan): string;
|
|
28
26
|
/**
|
|
29
27
|
* Locate a manual-notes block at the top of an existing changelog and split it
|
|
30
28
|
* out. The notes block is the first release-level heading whose text is not a
|
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { applyRevertSuppression, inferReleaseTypeFromParsedCommit, parseConventionalCommitMessage, } from "../git/commits.js";
|
|
4
4
|
import { resolveRepositoryWebBaseUrl } from "../git/repo-url.js";
|
|
5
|
-
import { resolvePackageDependencies, } from "./plan.js";
|
|
5
|
+
import { resolvePackageDependencies, resolveRootReleaseView, } from "./plan.js";
|
|
6
6
|
import { isVersionHeading } from "./semver.js";
|
|
7
7
|
const REVIEW_REQUEST_FOOTER = "---\n\nThis PR was generated by [Versionary](https://github.com/jolars/versionary).";
|
|
8
8
|
function formatDate() {
|
|
@@ -68,6 +68,7 @@ function groupCommitLines(commits, repoUrl) {
|
|
|
68
68
|
const fixes = [];
|
|
69
69
|
const performance = [];
|
|
70
70
|
const reverts = [];
|
|
71
|
+
const other = [];
|
|
71
72
|
const effectiveCommits = applyRevertSuppression(commits);
|
|
72
73
|
const getRevertedSubject = (commit) => {
|
|
73
74
|
const normalizedDescription = (commit.description ?? "")
|
|
@@ -93,9 +94,6 @@ function groupCommitLines(commits, repoUrl) {
|
|
|
93
94
|
};
|
|
94
95
|
for (const commit of effectiveCommits) {
|
|
95
96
|
const type = inferReleaseTypeFromParsedCommit(commit);
|
|
96
|
-
if (!type) {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
97
|
const { label, message } = formatCommitMessage(commit.subject);
|
|
100
98
|
const short = commit.hash.slice(0, 7);
|
|
101
99
|
const hashLabel = repoUrl
|
|
@@ -106,6 +104,10 @@ function groupCommitLines(commits, repoUrl) {
|
|
|
106
104
|
const line = `- ${label}${message} (${hashLabel})${referencesSuffix}`;
|
|
107
105
|
const commitType = (commit.type ?? "").toLowerCase();
|
|
108
106
|
const isBreaking = type === "major";
|
|
107
|
+
if (!type) {
|
|
108
|
+
other.push(line);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
109
111
|
if (commit.isRevert) {
|
|
110
112
|
if (!shouldIncludeRevert(commit)) {
|
|
111
113
|
continue;
|
|
@@ -128,7 +130,23 @@ function groupCommitLines(commits, repoUrl) {
|
|
|
128
130
|
fixes.push(line);
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
|
-
return { breaking, features, fixes, performance, reverts };
|
|
133
|
+
return { breaking, features, fixes, performance, reverts, other };
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* A forced bump — a stale dependency, or a propagated requirement rewrite —
|
|
137
|
+
* can carry no release-worthy commits at all. Rather than publish a bare
|
|
138
|
+
* version heading, such a release falls back to listing whatever else is
|
|
139
|
+
* shipping under it.
|
|
140
|
+
*/
|
|
141
|
+
function needsOtherChangesFallback(grouped, hasHighlights, dependencyCount) {
|
|
142
|
+
if (hasHighlights || dependencyCount > 0 || grouped.other.length === 0) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
return (grouped.breaking.length === 0 &&
|
|
146
|
+
grouped.features.length === 0 &&
|
|
147
|
+
grouped.fixes.length === 0 &&
|
|
148
|
+
grouped.performance.length === 0 &&
|
|
149
|
+
grouped.reverts.length === 0);
|
|
132
150
|
}
|
|
133
151
|
export function renderReleaseNotesSection(input, options = {}) {
|
|
134
152
|
const repoUrl = resolveRepositoryWebBaseUrl(input.cwd ?? process.cwd());
|
|
@@ -161,6 +179,9 @@ export function renderReleaseNotesSection(input, options = {}) {
|
|
|
161
179
|
if (input.dependencies && input.dependencies.length > 0) {
|
|
162
180
|
sections.push("### Dependencies", ...input.dependencies.map((dependency) => `- updated ${dependency.name} to v${dependency.version}`), "");
|
|
163
181
|
}
|
|
182
|
+
if (needsOtherChangesFallback(grouped, trimmedHighlights.length > 0, input.dependencies?.length ?? 0)) {
|
|
183
|
+
sections.push("### Other changes", ...grouped.other, "");
|
|
184
|
+
}
|
|
164
185
|
const body = [header, "", ...sections].join("\n").trimEnd();
|
|
165
186
|
if (options.includeFooter) {
|
|
166
187
|
return `${body}\n\n${renderReviewRequestFooter()}`;
|
|
@@ -171,24 +192,27 @@ export function renderReviewRequestFooter() {
|
|
|
171
192
|
return REVIEW_REQUEST_FOOTER;
|
|
172
193
|
}
|
|
173
194
|
export function renderReleasePlanChangelog(plan, options = {}) {
|
|
174
|
-
|
|
195
|
+
// Root's changelog describes root's own release, so it must be driven by the
|
|
196
|
+
// root package's version and commit set rather than the plan-level aggregate.
|
|
197
|
+
const root = resolveRootReleaseView(plan);
|
|
198
|
+
if (!root.nextVersion) {
|
|
175
199
|
return "";
|
|
176
200
|
}
|
|
177
201
|
const dedupedCommits = [
|
|
178
|
-
...new Map(
|
|
202
|
+
...new Map(root.commits.map((commit) => [commit.hash, commit])).values(),
|
|
179
203
|
];
|
|
180
204
|
if (plan.changelogFormat === "r-news") {
|
|
181
205
|
return renderRNewsReleaseNotes({
|
|
182
206
|
packageName: plan.packageName,
|
|
183
|
-
nextVersion:
|
|
207
|
+
nextVersion: root.nextVersion,
|
|
184
208
|
commits: dedupedCommits,
|
|
185
209
|
cwd: process.cwd(),
|
|
186
210
|
highlights: options.highlights,
|
|
187
211
|
});
|
|
188
212
|
}
|
|
189
213
|
return renderReleaseNotesSection({
|
|
190
|
-
currentVersion:
|
|
191
|
-
nextVersion:
|
|
214
|
+
currentVersion: root.currentVersion,
|
|
215
|
+
nextVersion: root.nextVersion,
|
|
192
216
|
commits: dedupedCommits,
|
|
193
217
|
cwd: options.cwd ?? process.cwd(),
|
|
194
218
|
dependencies: resolvePackageDependencies(plan, "."),
|
|
@@ -198,10 +222,6 @@ export function renderReleasePlanChangelog(plan, options = {}) {
|
|
|
198
222
|
includeFooter: options.includeFooter,
|
|
199
223
|
});
|
|
200
224
|
}
|
|
201
|
-
/** @deprecated Use renderReleasePlanChangelog. */
|
|
202
|
-
export function renderSimpleChangelog(plan) {
|
|
203
|
-
return renderReleasePlanChangelog(plan);
|
|
204
|
-
}
|
|
205
225
|
/**
|
|
206
226
|
* Locate a manual-notes block at the top of an existing changelog and split it
|
|
207
227
|
* out. The notes block is the first release-level heading whose text is not a
|
|
@@ -292,6 +312,9 @@ export function renderRNewsReleaseNotes(input) {
|
|
|
292
312
|
if (grouped.reverts.length > 0) {
|
|
293
313
|
sections.push("## Reverts", "", ...grouped.reverts, "");
|
|
294
314
|
}
|
|
315
|
+
if (needsOtherChangesFallback(grouped, trimmedHighlights.length > 0, 0)) {
|
|
316
|
+
sections.push("## Other changes", "", ...grouped.other, "");
|
|
317
|
+
}
|
|
295
318
|
return [`# ${input.packageName} ${normalizedVersion}`, "", ...sections]
|
|
296
319
|
.join("\n")
|
|
297
320
|
.trimEnd();
|
package/dist/release/plan.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ParsedCommit } from "../git/commits.js";
|
|
2
2
|
import type { VersionaryChangelogFormat, VersionaryConfig } from "../types/config.js";
|
|
3
3
|
import { type ReleaseType } from "./semver.js";
|
|
4
|
+
type BumpReason = "direct" | "dependency-propagation" | "stale-dependency" | "follows" | "release-as";
|
|
4
5
|
export interface ReleasePlan {
|
|
5
6
|
mode: "simple";
|
|
6
7
|
releaseType: ReleaseType;
|
|
@@ -18,13 +19,11 @@ export interface ReleasePlan {
|
|
|
18
19
|
releaseType: ReleaseType;
|
|
19
20
|
currentVersion: string;
|
|
20
21
|
nextVersion: string | null;
|
|
21
|
-
bumpReason?:
|
|
22
|
+
bumpReason?: BumpReason;
|
|
22
23
|
dependencySourcePaths?: string[];
|
|
23
24
|
commits: ParsedCommit[];
|
|
24
25
|
}>;
|
|
25
26
|
}
|
|
26
|
-
/** @deprecated Use ReleasePlan. */
|
|
27
|
-
export type SimplePlan = ReleasePlan;
|
|
28
27
|
export declare function getChangelogDefaults(config: {
|
|
29
28
|
"release-type"?: VersionaryConfig["release-type"];
|
|
30
29
|
"changelog-file"?: VersionaryConfig["changelog-file"];
|
|
@@ -35,9 +34,30 @@ export declare function getChangelogDefaults(config: {
|
|
|
35
34
|
changelogFormat: VersionaryChangelogFormat;
|
|
36
35
|
};
|
|
37
36
|
export declare function createReleasePlan(cwd?: string): ReleasePlan;
|
|
38
|
-
/**
|
|
39
|
-
|
|
37
|
+
/**
|
|
38
|
+
* The root package's own release, as distinct from the plan-level aggregate.
|
|
39
|
+
*
|
|
40
|
+
* `plan.releaseType`/`plan.nextVersion`/`plan.commits` describe the repository
|
|
41
|
+
* as a whole: the aggregate release type folds in every package's commits and
|
|
42
|
+
* is then applied to root's version number. That answers "is anything
|
|
43
|
+
* releasing, and how large is the biggest change anywhere" — not "what is root
|
|
44
|
+
* releasing". A sibling's `feat` therefore lifts the aggregate to a minor even
|
|
45
|
+
* when root's own `exclude-paths` drop that commit, so anything that names or
|
|
46
|
+
* describes root's release must go through here instead. Using the aggregate
|
|
47
|
+
* would report a version no version file carries and list commits root
|
|
48
|
+
* deliberately excluded.
|
|
49
|
+
*
|
|
50
|
+
* Falls back to the aggregate when the plan has no explicit root package: the
|
|
51
|
+
* top-level changelog is then a repository-wide summary with no package of its
|
|
52
|
+
* own to describe.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveRootReleaseView(plan: ReleasePlan): {
|
|
55
|
+
currentVersion: string;
|
|
56
|
+
nextVersion: string | null;
|
|
57
|
+
commits: ParsedCommit[];
|
|
58
|
+
};
|
|
40
59
|
export declare function resolvePackageDependencies(plan: ReleasePlan, packagePath: string): Array<{
|
|
41
60
|
name: string;
|
|
42
61
|
version: string;
|
|
43
62
|
}>;
|
|
63
|
+
export {};
|