versionary 0.20.2 → 0.22.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/dist/cli/index.js +10 -3
- package/dist/config/schema.d.ts +1 -0
- package/dist/config/schema.js +1 -0
- package/dist/release/artifact-rules.js +83 -32
- package/dist/release/changelog.d.ts +3 -0
- package/dist/release/changelog.js +10 -0
- package/dist/release/pr.d.ts +13 -1
- package/dist/release/pr.js +52 -3
- package/dist/types/config.d.ts +1 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const node_child_process_1 = require("node:child_process");
|
|
5
|
+
const load_config_js_1 = require("../config/load-config.js");
|
|
5
6
|
const changelog_js_1 = require("../release/changelog.js");
|
|
6
7
|
const plan_js_1 = require("../release/plan.js");
|
|
7
8
|
const pr_js_1 = require("../release/pr.js");
|
|
@@ -162,7 +163,7 @@ async function main() {
|
|
|
162
163
|
return 0;
|
|
163
164
|
}
|
|
164
165
|
(0, pr_js_1.pushReleaseBranch)(process.cwd(), pr.branch);
|
|
165
|
-
const reviewResult = await (0, pr_js_1.openOrUpdateReviewRequest)(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan, { logger });
|
|
166
|
+
const reviewResult = await (0, pr_js_1.openOrUpdateReviewRequest)(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan, { logger, highlights: pr.highlights });
|
|
166
167
|
const message = `Prepared release PR branch ${pr.branch}`;
|
|
167
168
|
if (flags.json) {
|
|
168
169
|
emitJson({
|
|
@@ -196,12 +197,18 @@ async function main() {
|
|
|
196
197
|
console.log("No releasable commits found.");
|
|
197
198
|
return 0;
|
|
198
199
|
}
|
|
199
|
-
const
|
|
200
|
+
const loaded = (0, load_config_js_1.loadConfig)();
|
|
201
|
+
const highlightsRead = (0, pr_js_1.readNextReleaseHighlights)(process.cwd(), loaded.config);
|
|
202
|
+
const highlights = highlightsRead?.content ?? "";
|
|
203
|
+
const section = (0, changelog_js_1.renderReleasePlanChangelog)(plan, { highlights });
|
|
200
204
|
if (!write) {
|
|
201
205
|
console.log(section);
|
|
202
206
|
return 0;
|
|
203
207
|
}
|
|
204
208
|
(0, changelog_js_1.prependChangelog)(process.cwd(), plan.changelogFile, section, plan.changelogFormat);
|
|
209
|
+
if (highlightsRead) {
|
|
210
|
+
(0, pr_js_1.consumeNextReleaseFile)(process.cwd(), highlightsRead.filePath);
|
|
211
|
+
}
|
|
205
212
|
console.log(`Updated ${plan.changelogFile}`);
|
|
206
213
|
return 0;
|
|
207
214
|
}
|
|
@@ -227,7 +234,7 @@ async function main() {
|
|
|
227
234
|
return 0;
|
|
228
235
|
}
|
|
229
236
|
(0, pr_js_1.pushReleaseBranch)(process.cwd(), pr.branch);
|
|
230
|
-
const reviewResult = await (0, pr_js_1.openOrUpdateReviewRequest)(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan);
|
|
237
|
+
const reviewResult = await (0, pr_js_1.openOrUpdateReviewRequest)(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan, { highlights: pr.highlights });
|
|
231
238
|
console.log(`Prepared release PR branch ${pr.branch}`);
|
|
232
239
|
console.log(`Title: ${pr.title}`);
|
|
233
240
|
console.log(reviewResult);
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export declare const configSchema: z.ZodObject<{
|
|
|
21
21
|
}>>;
|
|
22
22
|
"release-branch": z.ZodOptional<z.ZodString>;
|
|
23
23
|
"baseline-file": z.ZodOptional<z.ZodString>;
|
|
24
|
+
"next-release-file": z.ZodOptional<z.ZodString>;
|
|
24
25
|
"bootstrap-sha": z.ZodOptional<z.ZodString>;
|
|
25
26
|
"monorepo-mode": z.ZodOptional<z.ZodEnum<{
|
|
26
27
|
independent: "independent";
|
package/dist/config/schema.js
CHANGED
|
@@ -76,6 +76,7 @@ exports.configSchema = zod_1.z
|
|
|
76
76
|
.optional(),
|
|
77
77
|
"release-branch": zod_1.z.string().optional(),
|
|
78
78
|
"baseline-file": zod_1.z.string().optional(),
|
|
79
|
+
"next-release-file": zod_1.z.string().optional(),
|
|
79
80
|
"bootstrap-sha": zod_1.z.string().optional(),
|
|
80
81
|
"monorepo-mode": zod_1.z.enum(["independent", "fixed"]).optional(),
|
|
81
82
|
"bump-minor-pre-major": zod_1.z.boolean().optional(),
|
|
@@ -8,6 +8,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const toml_1 = __importDefault(require("@iarna/toml"));
|
|
10
10
|
const yaml_1 = __importDefault(require("yaml"));
|
|
11
|
+
const WILDCARD = Symbol("wildcard");
|
|
11
12
|
function isRecord(value) {
|
|
12
13
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
13
14
|
}
|
|
@@ -20,7 +21,12 @@ function parseFieldPath(fieldPath) {
|
|
|
20
21
|
while (index < fieldPath.length) {
|
|
21
22
|
const current = fieldPath[index];
|
|
22
23
|
if (current === ".") {
|
|
23
|
-
|
|
24
|
+
if (fieldPath[index + 1] === "*") {
|
|
25
|
+
tokens.push(WILDCARD);
|
|
26
|
+
index += 2;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const keyMatch = fieldPath.slice(index + 1).match(/^[A-Za-z0-9_@/-]+/u);
|
|
24
30
|
if (!keyMatch) {
|
|
25
31
|
throw new Error(`Invalid field-path "${fieldPath}" near index ${index}.`);
|
|
26
32
|
}
|
|
@@ -30,6 +36,11 @@ function parseFieldPath(fieldPath) {
|
|
|
30
36
|
}
|
|
31
37
|
if (current === "[") {
|
|
32
38
|
const rest = fieldPath.slice(index + 1);
|
|
39
|
+
if (rest.startsWith("*]")) {
|
|
40
|
+
tokens.push(WILDCARD);
|
|
41
|
+
index += 3;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
33
44
|
const numberMatch = rest.match(/^(\d+)\]/u);
|
|
34
45
|
if (numberMatch) {
|
|
35
46
|
tokens.push(Number(numberMatch[1]));
|
|
@@ -55,49 +66,86 @@ function parseFieldPath(fieldPath) {
|
|
|
55
66
|
}
|
|
56
67
|
return tokens;
|
|
57
68
|
}
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
for (let index = 0; index < tokens.length - 1; index += 1) {
|
|
62
|
-
const token = tokens[index];
|
|
63
|
-
if (token === undefined) {
|
|
69
|
+
function assignLeaf(container, key, fieldPath, version) {
|
|
70
|
+
if (typeof key === "number") {
|
|
71
|
+
if (!Array.isArray(container) || key >= container.length) {
|
|
64
72
|
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
65
73
|
}
|
|
66
|
-
|
|
67
|
-
if (!Array.isArray(cursor) || token >= cursor.length) {
|
|
68
|
-
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
69
|
-
}
|
|
70
|
-
cursor = cursor[token];
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
if (!isRecord(cursor) || !(token in cursor)) {
|
|
74
|
-
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
75
|
-
}
|
|
76
|
-
cursor = cursor[token];
|
|
77
|
-
}
|
|
78
|
-
const leaf = tokens.at(-1);
|
|
79
|
-
if (leaf === undefined) {
|
|
80
|
-
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
81
|
-
}
|
|
82
|
-
if (typeof leaf === "number") {
|
|
83
|
-
if (!Array.isArray(cursor) || leaf >= cursor.length) {
|
|
84
|
-
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
85
|
-
}
|
|
86
|
-
const current = cursor[leaf];
|
|
74
|
+
const current = container[key];
|
|
87
75
|
if (typeof current !== "string" && typeof current !== "number") {
|
|
88
76
|
throw new Error(`field-path "${fieldPath}" must point to a string or number field for version updates.`);
|
|
89
77
|
}
|
|
90
|
-
|
|
78
|
+
container[key] = version;
|
|
91
79
|
return;
|
|
92
80
|
}
|
|
93
|
-
if (!isRecord(
|
|
81
|
+
if (!isRecord(container) || !(key in container)) {
|
|
94
82
|
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
95
83
|
}
|
|
96
|
-
const current =
|
|
84
|
+
const current = container[key];
|
|
97
85
|
if (typeof current !== "string" && typeof current !== "number") {
|
|
98
86
|
throw new Error(`field-path "${fieldPath}" must point to a string or number field for version updates.`);
|
|
99
87
|
}
|
|
100
|
-
|
|
88
|
+
container[key] = version;
|
|
89
|
+
}
|
|
90
|
+
function applyTokens(cursor, tokens, position, fieldPath, version) {
|
|
91
|
+
const token = tokens[position];
|
|
92
|
+
const isLeaf = position === tokens.length - 1;
|
|
93
|
+
if (token === WILDCARD) {
|
|
94
|
+
let matched = false;
|
|
95
|
+
if (isRecord(cursor)) {
|
|
96
|
+
for (const key of Object.keys(cursor)) {
|
|
97
|
+
if (isLeaf) {
|
|
98
|
+
assignLeaf(cursor, key, fieldPath, version);
|
|
99
|
+
matched = true;
|
|
100
|
+
}
|
|
101
|
+
else if (applyTokens(cursor[key], tokens, position + 1, fieldPath, version)) {
|
|
102
|
+
matched = true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return matched;
|
|
106
|
+
}
|
|
107
|
+
if (Array.isArray(cursor)) {
|
|
108
|
+
for (let i = 0; i < cursor.length; i += 1) {
|
|
109
|
+
if (isLeaf) {
|
|
110
|
+
assignLeaf(cursor, i, fieldPath, version);
|
|
111
|
+
matched = true;
|
|
112
|
+
}
|
|
113
|
+
else if (applyTokens(cursor[i], tokens, position + 1, fieldPath, version)) {
|
|
114
|
+
matched = true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return matched;
|
|
118
|
+
}
|
|
119
|
+
throw new Error(`field-path "${fieldPath}" wildcard segment does not target an object or array.`);
|
|
120
|
+
}
|
|
121
|
+
if (typeof token === "number") {
|
|
122
|
+
if (!Array.isArray(cursor) || token >= cursor.length) {
|
|
123
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
124
|
+
}
|
|
125
|
+
if (isLeaf) {
|
|
126
|
+
assignLeaf(cursor, token, fieldPath, version);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
return applyTokens(cursor[token], tokens, position + 1, fieldPath, version);
|
|
130
|
+
}
|
|
131
|
+
if (typeof token === "string") {
|
|
132
|
+
if (!isRecord(cursor) || !(token in cursor)) {
|
|
133
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
134
|
+
}
|
|
135
|
+
if (isLeaf) {
|
|
136
|
+
assignLeaf(cursor, token, fieldPath, version);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
return applyTokens(cursor[token], tokens, position + 1, fieldPath, version);
|
|
140
|
+
}
|
|
141
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
142
|
+
}
|
|
143
|
+
function setVersionAtJsonPath(document, fieldPath, version) {
|
|
144
|
+
const tokens = parseFieldPath(fieldPath);
|
|
145
|
+
const matched = applyTokens(document, tokens, 0, fieldPath, version);
|
|
146
|
+
if (!matched) {
|
|
147
|
+
throw new Error(`field-path "${fieldPath}" did not match any fields.`);
|
|
148
|
+
}
|
|
101
149
|
}
|
|
102
150
|
function resolveFieldPath(rule) {
|
|
103
151
|
const fieldPath = rule["field-path"] ?? rule.jsonpath;
|
|
@@ -232,6 +280,9 @@ function findMatchingBrace(content, openBraceIndex, endExclusive) {
|
|
|
232
280
|
}
|
|
233
281
|
function resolveNixPathTokens(fieldPath) {
|
|
234
282
|
const tokens = parseFieldPath(fieldPath);
|
|
283
|
+
if (tokens.some((token) => token === WILDCARD)) {
|
|
284
|
+
throw new Error(`Nix artifact rules do not support wildcard segments in field-path "${fieldPath}".`);
|
|
285
|
+
}
|
|
235
286
|
if (tokens.some((token) => typeof token === "number")) {
|
|
236
287
|
throw new Error(`Nix artifact rules do not support array index segments in field-path "${fieldPath}".`);
|
|
237
288
|
}
|
|
@@ -10,6 +10,7 @@ export declare function renderSimpleReleaseNotes(input: {
|
|
|
10
10
|
name: string;
|
|
11
11
|
version: string;
|
|
12
12
|
}>;
|
|
13
|
+
highlights?: string;
|
|
13
14
|
}, options?: {
|
|
14
15
|
includeFooter?: boolean;
|
|
15
16
|
headerLabel?: string;
|
|
@@ -19,6 +20,7 @@ export declare function renderReleasePlanChangelog(plan: ReleasePlan, options?:
|
|
|
19
20
|
headerLabel?: string;
|
|
20
21
|
includeFooter?: boolean;
|
|
21
22
|
cwd?: string;
|
|
23
|
+
highlights?: string;
|
|
22
24
|
}): string;
|
|
23
25
|
/** @deprecated Use renderReleasePlanChangelog. */
|
|
24
26
|
export declare function renderSimpleChangelog(plan: SimplePlan): string;
|
|
@@ -35,4 +37,5 @@ export declare function renderRNewsReleaseNotes(input: {
|
|
|
35
37
|
nextVersion: string;
|
|
36
38
|
commits: ParsedCommit[];
|
|
37
39
|
cwd?: string;
|
|
40
|
+
highlights?: string;
|
|
38
41
|
}): string;
|
|
@@ -148,6 +148,10 @@ function renderSimpleReleaseNotes(input, options = {}) {
|
|
|
148
148
|
: `## ${headerLabel} (${formatDate()})`;
|
|
149
149
|
const grouped = groupCommitLines(input.commits, repoUrl);
|
|
150
150
|
const sections = [];
|
|
151
|
+
const trimmedHighlights = input.highlights?.trim() ?? "";
|
|
152
|
+
if (trimmedHighlights.length > 0) {
|
|
153
|
+
sections.push(trimmedHighlights, "");
|
|
154
|
+
}
|
|
151
155
|
if (grouped.breaking.length > 0) {
|
|
152
156
|
sections.push("### Breaking changes", ...grouped.breaking, "");
|
|
153
157
|
}
|
|
@@ -212,6 +216,7 @@ function renderReleasePlanChangelog(plan, options = {}) {
|
|
|
212
216
|
nextVersion: plan.nextVersion,
|
|
213
217
|
commits: dedupedCommits,
|
|
214
218
|
cwd: process.cwd(),
|
|
219
|
+
highlights: options.highlights,
|
|
215
220
|
});
|
|
216
221
|
}
|
|
217
222
|
return renderSimpleReleaseNotes({
|
|
@@ -220,6 +225,7 @@ function renderReleasePlanChangelog(plan, options = {}) {
|
|
|
220
225
|
commits: dedupedCommits,
|
|
221
226
|
cwd: options.cwd ?? process.cwd(),
|
|
222
227
|
dependencies,
|
|
228
|
+
highlights: options.highlights,
|
|
223
229
|
}, {
|
|
224
230
|
includeFooter: options.includeFooter,
|
|
225
231
|
headerLabel: options.headerLabel,
|
|
@@ -276,6 +282,10 @@ function renderRNewsReleaseNotes(input) {
|
|
|
276
282
|
const grouped = groupCommitLines(input.commits, repoUrl);
|
|
277
283
|
const normalizedVersion = input.nextVersion.replace(/\.\d+$/u, "");
|
|
278
284
|
const sections = [];
|
|
285
|
+
const trimmedHighlights = input.highlights?.trim() ?? "";
|
|
286
|
+
if (trimmedHighlights.length > 0) {
|
|
287
|
+
sections.push(trimmedHighlights, "");
|
|
288
|
+
}
|
|
279
289
|
if (grouped.breaking.length > 0) {
|
|
280
290
|
sections.push("## Breaking changes", "", ...grouped.breaking, "");
|
|
281
291
|
}
|
package/dist/release/pr.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { ParsedCommit } from "../git/commits.js";
|
|
2
|
+
import type { VersionaryConfig } from "../types/config.js";
|
|
2
3
|
import type { VersionaryPluginContext } from "../types/plugins.js";
|
|
3
4
|
import { type ReleasePlan, type SimplePlan } from "./plan.js";
|
|
5
|
+
export declare function getNextReleaseFile(config: VersionaryConfig): string;
|
|
6
|
+
export declare function readNextReleaseHighlights(cwd: string, config: VersionaryConfig): {
|
|
7
|
+
content: string;
|
|
8
|
+
filePath: string;
|
|
9
|
+
} | null;
|
|
10
|
+
export declare function consumeNextReleaseFile(cwd: string, filePath: string): {
|
|
11
|
+
tracked: boolean;
|
|
12
|
+
};
|
|
4
13
|
export declare function splitSafeDirtyFiles(files: string[]): {
|
|
5
14
|
ignored: string[];
|
|
6
15
|
blocking: string[];
|
|
@@ -15,10 +24,12 @@ export declare function prepareReleasePr(cwd?: string, options?: {
|
|
|
15
24
|
commits: ParsedCommit[];
|
|
16
25
|
plan: ReleasePlan;
|
|
17
26
|
updated: boolean;
|
|
27
|
+
highlights: string;
|
|
18
28
|
};
|
|
19
|
-
export declare function renderSimpleReviewRequestBody(version: string, previousVersion: string, commits: ParsedCommit[], plan?: SimplePlan | null, cwd?: string): string;
|
|
29
|
+
export declare function renderSimpleReviewRequestBody(version: string, previousVersion: string, commits: ParsedCommit[], plan?: SimplePlan | null, cwd?: string, highlights?: string): string;
|
|
20
30
|
export declare function openOrUpdateReviewRequest(cwd: string, branch: string, title: string, version: string, previousVersion: string, commits: ParsedCommit[], plan?: SimplePlan | null, options?: {
|
|
21
31
|
logger?: VersionaryPluginContext["logger"];
|
|
32
|
+
highlights?: string;
|
|
22
33
|
}): Promise<string>;
|
|
23
34
|
export declare function closeStaleReviewRequestIfExists(cwd?: string, options?: {
|
|
24
35
|
logger?: VersionaryPluginContext["logger"];
|
|
@@ -34,6 +45,7 @@ export declare function prepareSimpleReleasePr(cwd?: string, options?: {
|
|
|
34
45
|
/** @deprecated Use openOrUpdateReviewRequest. */
|
|
35
46
|
export declare function openOrUpdateSimpleReviewRequest(cwd: string, branch: string, title: string, version: string, previousVersion: string, commits: ParsedCommit[], plan?: SimplePlan | null, options?: {
|
|
36
47
|
logger?: VersionaryPluginContext["logger"];
|
|
48
|
+
highlights?: string;
|
|
37
49
|
}): Promise<string>;
|
|
38
50
|
export declare function pushReleaseBranch(cwd: string, branch: string): void;
|
|
39
51
|
export declare function isReleaseCommitMessage(commitMessage: string): boolean;
|
package/dist/release/pr.js
CHANGED
|
@@ -3,6 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getNextReleaseFile = getNextReleaseFile;
|
|
7
|
+
exports.readNextReleaseHighlights = readNextReleaseHighlights;
|
|
8
|
+
exports.consumeNextReleaseFile = consumeNextReleaseFile;
|
|
6
9
|
exports.splitSafeDirtyFiles = splitSafeDirtyFiles;
|
|
7
10
|
exports.prepareReleasePr = prepareReleasePr;
|
|
8
11
|
exports.renderSimpleReviewRequestBody = renderSimpleReviewRequestBody;
|
|
@@ -13,6 +16,7 @@ exports.openOrUpdateSimpleReviewRequest = openOrUpdateSimpleReviewRequest;
|
|
|
13
16
|
exports.pushReleaseBranch = pushReleaseBranch;
|
|
14
17
|
exports.isReleaseCommitMessage = isReleaseCommitMessage;
|
|
15
18
|
const node_child_process_1 = require("node:child_process");
|
|
19
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
16
20
|
const node_path_1 = __importDefault(require("node:path"));
|
|
17
21
|
const load_config_js_1 = require("../config/load-config.js");
|
|
18
22
|
const client_js_1 = require("../scm/client.js");
|
|
@@ -29,6 +33,38 @@ const SAFE_DIRTY_FILES = new Set([
|
|
|
29
33
|
"npm-shrinkwrap.json",
|
|
30
34
|
]);
|
|
31
35
|
const VERSIONARY_RELEASE_TRAILER = "Versionary-Release: true";
|
|
36
|
+
function getNextReleaseFile(config) {
|
|
37
|
+
return config["next-release-file"] ?? "NEXT_RELEASE.md";
|
|
38
|
+
}
|
|
39
|
+
function readNextReleaseHighlights(cwd, config) {
|
|
40
|
+
const filePath = getNextReleaseFile(config);
|
|
41
|
+
const fullPath = node_path_1.default.join(cwd, filePath);
|
|
42
|
+
if (!node_fs_1.default.existsSync(fullPath)) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const content = node_fs_1.default.readFileSync(fullPath, "utf8").trim();
|
|
46
|
+
return { content, filePath };
|
|
47
|
+
}
|
|
48
|
+
function isTrackedFile(cwd, filePath) {
|
|
49
|
+
try {
|
|
50
|
+
(0, node_child_process_1.execFileSync)("git", ["ls-files", "--error-unmatch", "--", filePath], {
|
|
51
|
+
cwd,
|
|
52
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
53
|
+
});
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function consumeNextReleaseFile(cwd, filePath) {
|
|
61
|
+
const tracked = isTrackedFile(cwd, filePath);
|
|
62
|
+
const fullPath = node_path_1.default.join(cwd, filePath);
|
|
63
|
+
if (node_fs_1.default.existsSync(fullPath)) {
|
|
64
|
+
node_fs_1.default.rmSync(fullPath);
|
|
65
|
+
}
|
|
66
|
+
return { tracked };
|
|
67
|
+
}
|
|
32
68
|
function listTrackedDirtyFiles(cwd) {
|
|
33
69
|
const status = (0, node_child_process_1.execFileSync)("git", ["status", "--porcelain", "--untracked-files=no"], {
|
|
34
70
|
cwd,
|
|
@@ -251,9 +287,18 @@ function prepareReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
251
287
|
}
|
|
252
288
|
const updatedArtifactFiles = (0, artifact_rules_js_1.applyConfiguredArtifactRules)(cwd, loaded.config, plan);
|
|
253
289
|
const packageReleaseMetadata = buildPackageReleaseMetadata(cwd, plan, loaded.config);
|
|
254
|
-
const
|
|
290
|
+
const nextReleaseRead = readNextReleaseHighlights(cwd, loaded.config);
|
|
291
|
+
const highlights = nextReleaseRead?.content ?? "";
|
|
292
|
+
const section = (0, changelog_js_1.renderReleasePlanChangelog)(plan, { highlights, cwd });
|
|
255
293
|
(0, changelog_js_1.prependChangelog)(cwd, plan.changelogFile, section, plan.changelogFormat);
|
|
256
294
|
const updatedChangelogFiles = [plan.changelogFile];
|
|
295
|
+
let consumedHighlightsPath = null;
|
|
296
|
+
if (nextReleaseRead) {
|
|
297
|
+
const { tracked } = consumeNextReleaseFile(cwd, nextReleaseRead.filePath);
|
|
298
|
+
if (tracked) {
|
|
299
|
+
consumedHighlightsPath = nextReleaseRead.filePath;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
257
302
|
for (const packagePlan of plan.packages ?? []) {
|
|
258
303
|
if (!packagePlan.nextVersion || packagePlan.path === ".") {
|
|
259
304
|
continue;
|
|
@@ -296,6 +341,7 @@ function prepareReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
296
341
|
...updatedVersionFiles,
|
|
297
342
|
...updatedArtifactFiles,
|
|
298
343
|
...updatedChangelogFiles,
|
|
344
|
+
...(consumedHighlightsPath ? [consumedHighlightsPath] : []),
|
|
299
345
|
]),
|
|
300
346
|
];
|
|
301
347
|
(0, node_child_process_1.execFileSync)("git", ["add", ...filesToAdd], {
|
|
@@ -325,9 +371,10 @@ function prepareReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
325
371
|
commits: plan.commits,
|
|
326
372
|
plan,
|
|
327
373
|
updated,
|
|
374
|
+
highlights,
|
|
328
375
|
};
|
|
329
376
|
}
|
|
330
|
-
function renderSimpleReviewRequestBody(version, previousVersion, commits, plan = null, cwd = process.cwd()) {
|
|
377
|
+
function renderSimpleReviewRequestBody(version, previousVersion, commits, plan = null, cwd = process.cwd(), highlights = "") {
|
|
331
378
|
const rootPackageLabel = node_path_1.default.basename(cwd);
|
|
332
379
|
const formatPackageLabel = (packagePath) => packagePath === "." ? rootPackageLabel : packagePath;
|
|
333
380
|
const isDirectBump = (pkg) => pkg.bumpReason === "direct" ||
|
|
@@ -361,6 +408,7 @@ function renderSimpleReviewRequestBody(version, previousVersion, commits, plan =
|
|
|
361
408
|
const rootNotes = (0, changelog_js_1.renderReleasePlanChangelog)(plan, {
|
|
362
409
|
headerLabel: `${formatPackageLabel(".")}: ${rootPackage.nextVersion}`,
|
|
363
410
|
cwd,
|
|
411
|
+
highlights,
|
|
364
412
|
});
|
|
365
413
|
sections.push(rootNotes);
|
|
366
414
|
}
|
|
@@ -393,6 +441,7 @@ function renderSimpleReviewRequestBody(version, previousVersion, commits, plan =
|
|
|
393
441
|
nextVersion: version,
|
|
394
442
|
commits,
|
|
395
443
|
cwd,
|
|
444
|
+
highlights,
|
|
396
445
|
}, { includeFooter: true });
|
|
397
446
|
}
|
|
398
447
|
async function openOrUpdateReviewRequest(cwd, branch, title, version, previousVersion, commits, plan = null, options = {}) {
|
|
@@ -406,7 +455,7 @@ async function openOrUpdateReviewRequest(cwd, branch, title, version, previousVe
|
|
|
406
455
|
baseBranch: process.env.VERSIONARY_BASE_BRANCH ?? "main",
|
|
407
456
|
headBranch: branch,
|
|
408
457
|
title,
|
|
409
|
-
body: renderSimpleReviewRequestBody(version, previousVersion, commits, plan, cwd),
|
|
458
|
+
body: renderSimpleReviewRequestBody(version, previousVersion, commits, plan, cwd, options.highlights ?? ""),
|
|
410
459
|
labels: ["release"],
|
|
411
460
|
}, {
|
|
412
461
|
cwd,
|
package/dist/types/config.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface VersionaryConfig {
|
|
|
26
26
|
"release-reference-comments"?: ReleaseReferenceCommentsMode;
|
|
27
27
|
"release-branch"?: string;
|
|
28
28
|
"baseline-file"?: string;
|
|
29
|
+
"next-release-file"?: string;
|
|
29
30
|
"bootstrap-sha"?: string;
|
|
30
31
|
"monorepo-mode"?: "independent" | "fixed";
|
|
31
32
|
"bump-minor-pre-major"?: boolean;
|