versionary 0.16.0 → 0.18.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 +13 -5
- package/dist/config/load-config.js +30 -0
- package/dist/git/commits.js +10 -1
- package/dist/release/changelog.d.ts +7 -1
- package/dist/release/changelog.js +18 -8
- package/dist/release/pr.d.ts +7 -0
- package/dist/release/pr.js +39 -19
- package/dist/release/recovery.d.ts +1 -0
- package/dist/release/release.js +1 -0
- package/dist/scm/github-plugin.js +63 -0
- package/dist/scm/types.d.ts +12 -0
- package/dist/strategy/resolve.js +6 -1
- package/package.json +3 -3
package/dist/cli/index.js
CHANGED
|
@@ -99,6 +99,9 @@ async function main() {
|
|
|
99
99
|
}
|
|
100
100
|
const plan = (0, plan_js_1.createReleasePlan)();
|
|
101
101
|
if (!plan.nextVersion) {
|
|
102
|
+
if (!flags["dry-run"]) {
|
|
103
|
+
await (0, pr_js_1.closeStaleReviewRequestIfExists)(process.cwd(), { logger });
|
|
104
|
+
}
|
|
102
105
|
const message = "No releasable commits found. Nothing to do.";
|
|
103
106
|
if (flags.json) {
|
|
104
107
|
emitJson({
|
|
@@ -203,12 +206,17 @@ async function main() {
|
|
|
203
206
|
return 0;
|
|
204
207
|
}
|
|
205
208
|
if (command === "pr") {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (!
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
const plan = (0, plan_js_1.createReleasePlan)();
|
|
210
|
+
if (!plan.nextVersion) {
|
|
211
|
+
if (!flags["dry-run"]) {
|
|
212
|
+
await (0, pr_js_1.closeStaleReviewRequestIfExists)(process.cwd(), {
|
|
213
|
+
logger: console,
|
|
214
|
+
});
|
|
211
215
|
}
|
|
216
|
+
console.log("No releasable commits found. Nothing to do.");
|
|
217
|
+
return 0;
|
|
218
|
+
}
|
|
219
|
+
if (flags["dry-run"]) {
|
|
212
220
|
console.log(`Dry run: would prepare release PR branch ${plan.releaseBranchPrefix} for ${plan.nextVersion}`);
|
|
213
221
|
return 0;
|
|
214
222
|
}
|
|
@@ -8,6 +8,7 @@ exports.loadConfig = loadConfig;
|
|
|
8
8
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
10
|
const jsonc_parser_1 = require("jsonc-parser");
|
|
11
|
+
const resolve_js_1 = require("../strategy/resolve.js");
|
|
11
12
|
const schema_js_1 = require("./schema.js");
|
|
12
13
|
const SUPPORTED_FILES = [
|
|
13
14
|
{ file: "versionary.jsonc", format: "jsonc" },
|
|
@@ -22,6 +23,34 @@ function parseConfig(raw, format) {
|
|
|
22
23
|
function isRecord(value) {
|
|
23
24
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
24
25
|
}
|
|
26
|
+
function validateReleaseTypes(config) {
|
|
27
|
+
try {
|
|
28
|
+
(0, resolve_js_1.resolveVersionStrategy)(config);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error instanceof Error) {
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
const known = (0, resolve_js_1.listKnownReleaseTypes)().join(", ");
|
|
35
|
+
throw new Error(`Unsupported release-type. Supported release types: ${known}.`);
|
|
36
|
+
}
|
|
37
|
+
for (const [packagePath, packageConfig] of Object.entries(config.packages ?? {})) {
|
|
38
|
+
const packageReleaseType = packageConfig["release-type"];
|
|
39
|
+
if (!packageReleaseType) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
(0, resolve_js_1.resolveVersionStrategy)({ ...config, "release-type": packageReleaseType });
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (error instanceof Error) {
|
|
47
|
+
throw new Error(`${error.message} (in packages["${packagePath}"])`);
|
|
48
|
+
}
|
|
49
|
+
const known = (0, resolve_js_1.listKnownReleaseTypes)().join(", ");
|
|
50
|
+
throw new Error(`Unsupported release-type in packages["${packagePath}"]. Supported release types: ${known}.`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
25
54
|
function findConfigFile(cwd) {
|
|
26
55
|
for (const candidate of SUPPORTED_FILES) {
|
|
27
56
|
const candidatePath = node_path_1.default.join(cwd, candidate.file);
|
|
@@ -45,6 +74,7 @@ function loadConfig(cwd = process.cwd()) {
|
|
|
45
74
|
throw new Error('The "plugins" config key is no longer supported. Versionary uses built-in integrations only.');
|
|
46
75
|
}
|
|
47
76
|
const validated = schema_js_1.configSchema.parse(parsed);
|
|
77
|
+
validateReleaseTypes(validated);
|
|
48
78
|
return {
|
|
49
79
|
path: found.path,
|
|
50
80
|
format: found.format,
|
package/dist/git/commits.js
CHANGED
|
@@ -437,17 +437,26 @@ function applyRevertSuppression(commits) {
|
|
|
437
437
|
}
|
|
438
438
|
const presentShas = new Set(commits.map((commit) => commit.hash.toLowerCase()));
|
|
439
439
|
const reverted = new Set();
|
|
440
|
+
const suppressedReverts = new Set();
|
|
440
441
|
for (const commit of commits) {
|
|
441
442
|
if (!commit.isRevert) {
|
|
442
443
|
continue;
|
|
443
444
|
}
|
|
445
|
+
const revertsOnlyInWindow = commit.revertedShas.length > 0 &&
|
|
446
|
+
commit.revertedShas.every((sha) => presentShas.has(sha));
|
|
447
|
+
if (revertsOnlyInWindow) {
|
|
448
|
+
suppressedReverts.add(commit.hash.toLowerCase());
|
|
449
|
+
}
|
|
444
450
|
for (const sha of commit.revertedShas) {
|
|
445
451
|
if (presentShas.has(sha)) {
|
|
446
452
|
reverted.add(sha);
|
|
447
453
|
}
|
|
448
454
|
}
|
|
449
455
|
}
|
|
450
|
-
return commits.filter((commit) =>
|
|
456
|
+
return commits.filter((commit) => {
|
|
457
|
+
const hash = commit.hash.toLowerCase();
|
|
458
|
+
return !reverted.has(hash) && !suppressedReverts.has(hash);
|
|
459
|
+
});
|
|
451
460
|
}
|
|
452
461
|
function analyzeParsedCommits(commits) {
|
|
453
462
|
let result = null;
|
|
@@ -12,8 +12,14 @@ export declare function renderSimpleReleaseNotes(input: {
|
|
|
12
12
|
}>;
|
|
13
13
|
}, options?: {
|
|
14
14
|
includeFooter?: boolean;
|
|
15
|
+
headerLabel?: string;
|
|
16
|
+
}): string;
|
|
17
|
+
export declare function renderReviewRequestFooter(): string;
|
|
18
|
+
export declare function renderReleasePlanChangelog(plan: ReleasePlan, options?: {
|
|
19
|
+
headerLabel?: string;
|
|
20
|
+
includeFooter?: boolean;
|
|
21
|
+
cwd?: string;
|
|
15
22
|
}): string;
|
|
16
|
-
export declare function renderReleasePlanChangelog(plan: ReleasePlan): string;
|
|
17
23
|
/** @deprecated Use renderReleasePlanChangelog. */
|
|
18
24
|
export declare function renderSimpleChangelog(plan: SimplePlan): string;
|
|
19
25
|
export declare function renderPackageChangelogSection(input: {
|
|
@@ -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.renderReviewRequestFooter = renderReviewRequestFooter;
|
|
7
8
|
exports.renderReleasePlanChangelog = renderReleasePlanChangelog;
|
|
8
9
|
exports.renderSimpleChangelog = renderSimpleChangelog;
|
|
9
10
|
exports.renderPackageChangelogSection = renderPackageChangelogSection;
|
|
@@ -13,6 +14,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
13
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
14
15
|
const commits_js_1 = require("../git/commits.js");
|
|
15
16
|
const repo_url_js_1 = require("../git/repo-url.js");
|
|
17
|
+
const REVIEW_REQUEST_FOOTER = "---\n\nThis PR was generated by [Versionary](https://github.com/jolars/versionary).";
|
|
16
18
|
function formatDate() {
|
|
17
19
|
return new Date().toISOString().slice(0, 10);
|
|
18
20
|
}
|
|
@@ -75,6 +77,7 @@ function groupCommitLines(commits, repoUrl) {
|
|
|
75
77
|
const features = [];
|
|
76
78
|
const fixes = [];
|
|
77
79
|
const reverts = [];
|
|
80
|
+
const effectiveCommits = (0, commits_js_1.applyRevertSuppression)(commits);
|
|
78
81
|
const getRevertedSubject = (commit) => {
|
|
79
82
|
const normalizedDescription = (commit.description ?? "")
|
|
80
83
|
.trim()
|
|
@@ -97,7 +100,7 @@ function groupCommitLines(commits, repoUrl) {
|
|
|
97
100
|
const revertedCommit = (0, commits_js_1.parseConventionalCommitMessage)(revertedSubject);
|
|
98
101
|
return (0, commits_js_1.inferReleaseTypeFromParsedCommit)(revertedCommit) !== null;
|
|
99
102
|
};
|
|
100
|
-
for (const commit of
|
|
103
|
+
for (const commit of effectiveCommits) {
|
|
101
104
|
const type = (0, commits_js_1.inferReleaseTypeFromParsedCommit)(commit);
|
|
102
105
|
if (!type) {
|
|
103
106
|
continue;
|
|
@@ -136,9 +139,10 @@ function groupCommitLines(commits, repoUrl) {
|
|
|
136
139
|
}
|
|
137
140
|
function renderSimpleReleaseNotes(input, options = {}) {
|
|
138
141
|
const repoUrl = (0, repo_url_js_1.resolveRepositoryWebBaseUrl)(input.cwd ?? process.cwd());
|
|
142
|
+
const headerLabel = options.headerLabel ?? input.nextVersion;
|
|
139
143
|
const header = repoUrl
|
|
140
|
-
? `## [${
|
|
141
|
-
: `## ${
|
|
144
|
+
? `## [${headerLabel}](${repoUrl}/compare/v${input.currentVersion}...v${input.nextVersion}) (${formatDate()})`
|
|
145
|
+
: `## ${headerLabel} (${formatDate()})`;
|
|
142
146
|
const grouped = groupCommitLines(input.commits, repoUrl);
|
|
143
147
|
const sections = [];
|
|
144
148
|
if (grouped.breaking.length > 0) {
|
|
@@ -156,13 +160,16 @@ function renderSimpleReleaseNotes(input, options = {}) {
|
|
|
156
160
|
if (input.dependencies && input.dependencies.length > 0) {
|
|
157
161
|
sections.push("### Dependencies", ...input.dependencies.map((dependency) => `- updated ${dependency.name} to v${dependency.version}`), "");
|
|
158
162
|
}
|
|
159
|
-
const
|
|
163
|
+
const body = [header, "", ...sections].join("\n").trimEnd();
|
|
160
164
|
if (options.includeFooter) {
|
|
161
|
-
|
|
165
|
+
return `${body}\n\n${renderReviewRequestFooter()}`;
|
|
162
166
|
}
|
|
163
|
-
return
|
|
167
|
+
return body;
|
|
168
|
+
}
|
|
169
|
+
function renderReviewRequestFooter() {
|
|
170
|
+
return REVIEW_REQUEST_FOOTER;
|
|
164
171
|
}
|
|
165
|
-
function renderReleasePlanChangelog(plan) {
|
|
172
|
+
function renderReleasePlanChangelog(plan, options = {}) {
|
|
166
173
|
if (!plan.nextVersion) {
|
|
167
174
|
return "";
|
|
168
175
|
}
|
|
@@ -194,8 +201,11 @@ function renderReleasePlanChangelog(plan) {
|
|
|
194
201
|
currentVersion: plan.currentVersion,
|
|
195
202
|
nextVersion: plan.nextVersion,
|
|
196
203
|
commits: dedupedCommits,
|
|
197
|
-
cwd: process.cwd(),
|
|
204
|
+
cwd: options.cwd ?? process.cwd(),
|
|
198
205
|
dependencies,
|
|
206
|
+
}, {
|
|
207
|
+
includeFooter: options.includeFooter,
|
|
208
|
+
headerLabel: options.headerLabel,
|
|
199
209
|
});
|
|
200
210
|
}
|
|
201
211
|
/** @deprecated Use renderReleasePlanChangelog. */
|
package/dist/release/pr.d.ts
CHANGED
|
@@ -20,6 +20,13 @@ export declare function renderSimpleReviewRequestBody(version: string, previousV
|
|
|
20
20
|
export declare function openOrUpdateReviewRequest(cwd: string, branch: string, title: string, version: string, previousVersion: string, commits: ParsedCommit[], plan?: SimplePlan | null, options?: {
|
|
21
21
|
logger?: VersionaryPluginContext["logger"];
|
|
22
22
|
}): Promise<string>;
|
|
23
|
+
export declare function closeStaleReviewRequestIfExists(cwd?: string, options?: {
|
|
24
|
+
logger?: VersionaryPluginContext["logger"];
|
|
25
|
+
}): Promise<{
|
|
26
|
+
closed: boolean;
|
|
27
|
+
url?: string;
|
|
28
|
+
number?: number;
|
|
29
|
+
}>;
|
|
23
30
|
/** @deprecated Use prepareReleasePr. */
|
|
24
31
|
export declare function prepareSimpleReleasePr(cwd?: string, options?: {
|
|
25
32
|
logger?: VersionaryPluginContext["logger"];
|
package/dist/release/pr.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.splitSafeDirtyFiles = splitSafeDirtyFiles;
|
|
|
7
7
|
exports.prepareReleasePr = prepareReleasePr;
|
|
8
8
|
exports.renderSimpleReviewRequestBody = renderSimpleReviewRequestBody;
|
|
9
9
|
exports.openOrUpdateReviewRequest = openOrUpdateReviewRequest;
|
|
10
|
+
exports.closeStaleReviewRequestIfExists = closeStaleReviewRequestIfExists;
|
|
10
11
|
exports.prepareSimpleReleasePr = prepareSimpleReleasePr;
|
|
11
12
|
exports.openOrUpdateSimpleReviewRequest = openOrUpdateSimpleReviewRequest;
|
|
12
13
|
exports.pushReleaseBranch = pushReleaseBranch;
|
|
@@ -348,25 +349,15 @@ function renderSimpleReviewRequestBody(version, previousVersion, commits, plan =
|
|
|
348
349
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
349
350
|
return directSources;
|
|
350
351
|
};
|
|
351
|
-
const relabelSectionHeader = (notes, packageLabel, nextVersion) => {
|
|
352
|
-
const linkedHeader = notes.match(/^##\s+\[([^\]]+)\]\(([^)]+)\)\s+\(([^)]+)\)/u);
|
|
353
|
-
if (linkedHeader) {
|
|
354
|
-
const [, , compareUrl, date] = linkedHeader;
|
|
355
|
-
return notes.replace(/^##\s+\[[^\]]+\]\([^)]+\)\s+\([^)]+\)/u, `## [${packageLabel}: ${nextVersion}](${compareUrl}) (${date})`);
|
|
356
|
-
}
|
|
357
|
-
const plainHeader = notes.match(/^##\s+([^\s]+)\s+\(([^)]+)\)/u);
|
|
358
|
-
if (plainHeader) {
|
|
359
|
-
const [, , date] = plainHeader;
|
|
360
|
-
return notes.replace(/^##\s+[^\s]+\s+\([^)]+\)/u, `## ${packageLabel}: ${nextVersion} (${date})`);
|
|
361
|
-
}
|
|
362
|
-
return notes;
|
|
363
|
-
};
|
|
364
352
|
if (plan?.packages && plan.packages.length > 1) {
|
|
365
353
|
const sections = [];
|
|
366
354
|
const rootPackage = plan.packages.find((pkg) => pkg.path === "." && pkg.nextVersion);
|
|
367
355
|
if (rootPackage?.nextVersion) {
|
|
368
|
-
const rootNotes = (0, changelog_js_1.renderReleasePlanChangelog)(plan
|
|
369
|
-
|
|
356
|
+
const rootNotes = (0, changelog_js_1.renderReleasePlanChangelog)(plan, {
|
|
357
|
+
headerLabel: `${formatPackageLabel(".")}: ${rootPackage.nextVersion}`,
|
|
358
|
+
cwd,
|
|
359
|
+
});
|
|
360
|
+
sections.push(rootNotes);
|
|
370
361
|
}
|
|
371
362
|
const packageSections = plan.packages
|
|
372
363
|
.filter((pkg) => pkg.path !== "." && pkg.nextVersion)
|
|
@@ -379,15 +370,18 @@ function renderSimpleReviewRequestBody(version, previousVersion, commits, plan =
|
|
|
379
370
|
commits: pkg.commits,
|
|
380
371
|
cwd,
|
|
381
372
|
dependencies: propagatedDependencies,
|
|
382
|
-
}, {
|
|
383
|
-
|
|
373
|
+
}, {
|
|
374
|
+
includeFooter: false,
|
|
375
|
+
headerLabel: `${packageLabel}: ${pkg.nextVersion ?? ""}`,
|
|
376
|
+
});
|
|
377
|
+
return notes;
|
|
384
378
|
});
|
|
385
379
|
sections.push(...packageSections);
|
|
386
380
|
const bodySections = sections.join("\n\n");
|
|
387
381
|
if (bodySections.length === 0) {
|
|
388
|
-
return
|
|
382
|
+
return (0, changelog_js_1.renderReviewRequestFooter)();
|
|
389
383
|
}
|
|
390
|
-
return `${bodySections}\n\
|
|
384
|
+
return `${bodySections}\n\n${(0, changelog_js_1.renderReviewRequestFooter)()}`;
|
|
391
385
|
}
|
|
392
386
|
return (0, changelog_js_1.renderSimpleReleaseNotes)({
|
|
393
387
|
currentVersion: previousVersion,
|
|
@@ -415,6 +409,32 @@ async function openOrUpdateReviewRequest(cwd, branch, title, version, previousVe
|
|
|
415
409
|
});
|
|
416
410
|
return result.url;
|
|
417
411
|
}
|
|
412
|
+
function hasScmRuntimeContext() {
|
|
413
|
+
const hasRepository = Boolean(process.env.GITHUB_REPOSITORY);
|
|
414
|
+
const hasToken = Boolean(process.env.VERSIONARY_PR_TOKEN ??
|
|
415
|
+
process.env.GH_TOKEN ??
|
|
416
|
+
process.env.GITHUB_TOKEN);
|
|
417
|
+
return hasRepository && hasToken;
|
|
418
|
+
}
|
|
419
|
+
async function closeStaleReviewRequestIfExists(cwd = process.cwd(), options = {}) {
|
|
420
|
+
if (!hasScmRuntimeContext()) {
|
|
421
|
+
return { closed: false };
|
|
422
|
+
}
|
|
423
|
+
const plan = (0, plan_js_1.createReleasePlan)(cwd);
|
|
424
|
+
const scmClient = (0, client_js_1.getScmClient)();
|
|
425
|
+
const result = await scmClient.closeReviewRequestIfExists({
|
|
426
|
+
baseBranch: process.env.VERSIONARY_BASE_BRANCH ?? "main",
|
|
427
|
+
headBranch: plan.releaseBranchPrefix,
|
|
428
|
+
reason: "Closing stale release PR because no releasable commits remain for the current baseline/tag state.",
|
|
429
|
+
}, {
|
|
430
|
+
cwd,
|
|
431
|
+
logger: options.logger,
|
|
432
|
+
});
|
|
433
|
+
if (result.closed && result.number) {
|
|
434
|
+
options.logger?.info(`Closed stale release review request #${result.number} for ${plan.releaseBranchPrefix}.`);
|
|
435
|
+
}
|
|
436
|
+
return result;
|
|
437
|
+
}
|
|
418
438
|
/** @deprecated Use prepareReleasePr. */
|
|
419
439
|
function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
420
440
|
return prepareReleasePr(cwd, options);
|
|
@@ -5,6 +5,7 @@ export interface ReleaseTargetInput {
|
|
|
5
5
|
version: string;
|
|
6
6
|
notes: string;
|
|
7
7
|
draft?: boolean;
|
|
8
|
+
makeLatest?: "true" | "false" | "legacy";
|
|
8
9
|
}
|
|
9
10
|
export interface ReleaseExecutionContext {
|
|
10
11
|
createReleaseMetadata: (input: ReleaseTargetInput) => Promise<VersionaryScmReleaseMetadataResult>;
|
package/dist/release/release.js
CHANGED
|
@@ -183,6 +183,7 @@ async function runReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
|
183
183
|
version: target.version,
|
|
184
184
|
notes: releaseNotes,
|
|
185
185
|
draft: loaded.config["release-draft"] ?? false,
|
|
186
|
+
makeLatest: target.path === "." ? "true" : "false",
|
|
186
187
|
}, {
|
|
187
188
|
createReleaseMetadata: (input) => scmClient.createReleaseMetadata(input, {
|
|
188
189
|
cwd,
|
|
@@ -174,6 +174,68 @@ function createGitHubPlugin() {
|
|
|
174
174
|
state: toReviewRequestState(created, `pull request #${created.number} in ${repoRef(repo)}`),
|
|
175
175
|
};
|
|
176
176
|
},
|
|
177
|
+
async closeReviewRequestIfExists(input, _context) {
|
|
178
|
+
const repo = getRepoFromEnv();
|
|
179
|
+
const octokit = new rest_1.Octokit({ auth: getGitHubToken() });
|
|
180
|
+
const listHead = resolveHeadForList(repo, input.headBranch);
|
|
181
|
+
let existing;
|
|
182
|
+
try {
|
|
183
|
+
const response = await octokit.pulls.list({
|
|
184
|
+
owner: repo.owner,
|
|
185
|
+
repo: repo.repo,
|
|
186
|
+
state: "open",
|
|
187
|
+
head: listHead,
|
|
188
|
+
base: input.baseBranch,
|
|
189
|
+
per_page: 100,
|
|
190
|
+
});
|
|
191
|
+
existing = response.data;
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
const { message } = parseGitHubError(error);
|
|
195
|
+
throw new Error(`Failed listing open pull requests for branch "${input.headBranch}" into "${input.baseBranch}": [${repoRef(repo)}] ${message}`);
|
|
196
|
+
}
|
|
197
|
+
if (existing.length > 1) {
|
|
198
|
+
const matches = existing.map((item) => `#${item.number}`).join(", ");
|
|
199
|
+
throw new Error(`Ambiguous open pull request matches for "${input.headBranch}" into "${input.baseBranch}": [${repoRef(repo)}] ${matches}`);
|
|
200
|
+
}
|
|
201
|
+
if (existing.length === 0) {
|
|
202
|
+
return { closed: false };
|
|
203
|
+
}
|
|
204
|
+
const pr = existing[0];
|
|
205
|
+
let updated;
|
|
206
|
+
try {
|
|
207
|
+
const response = await octokit.pulls.update({
|
|
208
|
+
owner: repo.owner,
|
|
209
|
+
repo: repo.repo,
|
|
210
|
+
pull_number: pr.number,
|
|
211
|
+
state: "closed",
|
|
212
|
+
});
|
|
213
|
+
updated = response.data;
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
const { message } = parseGitHubError(error);
|
|
217
|
+
throw new Error(`Failed closing pull request #${pr.number}: [${repoRef(repo)} base=${input.baseBranch} head=${input.headBranch}] ${message}`);
|
|
218
|
+
}
|
|
219
|
+
try {
|
|
220
|
+
await octokit.issues.createComment({
|
|
221
|
+
owner: repo.owner,
|
|
222
|
+
repo: repo.repo,
|
|
223
|
+
issue_number: pr.number,
|
|
224
|
+
body: input.reason,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
const { status, message } = parseGitHubError(error);
|
|
229
|
+
if (status !== 404 && status !== 410) {
|
|
230
|
+
throw new Error(`Failed commenting on closed pull request #${pr.number}: [${repoRef(repo)} base=${input.baseBranch} head=${input.headBranch}] ${message}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
closed: true,
|
|
235
|
+
number: updated.number,
|
|
236
|
+
url: updated.html_url,
|
|
237
|
+
};
|
|
238
|
+
},
|
|
177
239
|
async createReleaseMetadata(input, _context) {
|
|
178
240
|
const repo = getRepoFromEnv();
|
|
179
241
|
const octokit = new rest_1.Octokit({ auth: getGitHubToken() });
|
|
@@ -200,6 +262,7 @@ function createGitHubPlugin() {
|
|
|
200
262
|
name: input.tag,
|
|
201
263
|
body: input.notes,
|
|
202
264
|
draft: input.draft ?? false,
|
|
265
|
+
make_latest: input.makeLatest,
|
|
203
266
|
});
|
|
204
267
|
data = response.data;
|
|
205
268
|
}
|
package/dist/scm/types.d.ts
CHANGED
|
@@ -20,11 +20,22 @@ export interface ScmReviewRequestResult {
|
|
|
20
20
|
url: string;
|
|
21
21
|
state: "open" | "closed" | "merged";
|
|
22
22
|
}
|
|
23
|
+
export interface ScmCloseReviewRequestInput {
|
|
24
|
+
baseBranch: string;
|
|
25
|
+
headBranch: string;
|
|
26
|
+
reason: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ScmCloseReviewRequestResult {
|
|
29
|
+
closed: boolean;
|
|
30
|
+
number?: number;
|
|
31
|
+
url?: string;
|
|
32
|
+
}
|
|
23
33
|
export interface ScmReleaseMetadataInput {
|
|
24
34
|
tag: string;
|
|
25
35
|
version: string;
|
|
26
36
|
notes: string;
|
|
27
37
|
draft?: boolean;
|
|
38
|
+
makeLatest?: "true" | "false" | "legacy";
|
|
28
39
|
}
|
|
29
40
|
export interface ScmReleaseMetadataResult {
|
|
30
41
|
url: string;
|
|
@@ -42,6 +53,7 @@ export interface ScmReleaseReferenceCommentsResult {
|
|
|
42
53
|
export interface ScmClient {
|
|
43
54
|
provider: ScmProvider;
|
|
44
55
|
createOrUpdateReviewRequest: (input: ScmReviewRequestInput, context: ScmClientContext) => Promise<ScmReviewRequestResult>;
|
|
56
|
+
closeReviewRequestIfExists: (input: ScmCloseReviewRequestInput, context: ScmClientContext) => Promise<ScmCloseReviewRequestResult>;
|
|
45
57
|
createReleaseMetadata: (input: ScmReleaseMetadataInput, context: ScmClientContext) => Promise<ScmReleaseMetadataResult>;
|
|
46
58
|
createReleaseReferenceComments?: (input: ScmReleaseReferenceCommentsInput, context: ScmClientContext) => Promise<ScmReleaseReferenceCommentsResult>;
|
|
47
59
|
}
|
package/dist/strategy/resolve.js
CHANGED
|
@@ -19,5 +19,10 @@ function listKnownReleaseTypes() {
|
|
|
19
19
|
}
|
|
20
20
|
function resolveVersionStrategy(config) {
|
|
21
21
|
const releaseType = config["release-type"] ?? "simple";
|
|
22
|
-
|
|
22
|
+
const strategy = strategyRegistry[releaseType];
|
|
23
|
+
if (!strategy) {
|
|
24
|
+
const known = listKnownReleaseTypes().join(", ");
|
|
25
|
+
throw new Error(`Unsupported release-type "${releaseType}". Supported release types: ${known}.`);
|
|
26
|
+
}
|
|
27
|
+
return strategy;
|
|
23
28
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "versionary",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Automatic release framework based on conventional commits and semantic versioning",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"releasing",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
"zod": "^4.1.12"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@types/node": "^
|
|
37
|
+
"@types/node": "^25.6.0",
|
|
38
38
|
"tsx": "^4.20.6",
|
|
39
|
-
"typescript": "^
|
|
39
|
+
"typescript": "^6.0.3",
|
|
40
40
|
"vitest": "^4.1.4"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|