versionary 0.12.0 → 0.14.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/README.md +8 -2
- package/dist/cli/index.js +15 -15
- package/dist/config/schema.d.ts +5 -0
- package/dist/config/schema.js +3 -0
- package/dist/index.d.ts +2 -2
- package/dist/release/changelog.d.ts +3 -1
- package/dist/release/changelog.js +15 -6
- package/dist/release/plan.d.ts +6 -2
- package/dist/release/plan.js +6 -1
- package/dist/release/pr.d.ts +11 -3
- package/dist/release/pr.js +49 -25
- package/dist/release/release.d.ts +13 -3
- package/dist/release/release.js +108 -28
- package/dist/release/semver.js +14 -3
- package/dist/scm/github-plugin.js +38 -1
- package/dist/scm/types.d.ts +10 -0
- package/dist/types/config.d.ts +2 -0
- package/dist/types/plugins.d.ts +5 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,8 +86,10 @@ Current ecosystem policy defaults:
|
|
|
86
86
|
|
|
87
87
|
- changelog source for publish:
|
|
88
88
|
- root target uses root `changelog-file`
|
|
89
|
-
- package target uses
|
|
90
|
-
|
|
89
|
+
- package target uses package changelog defaults:
|
|
90
|
+
- `packages.<path>.changelog-file` when configured
|
|
91
|
+
- otherwise `NEWS.md` for R targets or `CHANGELOG.md` for other targets at
|
|
92
|
+
`<package-path>/<default-file>`
|
|
91
93
|
- lockfiles:
|
|
92
94
|
- Node strategy updates root `package-lock.json`/`npm-shrinkwrap.json` when
|
|
93
95
|
present
|
|
@@ -142,6 +144,10 @@ For a quick trial, use:
|
|
|
142
144
|
request)
|
|
143
145
|
- `release-draft` (default `false`) publishes GitHub releases as drafts when
|
|
144
146
|
enabled
|
|
147
|
+
- `release-reference-comments` controls release comments on linked issues/PRs:
|
|
148
|
+
- `off` (default): do not post comments
|
|
149
|
+
- `best-effort`: post comments and continue on API/permission failures
|
|
150
|
+
- `strict`: fail release if comment posting fails
|
|
145
151
|
- optional monorepo planning with `monorepo-mode` and `packages`:
|
|
146
152
|
- `independent` computes package bumps per path
|
|
147
153
|
- `fixed` computes one shared bump across configured package paths
|
package/dist/cli/index.js
CHANGED
|
@@ -52,7 +52,7 @@ async function main() {
|
|
|
52
52
|
}).trim();
|
|
53
53
|
if ((0, pr_js_1.isReleaseCommitMessage)(commitMessage)) {
|
|
54
54
|
if (flags["dry-run"] && !flags.json) {
|
|
55
|
-
const release = await (0, release_js_1.
|
|
55
|
+
const release = await (0, release_js_1.runReleaseDetailed)(process.cwd(), {
|
|
56
56
|
logger,
|
|
57
57
|
"dry-run": true,
|
|
58
58
|
});
|
|
@@ -62,7 +62,7 @@ async function main() {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
if (flags.json) {
|
|
65
|
-
const release = await (0, release_js_1.
|
|
65
|
+
const release = await (0, release_js_1.runReleaseDetailed)(process.cwd(), {
|
|
66
66
|
logger,
|
|
67
67
|
"dry-run": flags["dry-run"],
|
|
68
68
|
});
|
|
@@ -93,11 +93,11 @@ async function main() {
|
|
|
93
93
|
});
|
|
94
94
|
return 0;
|
|
95
95
|
}
|
|
96
|
-
const message = await (0, release_js_1.
|
|
96
|
+
const message = await (0, release_js_1.runRelease)(process.cwd());
|
|
97
97
|
console.log(message);
|
|
98
98
|
return 0;
|
|
99
99
|
}
|
|
100
|
-
const plan = (0, plan_js_1.
|
|
100
|
+
const plan = (0, plan_js_1.createReleasePlan)();
|
|
101
101
|
if (!plan.nextVersion) {
|
|
102
102
|
const message = "No releasable commits found. Nothing to do.";
|
|
103
103
|
if (flags.json) {
|
|
@@ -140,9 +140,9 @@ async function main() {
|
|
|
140
140
|
console.log(dryRunMessage);
|
|
141
141
|
return 0;
|
|
142
142
|
}
|
|
143
|
-
const pr = (0, pr_js_1.
|
|
143
|
+
const pr = (0, pr_js_1.prepareReleasePr)(process.cwd(), { logger });
|
|
144
144
|
(0, pr_js_1.pushReleaseBranch)(process.cwd(), pr.branch);
|
|
145
|
-
const reviewResult = await (0, pr_js_1.
|
|
145
|
+
const reviewResult = await (0, pr_js_1.openOrUpdateReviewRequest)(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan, { logger });
|
|
146
146
|
const message = `Prepared release PR branch ${pr.branch}`;
|
|
147
147
|
if (flags.json) {
|
|
148
148
|
emitJson({
|
|
@@ -165,18 +165,18 @@ async function main() {
|
|
|
165
165
|
return printVerifyResult();
|
|
166
166
|
}
|
|
167
167
|
if (command === "plan") {
|
|
168
|
-
const plan = (0, plan_js_1.
|
|
168
|
+
const plan = (0, plan_js_1.createReleasePlan)();
|
|
169
169
|
console.log(JSON.stringify(plan, null, 2));
|
|
170
170
|
return 0;
|
|
171
171
|
}
|
|
172
172
|
if (command === "changelog") {
|
|
173
173
|
const write = args.includes("--write");
|
|
174
|
-
const plan = (0, plan_js_1.
|
|
174
|
+
const plan = (0, plan_js_1.createReleasePlan)();
|
|
175
175
|
if (!plan.nextVersion) {
|
|
176
176
|
console.log("No releasable commits found.");
|
|
177
177
|
return 0;
|
|
178
178
|
}
|
|
179
|
-
const section = (0, changelog_js_1.
|
|
179
|
+
const section = (0, changelog_js_1.renderReleasePlanChangelog)(plan);
|
|
180
180
|
if (!write) {
|
|
181
181
|
console.log(section);
|
|
182
182
|
return 0;
|
|
@@ -187,7 +187,7 @@ async function main() {
|
|
|
187
187
|
}
|
|
188
188
|
if (command === "pr") {
|
|
189
189
|
if (flags["dry-run"]) {
|
|
190
|
-
const plan = (0, plan_js_1.
|
|
190
|
+
const plan = (0, plan_js_1.createReleasePlan)();
|
|
191
191
|
if (!plan.nextVersion) {
|
|
192
192
|
console.log("No releasable commits found. Nothing to do.");
|
|
193
193
|
return 0;
|
|
@@ -195,9 +195,9 @@ async function main() {
|
|
|
195
195
|
console.log(`Dry run: would prepare release PR branch ${plan.releaseBranchPrefix} for ${plan.nextVersion}`);
|
|
196
196
|
return 0;
|
|
197
197
|
}
|
|
198
|
-
const pr = (0, pr_js_1.
|
|
198
|
+
const pr = (0, pr_js_1.prepareReleasePr)(process.cwd(), { logger: console });
|
|
199
199
|
(0, pr_js_1.pushReleaseBranch)(process.cwd(), pr.branch);
|
|
200
|
-
const reviewResult = await (0, pr_js_1.
|
|
200
|
+
const reviewResult = await (0, pr_js_1.openOrUpdateReviewRequest)(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan);
|
|
201
201
|
console.log(`Prepared release PR branch ${pr.branch}`);
|
|
202
202
|
console.log(`Title: ${pr.title}`);
|
|
203
203
|
console.log(reviewResult);
|
|
@@ -205,7 +205,7 @@ async function main() {
|
|
|
205
205
|
}
|
|
206
206
|
if (command === "release") {
|
|
207
207
|
if (flags["dry-run"]) {
|
|
208
|
-
const result = await (0, release_js_1.
|
|
208
|
+
const result = await (0, release_js_1.runReleaseDetailed)(process.cwd(), {
|
|
209
209
|
logger,
|
|
210
210
|
"dry-run": true,
|
|
211
211
|
});
|
|
@@ -220,7 +220,7 @@ async function main() {
|
|
|
220
220
|
}
|
|
221
221
|
return 0;
|
|
222
222
|
}
|
|
223
|
-
const message = await (0, release_js_1.
|
|
223
|
+
const message = await (0, release_js_1.runRelease)(process.cwd());
|
|
224
224
|
console.log(message);
|
|
225
225
|
return 0;
|
|
226
226
|
}
|
|
@@ -228,7 +228,7 @@ async function main() {
|
|
|
228
228
|
console.log("Commands:");
|
|
229
229
|
console.log(" run [--json] [--dry-run] Auto-dispatch release PR/update or release publish by context");
|
|
230
230
|
console.log(" verify Validate config and basic repository shape");
|
|
231
|
-
console.log(" plan Print release plan
|
|
231
|
+
console.log(" plan Print release plan");
|
|
232
232
|
console.log(" changelog [--write] Print or write changelog section");
|
|
233
233
|
console.log(" pr [--dry-run] Prepare release PR commit and branch");
|
|
234
234
|
console.log(" release [--dry-run] Publish release metadata for release commit context");
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -14,6 +14,11 @@ export declare const configSchema: z.ZodObject<{
|
|
|
14
14
|
"r-news": "r-news";
|
|
15
15
|
}>>;
|
|
16
16
|
"release-draft": z.ZodOptional<z.ZodBoolean>;
|
|
17
|
+
"release-reference-comments": z.ZodOptional<z.ZodEnum<{
|
|
18
|
+
off: "off";
|
|
19
|
+
"best-effort": "best-effort";
|
|
20
|
+
strict: "strict";
|
|
21
|
+
}>>;
|
|
17
22
|
"release-branch": z.ZodOptional<z.ZodString>;
|
|
18
23
|
"baseline-file": z.ZodOptional<z.ZodString>;
|
|
19
24
|
"bootstrap-sha": z.ZodOptional<z.ZodString>;
|
package/dist/config/schema.js
CHANGED
|
@@ -68,6 +68,9 @@ exports.configSchema = zod_1.z
|
|
|
68
68
|
"changelog-file": zod_1.z.string().optional(),
|
|
69
69
|
"changelog-format": zod_1.z.enum(["markdown-changelog", "r-news"]).optional(),
|
|
70
70
|
"release-draft": zod_1.z.boolean().optional(),
|
|
71
|
+
"release-reference-comments": zod_1.z
|
|
72
|
+
.enum(["off", "best-effort", "strict"])
|
|
73
|
+
.optional(),
|
|
71
74
|
"release-branch": zod_1.z.string().optional(),
|
|
72
75
|
"baseline-file": zod_1.z.string().optional(),
|
|
73
76
|
"bootstrap-sha": zod_1.z.string().optional(),
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { verifyProject } from "./release/verify-project.js";
|
|
|
3
3
|
export { findPluginsByCapability, pluginHasCapability, } from "./scm/capabilities.js";
|
|
4
4
|
export { getScmClient } from "./scm/client.js";
|
|
5
5
|
export { createGitHubPlugin } from "./scm/github-plugin.js";
|
|
6
|
-
export type { ScmClient, ScmClientContext, ScmProvider, ScmReleaseMetadataInput, ScmReleaseMetadataResult, ScmReviewRequestInput, ScmReviewRequestResult, } from "./scm/types.js";
|
|
6
|
+
export type { ScmClient, ScmClientContext, ScmProvider, ScmReleaseMetadataInput, ScmReleaseMetadataResult, ScmReleaseReferenceCommentsInput, ScmReleaseReferenceCommentsResult, ScmReviewRequestInput, ScmReviewRequestResult, } from "./scm/types.js";
|
|
7
7
|
export { resolveVersionStrategy } from "./strategy/resolve.js";
|
|
8
8
|
export type { VersionaryArtifactRule, VersionaryConfig, VersionaryPackage, } from "./types/config.js";
|
|
9
|
-
export type { VersionaryPluginCapability, VersionaryPluginContext, VersionaryPluginRuntime, VersionaryScmReleaseMetadataInput, VersionaryScmReleaseMetadataResult, VersionaryScmReviewRequestInput, VersionaryScmReviewRequestResult, } from "./types/plugins.js";
|
|
9
|
+
export type { VersionaryPluginCapability, VersionaryPluginContext, VersionaryPluginRuntime, VersionaryScmReleaseMetadataInput, VersionaryScmReleaseMetadataResult, VersionaryScmReleaseReferenceCommentsInput, VersionaryScmReleaseReferenceCommentsResult, VersionaryScmReviewRequestInput, VersionaryScmReviewRequestResult, } from "./types/plugins.js";
|
|
@@ -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 { SimplePlan } from "./plan.js";
|
|
3
|
+
import type { ReleasePlan, SimplePlan } from "./plan.js";
|
|
4
4
|
export declare function renderSimpleReleaseNotes(input: {
|
|
5
5
|
currentVersion: string;
|
|
6
6
|
nextVersion: string;
|
|
@@ -13,6 +13,8 @@ export declare function renderSimpleReleaseNotes(input: {
|
|
|
13
13
|
}, options?: {
|
|
14
14
|
includeFooter?: boolean;
|
|
15
15
|
}): string;
|
|
16
|
+
export declare function renderReleasePlanChangelog(plan: ReleasePlan): string;
|
|
17
|
+
/** @deprecated Use renderReleasePlanChangelog. */
|
|
16
18
|
export declare function renderSimpleChangelog(plan: SimplePlan): string;
|
|
17
19
|
export declare function renderPackageChangelogSection(input: {
|
|
18
20
|
currentVersion: string;
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.renderSimpleReleaseNotes = renderSimpleReleaseNotes;
|
|
7
|
+
exports.renderReleasePlanChangelog = renderReleasePlanChangelog;
|
|
7
8
|
exports.renderSimpleChangelog = renderSimpleChangelog;
|
|
8
9
|
exports.renderPackageChangelogSection = renderPackageChangelogSection;
|
|
9
10
|
exports.prependChangelog = prependChangelog;
|
|
@@ -112,7 +113,7 @@ function renderSimpleReleaseNotes(input, options = {}) {
|
|
|
112
113
|
}
|
|
113
114
|
return lines.join("\n");
|
|
114
115
|
}
|
|
115
|
-
function
|
|
116
|
+
function renderReleasePlanChangelog(plan) {
|
|
116
117
|
if (!plan.nextVersion) {
|
|
117
118
|
return "";
|
|
118
119
|
}
|
|
@@ -129,22 +130,29 @@ function renderSimpleChangelog(plan) {
|
|
|
129
130
|
version: pkg.nextVersion,
|
|
130
131
|
}))
|
|
131
132
|
: [];
|
|
133
|
+
const dedupedCommits = [
|
|
134
|
+
...new Map(plan.commits.map((commit) => [commit.hash, commit])).values(),
|
|
135
|
+
];
|
|
132
136
|
if (plan.changelogFormat === "r-news") {
|
|
133
137
|
return renderRNewsReleaseNotes({
|
|
134
138
|
packageName: plan.packageName,
|
|
135
139
|
nextVersion: plan.nextVersion,
|
|
136
|
-
commits:
|
|
140
|
+
commits: dedupedCommits,
|
|
137
141
|
cwd: process.cwd(),
|
|
138
142
|
});
|
|
139
143
|
}
|
|
140
144
|
return renderSimpleReleaseNotes({
|
|
141
145
|
currentVersion: plan.currentVersion,
|
|
142
146
|
nextVersion: plan.nextVersion,
|
|
143
|
-
commits:
|
|
147
|
+
commits: dedupedCommits,
|
|
144
148
|
cwd: process.cwd(),
|
|
145
149
|
dependencies,
|
|
146
150
|
});
|
|
147
151
|
}
|
|
152
|
+
/** @deprecated Use renderReleasePlanChangelog. */
|
|
153
|
+
function renderSimpleChangelog(plan) {
|
|
154
|
+
return renderReleasePlanChangelog(plan);
|
|
155
|
+
}
|
|
148
156
|
function renderPackageChangelogSection(input) {
|
|
149
157
|
const repoUrl = (0, repo_url_js_1.resolveRepositoryWebBaseUrl)(input.cwd ?? process.cwd());
|
|
150
158
|
const header = repoUrl
|
|
@@ -172,15 +180,16 @@ function prependChangelog(cwd, changelogFile, section, format = "markdown-change
|
|
|
172
180
|
? node_fs_1.default.readFileSync(changelogPath, "utf8")
|
|
173
181
|
: "";
|
|
174
182
|
if (format === "r-news") {
|
|
175
|
-
const
|
|
176
|
-
const
|
|
183
|
+
const bodyWithoutDevHeader = existing.replace(/^#\s+.+\s+\(development version\)\s*(?:\r?\n)*/u, "");
|
|
184
|
+
const separator = bodyWithoutDevHeader.length > 0 ? "\n\n" : "";
|
|
185
|
+
const next = `${`${section}${separator}${bodyWithoutDevHeader}`.trimEnd()}\n`;
|
|
177
186
|
node_fs_1.default.writeFileSync(changelogPath, next, "utf8");
|
|
178
187
|
return;
|
|
179
188
|
}
|
|
180
189
|
const heading = "# Changelog\n\n";
|
|
181
190
|
const bodyWithoutHeading = existing.replace(/^# Changelog\s*/u, "");
|
|
182
191
|
const separator = existing.length > 0 ? "\n" : "";
|
|
183
|
-
const next = `${heading}${section}${separator}${bodyWithoutHeading}`.trimEnd()
|
|
192
|
+
const next = `${`${heading}${section}${separator}${bodyWithoutHeading}`.trimEnd()}\n`;
|
|
184
193
|
node_fs_1.default.writeFileSync(changelogPath, next, "utf8");
|
|
185
194
|
}
|
|
186
195
|
function renderRNewsReleaseNotes(input) {
|
package/dist/release/plan.d.ts
CHANGED
|
@@ -1,7 +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
|
-
export interface
|
|
4
|
+
export interface ReleasePlan {
|
|
5
5
|
mode: "simple";
|
|
6
6
|
releaseType: ReleaseType;
|
|
7
7
|
currentVersion: string;
|
|
@@ -22,6 +22,8 @@ export interface SimplePlan {
|
|
|
22
22
|
commits: ParsedCommit[];
|
|
23
23
|
}>;
|
|
24
24
|
}
|
|
25
|
+
/** @deprecated Use ReleasePlan. */
|
|
26
|
+
export type SimplePlan = ReleasePlan;
|
|
25
27
|
export declare function getChangelogDefaults(config: {
|
|
26
28
|
"release-type"?: VersionaryConfig["release-type"];
|
|
27
29
|
"changelog-file"?: VersionaryConfig["changelog-file"];
|
|
@@ -30,4 +32,6 @@ export declare function getChangelogDefaults(config: {
|
|
|
30
32
|
changelogFile: string;
|
|
31
33
|
changelogFormat: VersionaryChangelogFormat;
|
|
32
34
|
};
|
|
33
|
-
export declare function
|
|
35
|
+
export declare function createReleasePlan(cwd?: string): ReleasePlan;
|
|
36
|
+
/** @deprecated Use createReleasePlan. */
|
|
37
|
+
export declare function createSimplePlan(cwd?: string): ReleasePlan;
|
package/dist/release/plan.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getChangelogDefaults = getChangelogDefaults;
|
|
7
|
+
exports.createReleasePlan = createReleasePlan;
|
|
7
8
|
exports.createSimplePlan = createSimplePlan;
|
|
8
9
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
10
|
const node_path_1 = __importDefault(require("node:path"));
|
|
@@ -23,7 +24,7 @@ function getChangelogDefaults(config) {
|
|
|
23
24
|
(changelogFormat === "r-news" ? "NEWS.md" : "CHANGELOG.md");
|
|
24
25
|
return { changelogFile, changelogFormat };
|
|
25
26
|
}
|
|
26
|
-
function
|
|
27
|
+
function createReleasePlan(cwd = process.cwd()) {
|
|
27
28
|
const loaded = (0, load_config_js_1.loadConfig)(cwd);
|
|
28
29
|
const strategy = (0, resolve_js_1.resolveVersionStrategy)(loaded.config);
|
|
29
30
|
const versionFile = strategy.getVersionFile(loaded.config);
|
|
@@ -189,3 +190,7 @@ function createSimplePlan(cwd = process.cwd()) {
|
|
|
189
190
|
packages: adjustedPackages,
|
|
190
191
|
};
|
|
191
192
|
}
|
|
193
|
+
/** @deprecated Use createReleasePlan. */
|
|
194
|
+
function createSimplePlan(cwd = process.cwd()) {
|
|
195
|
+
return createReleasePlan(cwd);
|
|
196
|
+
}
|
package/dist/release/pr.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { ParsedCommit } from "../git/commits.js";
|
|
2
2
|
import type { VersionaryPluginContext } from "../types/plugins.js";
|
|
3
|
-
import { type SimplePlan } from "./plan.js";
|
|
3
|
+
import { type ReleasePlan, type SimplePlan } from "./plan.js";
|
|
4
4
|
export declare function splitSafeDirtyFiles(files: string[]): {
|
|
5
5
|
ignored: string[];
|
|
6
6
|
blocking: string[];
|
|
7
7
|
};
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function prepareReleasePr(cwd?: string, options?: {
|
|
9
9
|
logger?: VersionaryPluginContext["logger"];
|
|
10
10
|
}): {
|
|
11
11
|
branch: string;
|
|
@@ -13,9 +13,17 @@ export declare function prepareSimpleReleasePr(cwd?: string, options?: {
|
|
|
13
13
|
version: string;
|
|
14
14
|
previousVersion: string;
|
|
15
15
|
commits: ParsedCommit[];
|
|
16
|
-
plan:
|
|
16
|
+
plan: ReleasePlan;
|
|
17
17
|
};
|
|
18
18
|
export declare function renderSimpleReviewRequestBody(version: string, previousVersion: string, commits: ParsedCommit[], plan?: SimplePlan | null, cwd?: string): string;
|
|
19
|
+
export declare function openOrUpdateReviewRequest(cwd: string, branch: string, title: string, version: string, previousVersion: string, commits: ParsedCommit[], plan?: SimplePlan | null, options?: {
|
|
20
|
+
logger?: VersionaryPluginContext["logger"];
|
|
21
|
+
}): Promise<string>;
|
|
22
|
+
/** @deprecated Use prepareReleasePr. */
|
|
23
|
+
export declare function prepareSimpleReleasePr(cwd?: string, options?: {
|
|
24
|
+
logger?: VersionaryPluginContext["logger"];
|
|
25
|
+
}): ReturnType<typeof prepareReleasePr>;
|
|
26
|
+
/** @deprecated Use openOrUpdateReviewRequest. */
|
|
19
27
|
export declare function openOrUpdateSimpleReviewRequest(cwd: string, branch: string, title: string, version: string, previousVersion: string, commits: ParsedCommit[], plan?: SimplePlan | null, options?: {
|
|
20
28
|
logger?: VersionaryPluginContext["logger"];
|
|
21
29
|
}): Promise<string>;
|
package/dist/release/pr.js
CHANGED
|
@@ -4,8 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.splitSafeDirtyFiles = splitSafeDirtyFiles;
|
|
7
|
-
exports.
|
|
7
|
+
exports.prepareReleasePr = prepareReleasePr;
|
|
8
8
|
exports.renderSimpleReviewRequestBody = renderSimpleReviewRequestBody;
|
|
9
|
+
exports.openOrUpdateReviewRequest = openOrUpdateReviewRequest;
|
|
10
|
+
exports.prepareSimpleReleasePr = prepareSimpleReleasePr;
|
|
9
11
|
exports.openOrUpdateSimpleReviewRequest = openOrUpdateSimpleReviewRequest;
|
|
10
12
|
exports.pushReleaseBranch = pushReleaseBranch;
|
|
11
13
|
exports.isReleaseCommitMessage = isReleaseCommitMessage;
|
|
@@ -202,8 +204,8 @@ function formatReleaseCommitTitle(releaseTargets) {
|
|
|
202
204
|
}
|
|
203
205
|
return `chore(release): ${tags[0]} (+${tags.length - 1} more)`;
|
|
204
206
|
}
|
|
205
|
-
function
|
|
206
|
-
const plan = (0, plan_js_1.
|
|
207
|
+
function prepareReleasePr(cwd = process.cwd(), options = {}) {
|
|
208
|
+
const plan = (0, plan_js_1.createReleasePlan)(cwd);
|
|
207
209
|
const loaded = (0, load_config_js_1.loadConfig)(cwd);
|
|
208
210
|
const strategy = (0, resolve_js_1.resolveVersionStrategy)(loaded.config);
|
|
209
211
|
if (!plan.nextVersion) {
|
|
@@ -253,7 +255,7 @@ function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
253
255
|
const updatedArtifactFiles = (0, artifact_rules_js_1.applyConfiguredArtifactRules)(cwd, loaded.config, plan);
|
|
254
256
|
const updatedRustLockFiles = ensureCargoLockUpToDate(cwd);
|
|
255
257
|
const packageReleaseMetadata = buildPackageReleaseMetadata(cwd, plan, loaded.config);
|
|
256
|
-
const section = (0, changelog_js_1.
|
|
258
|
+
const section = (0, changelog_js_1.renderReleasePlanChangelog)(plan);
|
|
257
259
|
(0, changelog_js_1.prependChangelog)(cwd, plan.changelogFile, section, plan.changelogFormat);
|
|
258
260
|
const updatedChangelogFiles = [plan.changelogFile];
|
|
259
261
|
for (const packagePlan of plan.packages ?? []) {
|
|
@@ -261,10 +263,11 @@ function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
261
263
|
continue;
|
|
262
264
|
}
|
|
263
265
|
const packageConfig = loaded.config.packages?.[packagePlan.path] ?? {};
|
|
264
|
-
const packageChangelogFile =
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
266
|
+
const { changelogFile: packageChangelogFile } = (0, plan_js_1.getChangelogDefaults)({
|
|
267
|
+
"release-type": packageConfig["release-type"] ?? loaded.config["release-type"],
|
|
268
|
+
"changelog-file": packageConfig["changelog-file"] ?? loaded.config["changelog-file"],
|
|
269
|
+
"changelog-format": packageConfig["changelog-format"] ?? loaded.config["changelog-format"],
|
|
270
|
+
});
|
|
268
271
|
const packageMetadata = packageReleaseMetadata[packagePlan.path];
|
|
269
272
|
if (!packageMetadata) {
|
|
270
273
|
continue;
|
|
@@ -342,9 +345,28 @@ function renderSimpleReviewRequestBody(version, previousVersion, commits, plan =
|
|
|
342
345
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
343
346
|
return directSources;
|
|
344
347
|
};
|
|
348
|
+
const relabelSectionHeader = (notes, packageLabel, nextVersion) => {
|
|
349
|
+
const linkedHeader = notes.match(/^##\s+\[([^\]]+)\]\(([^)]+)\)\s+\(([^)]+)\)/u);
|
|
350
|
+
if (linkedHeader) {
|
|
351
|
+
const [, , compareUrl, date] = linkedHeader;
|
|
352
|
+
return notes.replace(/^##\s+\[[^\]]+\]\([^)]+\)\s+\([^)]+\)/u, `## [${packageLabel}: ${nextVersion}](${compareUrl}) (${date})`);
|
|
353
|
+
}
|
|
354
|
+
const plainHeader = notes.match(/^##\s+([^\s]+)\s+\(([^)]+)\)/u);
|
|
355
|
+
if (plainHeader) {
|
|
356
|
+
const [, , date] = plainHeader;
|
|
357
|
+
return notes.replace(/^##\s+[^\s]+\s+\([^)]+\)/u, `## ${packageLabel}: ${nextVersion} (${date})`);
|
|
358
|
+
}
|
|
359
|
+
return notes;
|
|
360
|
+
};
|
|
345
361
|
if (plan?.packages && plan.packages.length > 1) {
|
|
346
|
-
const sections =
|
|
347
|
-
|
|
362
|
+
const sections = [];
|
|
363
|
+
const rootPackage = plan.packages.find((pkg) => pkg.path === "." && pkg.nextVersion);
|
|
364
|
+
if (rootPackage?.nextVersion) {
|
|
365
|
+
const rootNotes = (0, changelog_js_1.renderReleasePlanChangelog)(plan);
|
|
366
|
+
sections.push(relabelSectionHeader(rootNotes, formatPackageLabel("."), rootPackage.nextVersion));
|
|
367
|
+
}
|
|
368
|
+
const packageSections = plan.packages
|
|
369
|
+
.filter((pkg) => pkg.path !== "." && pkg.nextVersion)
|
|
348
370
|
.map((pkg) => {
|
|
349
371
|
const packageLabel = formatPackageLabel(pkg.path);
|
|
350
372
|
const propagatedDependencies = findPropagatedDependencies(pkg.path, plan.packages ?? []);
|
|
@@ -355,20 +377,14 @@ function renderSimpleReviewRequestBody(version, previousVersion, commits, plan =
|
|
|
355
377
|
cwd,
|
|
356
378
|
dependencies: propagatedDependencies,
|
|
357
379
|
}, { includeFooter: false });
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
return notes.replace(/^##\s+[^\s]+\s+\([^)]+\)/u, `## ${packageLabel}: ${pkg.nextVersion ?? ""} (${date})`);
|
|
367
|
-
}
|
|
368
|
-
return notes;
|
|
369
|
-
})
|
|
370
|
-
.join("\n\n");
|
|
371
|
-
return `${sections}\n\nThis PR was generated by Versionary.`;
|
|
380
|
+
return relabelSectionHeader(notes, packageLabel, pkg.nextVersion ?? "");
|
|
381
|
+
});
|
|
382
|
+
sections.push(...packageSections);
|
|
383
|
+
const bodySections = sections.join("\n\n");
|
|
384
|
+
if (bodySections.length === 0) {
|
|
385
|
+
return "This PR was generated by Versionary.";
|
|
386
|
+
}
|
|
387
|
+
return `${bodySections}\n\nThis PR was generated by Versionary.`;
|
|
372
388
|
}
|
|
373
389
|
return (0, changelog_js_1.renderSimpleReleaseNotes)({
|
|
374
390
|
currentVersion: previousVersion,
|
|
@@ -377,7 +393,7 @@ function renderSimpleReviewRequestBody(version, previousVersion, commits, plan =
|
|
|
377
393
|
cwd,
|
|
378
394
|
}, { includeFooter: true });
|
|
379
395
|
}
|
|
380
|
-
async function
|
|
396
|
+
async function openOrUpdateReviewRequest(cwd, branch, title, version, previousVersion, commits, plan = null, options = {}) {
|
|
381
397
|
const loaded = (0, load_config_js_1.loadConfig)(cwd);
|
|
382
398
|
const releaseFlow = loaded.config["review-mode"] ?? "pr";
|
|
383
399
|
if (releaseFlow === "direct") {
|
|
@@ -396,6 +412,14 @@ async function openOrUpdateSimpleReviewRequest(cwd, branch, title, version, prev
|
|
|
396
412
|
});
|
|
397
413
|
return result.url;
|
|
398
414
|
}
|
|
415
|
+
/** @deprecated Use prepareReleasePr. */
|
|
416
|
+
function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
417
|
+
return prepareReleasePr(cwd, options);
|
|
418
|
+
}
|
|
419
|
+
/** @deprecated Use openOrUpdateReviewRequest. */
|
|
420
|
+
async function openOrUpdateSimpleReviewRequest(cwd, branch, title, version, previousVersion, commits, plan = null, options = {}) {
|
|
421
|
+
return openOrUpdateReviewRequest(cwd, branch, title, version, previousVersion, commits, plan, options);
|
|
422
|
+
}
|
|
399
423
|
function pushReleaseBranch(cwd, branch) {
|
|
400
424
|
(0, node_child_process_1.execFileSync)("git", ["push", "--force-with-lease", "origin", branch], {
|
|
401
425
|
cwd,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { VersionaryConfig } from "../types/config.js";
|
|
2
2
|
import type { VersionaryPluginContext } from "../types/plugins.js";
|
|
3
|
+
export declare function extractReleaseNotes(content: string, version: string, changelogFormat: "markdown-changelog" | "r-news"): string;
|
|
4
|
+
export declare function extractClosingReferencesFromNotes(notes: string): number[];
|
|
3
5
|
export declare function resolveTargetChangelogFile(config: VersionaryConfig, rootChangelogFile: string, targetPath: string): string;
|
|
4
|
-
export declare function
|
|
5
|
-
export type
|
|
6
|
+
export declare function runRelease(cwd?: string): Promise<string>;
|
|
7
|
+
export type RunReleaseResult = {
|
|
6
8
|
action: "release-skipped";
|
|
7
9
|
reason: string;
|
|
8
10
|
} | {
|
|
@@ -22,8 +24,16 @@ export type SimpleRunReleaseResult = {
|
|
|
22
24
|
metadataStatus: "created" | "exists";
|
|
23
25
|
}[];
|
|
24
26
|
};
|
|
25
|
-
export interface
|
|
27
|
+
export interface RunReleaseOptions {
|
|
26
28
|
logger?: VersionaryPluginContext["logger"];
|
|
27
29
|
"dry-run"?: boolean;
|
|
28
30
|
}
|
|
31
|
+
export declare function runReleaseDetailed(cwd?: string, options?: RunReleaseOptions): Promise<RunReleaseResult>;
|
|
32
|
+
/** @deprecated Use RunReleaseResult. */
|
|
33
|
+
export type SimpleRunReleaseResult = RunReleaseResult;
|
|
34
|
+
/** @deprecated Use RunReleaseOptions. */
|
|
35
|
+
export type RunSimpleReleaseOptions = RunReleaseOptions;
|
|
36
|
+
/** @deprecated Use runRelease. */
|
|
37
|
+
export declare function runSimpleRelease(cwd?: string): Promise<string>;
|
|
38
|
+
/** @deprecated Use runReleaseDetailed. */
|
|
29
39
|
export declare function runSimpleReleaseDetailed(cwd?: string, options?: RunSimpleReleaseOptions): Promise<SimpleRunReleaseResult>;
|
package/dist/release/release.js
CHANGED
|
@@ -3,7 +3,11 @@ 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.extractReleaseNotes = extractReleaseNotes;
|
|
7
|
+
exports.extractClosingReferencesFromNotes = extractClosingReferencesFromNotes;
|
|
6
8
|
exports.resolveTargetChangelogFile = resolveTargetChangelogFile;
|
|
9
|
+
exports.runRelease = runRelease;
|
|
10
|
+
exports.runReleaseDetailed = runReleaseDetailed;
|
|
7
11
|
exports.runSimpleRelease = runSimpleRelease;
|
|
8
12
|
exports.runSimpleReleaseDetailed = runSimpleReleaseDetailed;
|
|
9
13
|
const node_child_process_1 = require("node:child_process");
|
|
@@ -16,60 +20,109 @@ const plan_js_1 = require("./plan.js");
|
|
|
16
20
|
const pr_js_1 = require("./pr.js");
|
|
17
21
|
const recovery_js_1 = require("./recovery.js");
|
|
18
22
|
const state_js_1 = require("./state.js");
|
|
19
|
-
function
|
|
20
|
-
return
|
|
21
|
-
cwd,
|
|
22
|
-
encoding: "utf8",
|
|
23
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
24
|
-
}).trim();
|
|
23
|
+
function escapeRegExp(input) {
|
|
24
|
+
return input.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
25
25
|
}
|
|
26
|
-
function
|
|
27
|
-
const changelogPath = node_path_1.default.join(cwd, changelogFile);
|
|
28
|
-
if (!node_fs_1.default.existsSync(changelogPath)) {
|
|
29
|
-
return `Automated release for v${version}`;
|
|
30
|
-
}
|
|
31
|
-
const content = node_fs_1.default.readFileSync(changelogPath, "utf8");
|
|
26
|
+
function extractReleaseNotes(content, version, changelogFormat) {
|
|
32
27
|
const lines = content.split("\n");
|
|
33
28
|
const shortVersion = version.replace(/\.\d+$/u, "");
|
|
34
|
-
const start =
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
const start = changelogFormat === "r-news"
|
|
30
|
+
? lines.findIndex((line) => {
|
|
31
|
+
const fullMatch = new RegExp(`^#\\s+.+\\s+${escapeRegExp(version)}\\s*$`, "u");
|
|
32
|
+
const shortMatch = new RegExp(`^#\\s+.+\\s+${escapeRegExp(shortVersion)}\\s*$`, "u");
|
|
33
|
+
return fullMatch.test(line) || shortMatch.test(line);
|
|
34
|
+
})
|
|
35
|
+
: lines.findIndex((line) => line.startsWith(`## ${version} -`) ||
|
|
36
|
+
line.startsWith(`## [${version}](`) ||
|
|
37
|
+
line.startsWith(`# ${shortVersion} -`) ||
|
|
38
|
+
line.startsWith(`# [${shortVersion}](`) ||
|
|
39
|
+
new RegExp(`^#\\s+.+\\s+${shortVersion}\\s*$`, "u").test(line));
|
|
39
40
|
if (start < 0) {
|
|
40
|
-
return
|
|
41
|
+
return "";
|
|
41
42
|
}
|
|
42
43
|
let end = lines.length;
|
|
43
44
|
for (let idx = start + 1; idx < lines.length; idx += 1) {
|
|
44
|
-
|
|
45
|
+
const line = lines[idx] ?? "";
|
|
46
|
+
if (changelogFormat === "r-news") {
|
|
47
|
+
if (/^#(?!#)\s+/u.test(line)) {
|
|
48
|
+
end = idx;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (line.startsWith("## ")) {
|
|
45
54
|
end = idx;
|
|
46
55
|
break;
|
|
47
56
|
}
|
|
48
57
|
}
|
|
49
|
-
|
|
58
|
+
return lines
|
|
50
59
|
.slice(start + 1, end)
|
|
51
60
|
.join("\n")
|
|
52
61
|
.trim();
|
|
62
|
+
}
|
|
63
|
+
function getHeadCommitMessage(cwd) {
|
|
64
|
+
return (0, node_child_process_1.execFileSync)("git", ["log", "-1", "--pretty=%B"], {
|
|
65
|
+
cwd,
|
|
66
|
+
encoding: "utf8",
|
|
67
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
68
|
+
}).trim();
|
|
69
|
+
}
|
|
70
|
+
function readReleaseNotes(cwd, version, changelogFile, changelogFormat) {
|
|
71
|
+
const changelogPath = node_path_1.default.join(cwd, changelogFile);
|
|
72
|
+
if (!node_fs_1.default.existsSync(changelogPath)) {
|
|
73
|
+
return `Automated release for v${version}`;
|
|
74
|
+
}
|
|
75
|
+
const content = node_fs_1.default.readFileSync(changelogPath, "utf8");
|
|
76
|
+
const notes = extractReleaseNotes(content, version, changelogFormat);
|
|
53
77
|
return notes.length > 0 ? notes : `Automated release for v${version}`;
|
|
54
78
|
}
|
|
79
|
+
function extractClosingReferencesFromNotes(notes) {
|
|
80
|
+
const refs = new Set();
|
|
81
|
+
const linkedPattern = /\b(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\b\s+\[#(\d+)\]\([^)]+\)/giu;
|
|
82
|
+
for (const match of notes.matchAll(linkedPattern)) {
|
|
83
|
+
const issue = Number(match[2] ?? "");
|
|
84
|
+
if (Number.isInteger(issue) && issue > 0) {
|
|
85
|
+
refs.add(issue);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const plainPattern = /\b(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\b\s+#(\d+)/giu;
|
|
89
|
+
for (const match of notes.matchAll(plainPattern)) {
|
|
90
|
+
const issue = Number(match[2] ?? "");
|
|
91
|
+
if (Number.isInteger(issue) && issue > 0) {
|
|
92
|
+
refs.add(issue);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return [...refs].sort((a, b) => a - b);
|
|
96
|
+
}
|
|
55
97
|
function resolveTargetChangelogFile(config, rootChangelogFile, targetPath) {
|
|
56
98
|
if (targetPath === ".") {
|
|
57
99
|
return rootChangelogFile;
|
|
58
100
|
}
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
101
|
+
const packageConfig = config.packages?.[targetPath];
|
|
102
|
+
const { changelogFile: packageChangelogFile } = (0, plan_js_1.getChangelogDefaults)({
|
|
103
|
+
"release-type": packageConfig?.["release-type"] ?? config["release-type"],
|
|
104
|
+
"changelog-file": packageConfig?.["changelog-file"] ?? config["changelog-file"],
|
|
105
|
+
"changelog-format": packageConfig?.["changelog-format"] ?? config["changelog-format"],
|
|
106
|
+
});
|
|
63
107
|
return node_path_1.default.posix.join(targetPath, packageChangelogFile);
|
|
64
108
|
}
|
|
65
|
-
|
|
66
|
-
const
|
|
109
|
+
function resolveTargetChangelogFormat(config, targetPath) {
|
|
110
|
+
const packageConfig = targetPath === "." ? undefined : config.packages?.[targetPath];
|
|
111
|
+
const { changelogFormat } = (0, plan_js_1.getChangelogDefaults)({
|
|
112
|
+
"release-type": packageConfig?.["release-type"] ?? config["release-type"],
|
|
113
|
+
"changelog-file": packageConfig?.["changelog-file"] ?? config["changelog-file"],
|
|
114
|
+
"changelog-format": packageConfig?.["changelog-format"] ?? config["changelog-format"],
|
|
115
|
+
});
|
|
116
|
+
return changelogFormat;
|
|
117
|
+
}
|
|
118
|
+
async function runRelease(cwd = process.cwd()) {
|
|
119
|
+
const result = await runReleaseDetailed(cwd, { logger: console });
|
|
67
120
|
if (result.action === "release-skipped") {
|
|
68
121
|
return result.reason;
|
|
69
122
|
}
|
|
70
123
|
return result.message;
|
|
71
124
|
}
|
|
72
|
-
async function
|
|
125
|
+
async function runReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
73
126
|
const commitMessage = getHeadCommitMessage(cwd);
|
|
74
127
|
if (!(0, pr_js_1.isReleaseCommitMessage)(commitMessage)) {
|
|
75
128
|
return {
|
|
@@ -80,6 +133,7 @@ async function runSimpleReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
|
80
133
|
const loaded = (0, load_config_js_1.loadConfig)(cwd);
|
|
81
134
|
const strategy = (0, resolve_js_1.resolveVersionStrategy)(loaded.config);
|
|
82
135
|
const { changelogFile } = (0, plan_js_1.getChangelogDefaults)(loaded.config);
|
|
136
|
+
const referenceCommentMode = loaded.config["release-reference-comments"] ?? "off";
|
|
83
137
|
const version = strategy.readVersion(cwd, loaded.config);
|
|
84
138
|
const defaultTag = `v${version}`;
|
|
85
139
|
const releaseTargets = (0, state_js_1.readReleaseTargets)(cwd);
|
|
@@ -105,12 +159,16 @@ async function runSimpleReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
|
105
159
|
}
|
|
106
160
|
const scmClient = (0, client_js_1.getScmClient)();
|
|
107
161
|
const releases = [];
|
|
162
|
+
const referencesByTag = new Map();
|
|
108
163
|
for (const target of targets) {
|
|
109
164
|
const targetChangelogFile = resolveTargetChangelogFile(loaded.config, changelogFile, target.path);
|
|
165
|
+
const targetChangelogFormat = resolveTargetChangelogFormat(loaded.config, target.path);
|
|
166
|
+
const releaseNotes = readReleaseNotes(cwd, target.version, targetChangelogFile, targetChangelogFormat);
|
|
167
|
+
referencesByTag.set(target.tag, extractClosingReferencesFromNotes(releaseNotes));
|
|
110
168
|
const outcome = await (0, recovery_js_1.executeIdempotentReleaseTarget)(cwd, {
|
|
111
169
|
tag: target.tag,
|
|
112
170
|
version: target.version,
|
|
113
|
-
notes:
|
|
171
|
+
notes: releaseNotes,
|
|
114
172
|
draft: loaded.config["release-draft"] ?? false,
|
|
115
173
|
}, {
|
|
116
174
|
createReleaseMetadata: (input) => scmClient.createReleaseMetadata(input, {
|
|
@@ -125,6 +183,20 @@ async function runSimpleReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
|
125
183
|
tagStatus: outcome.tagStatus,
|
|
126
184
|
metadataStatus: outcome.metadataStatus,
|
|
127
185
|
});
|
|
186
|
+
const references = referencesByTag.get(outcome.tag) ?? [];
|
|
187
|
+
if (references.length > 0 &&
|
|
188
|
+
referenceCommentMode !== "off" &&
|
|
189
|
+
scmClient.createReleaseReferenceComments) {
|
|
190
|
+
await scmClient.createReleaseReferenceComments({
|
|
191
|
+
version: target.version,
|
|
192
|
+
releaseUrl: outcome.url,
|
|
193
|
+
references,
|
|
194
|
+
mode: referenceCommentMode,
|
|
195
|
+
}, {
|
|
196
|
+
cwd,
|
|
197
|
+
logger: options.logger,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
128
200
|
}
|
|
129
201
|
const published = releases.map((outcome) => `${outcome.tag}: ${outcome.url} (tag=${outcome.tagStatus}, metadata=${outcome.metadataStatus})`);
|
|
130
202
|
return {
|
|
@@ -133,3 +205,11 @@ async function runSimpleReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
|
133
205
|
message: `Published releases ${published.join(", ")}`,
|
|
134
206
|
};
|
|
135
207
|
}
|
|
208
|
+
/** @deprecated Use runRelease. */
|
|
209
|
+
async function runSimpleRelease(cwd = process.cwd()) {
|
|
210
|
+
return runRelease(cwd);
|
|
211
|
+
}
|
|
212
|
+
/** @deprecated Use runReleaseDetailed. */
|
|
213
|
+
async function runSimpleReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
214
|
+
return runReleaseDetailed(cwd, options);
|
|
215
|
+
}
|
package/dist/release/semver.js
CHANGED
|
@@ -5,10 +5,21 @@ exports.isValidVersion = isValidVersion;
|
|
|
5
5
|
exports.compareVersions = compareVersions;
|
|
6
6
|
exports.bumpVersion = bumpVersion;
|
|
7
7
|
const SEMVER_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/u;
|
|
8
|
+
const COMPAT_DOTTED_PRERELEASE_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u;
|
|
9
|
+
function normalizeVersionInput(version) {
|
|
10
|
+
const trimmed = version.trim();
|
|
11
|
+
const compatMatch = trimmed.match(COMPAT_DOTTED_PRERELEASE_PATTERN);
|
|
12
|
+
if (!compatMatch) {
|
|
13
|
+
return trimmed;
|
|
14
|
+
}
|
|
15
|
+
const [, major, minor, patch, prerelease] = compatMatch;
|
|
16
|
+
return `${major}.${minor}.${patch}-${prerelease}`;
|
|
17
|
+
}
|
|
8
18
|
function parseVersion(version) {
|
|
9
|
-
const
|
|
19
|
+
const normalized = normalizeVersionInput(version);
|
|
20
|
+
const match = normalized.match(SEMVER_PATTERN);
|
|
10
21
|
if (!match) {
|
|
11
|
-
throw new Error(`Invalid version in version file: "${version}". Expected SemVer 2.0.0 format.`);
|
|
22
|
+
throw new Error(`Invalid version in version file: "${version}". Expected SemVer 2.0.0 format (or compatibility form X.Y.Z.W).`);
|
|
12
23
|
}
|
|
13
24
|
return {
|
|
14
25
|
major: Number(match[1]),
|
|
@@ -19,7 +30,7 @@ function parseVersion(version) {
|
|
|
19
30
|
};
|
|
20
31
|
}
|
|
21
32
|
function isValidVersion(version) {
|
|
22
|
-
return SEMVER_PATTERN.test(version
|
|
33
|
+
return SEMVER_PATTERN.test(normalizeVersionInput(version));
|
|
23
34
|
}
|
|
24
35
|
function isNumericIdentifier(identifier) {
|
|
25
36
|
return /^(0|[1-9]\d*)$/u.test(identifier);
|
|
@@ -89,7 +89,11 @@ async function ensureLabels(octokit, repo, pullNumber, labels, branchContext) {
|
|
|
89
89
|
function createGitHubPlugin() {
|
|
90
90
|
return {
|
|
91
91
|
name: "github",
|
|
92
|
-
capabilities: [
|
|
92
|
+
capabilities: [
|
|
93
|
+
"scm.reviewRequest",
|
|
94
|
+
"scm.releaseMetadata",
|
|
95
|
+
"scm.releaseReferenceComments",
|
|
96
|
+
],
|
|
93
97
|
provider: "github",
|
|
94
98
|
async createOrUpdateReviewRequest(input, _context) {
|
|
95
99
|
const repo = getRepoFromEnv();
|
|
@@ -205,5 +209,38 @@ function createGitHubPlugin() {
|
|
|
205
209
|
}
|
|
206
210
|
return { url: data.html_url, status: "created" };
|
|
207
211
|
},
|
|
212
|
+
async createReleaseReferenceComments(input, context) {
|
|
213
|
+
const repo = getRepoFromEnv();
|
|
214
|
+
const octokit = new rest_1.Octokit({ auth: getGitHubToken() });
|
|
215
|
+
const uniqueReferences = [...new Set(input.references)].sort((a, b) => a - b);
|
|
216
|
+
const commented = [];
|
|
217
|
+
const mode = input.mode ?? "best-effort";
|
|
218
|
+
for (const reference of uniqueReferences) {
|
|
219
|
+
const body = reference >= 1_000_000_000
|
|
220
|
+
? `This pull request is included in [version ${input.version}](${input.releaseUrl}).`
|
|
221
|
+
: `This issue has been resolved in [version ${input.version}](${input.releaseUrl}).`;
|
|
222
|
+
try {
|
|
223
|
+
await octokit.issues.createComment({
|
|
224
|
+
owner: repo.owner,
|
|
225
|
+
repo: repo.repo,
|
|
226
|
+
issue_number: reference,
|
|
227
|
+
body,
|
|
228
|
+
});
|
|
229
|
+
commented.push(reference);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
const { status, message } = parseGitHubError(error);
|
|
233
|
+
if (mode === "strict") {
|
|
234
|
+
throw new Error(`Failed creating release reference comment on #${reference}: [${repoRef(repo)}] ${message}`);
|
|
235
|
+
}
|
|
236
|
+
if (status === 404 || status === 410 || status === 403) {
|
|
237
|
+
context.logger?.warn(`Skipping release reference comment on #${reference}: [${repoRef(repo)}] ${message}`);
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
context.logger?.warn(`Skipping release reference comment on #${reference}: [${repoRef(repo)}] ${message}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return { commented };
|
|
244
|
+
},
|
|
208
245
|
};
|
|
209
246
|
}
|
package/dist/scm/types.d.ts
CHANGED
|
@@ -30,8 +30,18 @@ export interface ScmReleaseMetadataResult {
|
|
|
30
30
|
url: string;
|
|
31
31
|
status?: "created" | "exists";
|
|
32
32
|
}
|
|
33
|
+
export interface ScmReleaseReferenceCommentsInput {
|
|
34
|
+
version: string;
|
|
35
|
+
releaseUrl: string;
|
|
36
|
+
references: number[];
|
|
37
|
+
mode?: "best-effort" | "strict";
|
|
38
|
+
}
|
|
39
|
+
export interface ScmReleaseReferenceCommentsResult {
|
|
40
|
+
commented: number[];
|
|
41
|
+
}
|
|
33
42
|
export interface ScmClient {
|
|
34
43
|
provider: ScmProvider;
|
|
35
44
|
createOrUpdateReviewRequest: (input: ScmReviewRequestInput, context: ScmClientContext) => Promise<ScmReviewRequestResult>;
|
|
36
45
|
createReleaseMetadata: (input: ScmReleaseMetadataInput, context: ScmClientContext) => Promise<ScmReleaseMetadataResult>;
|
|
46
|
+
createReleaseReferenceComments?: (input: ScmReleaseReferenceCommentsInput, context: ScmClientContext) => Promise<ScmReleaseReferenceCommentsResult>;
|
|
37
47
|
}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type ConfigFileFormat = "jsonc" | "json" | "toml" | "js";
|
|
2
2
|
export type VersionaryChangelogFormat = "markdown-changelog" | "r-news";
|
|
3
|
+
export type ReleaseReferenceCommentsMode = "off" | "best-effort" | "strict";
|
|
3
4
|
export interface VersionaryArtifactRule {
|
|
4
5
|
type: "json" | "toml" | "yaml" | "regex";
|
|
5
6
|
path: string;
|
|
@@ -22,6 +23,7 @@ export interface VersionaryConfig {
|
|
|
22
23
|
"changelog-file"?: string;
|
|
23
24
|
"changelog-format"?: VersionaryChangelogFormat;
|
|
24
25
|
"release-draft"?: boolean;
|
|
26
|
+
"release-reference-comments"?: ReleaseReferenceCommentsMode;
|
|
25
27
|
"release-branch"?: string;
|
|
26
28
|
"baseline-file"?: string;
|
|
27
29
|
"bootstrap-sha"?: string;
|
package/dist/types/plugins.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type { ScmClientContext, ScmProvider, ScmReleaseMetadataInput, ScmReleaseMetadataResult, ScmReviewRequestInput, ScmReviewRequestResult } from "../scm/types.js";
|
|
2
|
-
export type VersionaryPluginCapability = "scm.reviewRequest" | "scm.releaseMetadata";
|
|
1
|
+
import type { ScmClientContext, ScmProvider, ScmReleaseMetadataInput, ScmReleaseMetadataResult, ScmReleaseReferenceCommentsInput, ScmReleaseReferenceCommentsResult, ScmReviewRequestInput, ScmReviewRequestResult } from "../scm/types.js";
|
|
2
|
+
export type VersionaryPluginCapability = "scm.reviewRequest" | "scm.releaseMetadata" | "scm.releaseReferenceComments";
|
|
3
3
|
export type VersionaryScmReviewRequestInput = ScmReviewRequestInput;
|
|
4
4
|
export type VersionaryScmReviewRequestResult = ScmReviewRequestResult;
|
|
5
5
|
export type VersionaryScmReleaseMetadataInput = ScmReleaseMetadataInput;
|
|
6
6
|
export type VersionaryScmReleaseMetadataResult = ScmReleaseMetadataResult;
|
|
7
|
+
export type VersionaryScmReleaseReferenceCommentsInput = ScmReleaseReferenceCommentsInput;
|
|
8
|
+
export type VersionaryScmReleaseReferenceCommentsResult = ScmReleaseReferenceCommentsResult;
|
|
7
9
|
export type VersionaryPluginContext = ScmClientContext;
|
|
8
10
|
export interface VersionaryPluginRuntime {
|
|
9
11
|
name: string;
|
|
@@ -11,4 +13,5 @@ export interface VersionaryPluginRuntime {
|
|
|
11
13
|
provider?: ScmProvider;
|
|
12
14
|
createOrUpdateReviewRequest?: (input: VersionaryScmReviewRequestInput, context: VersionaryPluginContext) => Promise<VersionaryScmReviewRequestResult>;
|
|
13
15
|
createReleaseMetadata?: (input: VersionaryScmReleaseMetadataInput, context: VersionaryPluginContext) => Promise<VersionaryScmReleaseMetadataResult>;
|
|
16
|
+
createReleaseReferenceComments?: (input: VersionaryScmReleaseReferenceCommentsInput, context: VersionaryPluginContext) => Promise<VersionaryScmReleaseReferenceCommentsResult>;
|
|
14
17
|
}
|