versionary 0.27.0 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action/index.js +7 -9
- package/dist/cli/index.js +32 -34
- package/dist/config/load-config.js +16 -23
- package/dist/config/schema.js +45 -48
- package/dist/git/commits.js +23 -42
- package/dist/git/identity.js +7 -11
- package/dist/git/repo-url.js +3 -6
- package/dist/index.js +6 -16
- package/dist/release/artifact-rules.js +15 -21
- package/dist/release/changelog.js +24 -35
- package/dist/release/plan.js +34 -43
- package/dist/release/pr.js +72 -96
- package/dist/release/recovery.js +9 -12
- package/dist/release/release.d.ts +1 -0
- package/dist/release/release.js +60 -56
- package/dist/release/semver.js +5 -12
- package/dist/release/state.js +22 -31
- package/dist/release/verify-project.js +14 -20
- package/dist/scm/capabilities.js +2 -6
- package/dist/scm/client.js +3 -6
- package/dist/scm/github-plugin.js +46 -13
- package/dist/scm/types.d.ts +6 -1
- package/dist/scm/types.js +1 -2
- package/dist/strategy/composite.js +1 -4
- package/dist/strategy/latex.js +18 -24
- package/dist/strategy/node.js +13 -19
- package/dist/strategy/package-context.d.ts +1 -0
- package/dist/strategy/package-context.js +14 -13
- package/dist/strategy/python.js +35 -41
- package/dist/strategy/r.js +16 -22
- package/dist/strategy/resolve.js +16 -20
- package/dist/strategy/rust.js +80 -89
- package/dist/strategy/simple.js +8 -14
- package/dist/strategy/types.js +1 -2
- package/dist/types/config.js +1 -2
- package/dist/types/plugins.js +1 -2
- package/package.json +3 -3
package/dist/action/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const node_crypto_1 = require("node:crypto");
|
|
5
|
-
const node_fs_1 = require("node:fs");
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { appendFileSync } from "node:fs";
|
|
6
4
|
function getInput(name) {
|
|
7
5
|
const canonical = `INPUT_${name.replace(/ /g, "_").toUpperCase()}`;
|
|
8
6
|
const underscoreAlias = canonical.replace(/-/g, "_");
|
|
@@ -12,7 +10,7 @@ function getInput(name) {
|
|
|
12
10
|
"").trim();
|
|
13
11
|
}
|
|
14
12
|
function runGit(cwd, args) {
|
|
15
|
-
return
|
|
13
|
+
return execFileSync("git", args, {
|
|
16
14
|
cwd,
|
|
17
15
|
encoding: "utf8",
|
|
18
16
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -55,8 +53,8 @@ function setOutput(name, value) {
|
|
|
55
53
|
if (!outputPath) {
|
|
56
54
|
throw new Error("GITHUB_OUTPUT is not set.");
|
|
57
55
|
}
|
|
58
|
-
const delimiter = `versionary-${
|
|
59
|
-
|
|
56
|
+
const delimiter = `versionary-${randomUUID()}`;
|
|
57
|
+
appendFileSync(outputPath, `${name}<<${delimiter}\n${value}\n${delimiter}\n`, "utf8");
|
|
60
58
|
}
|
|
61
59
|
function main() {
|
|
62
60
|
const token = getInput("token") || getInput("github-token");
|
|
@@ -120,7 +118,7 @@ function main() {
|
|
|
120
118
|
return;
|
|
121
119
|
}
|
|
122
120
|
}
|
|
123
|
-
const raw =
|
|
121
|
+
const raw = execFileSync("npx", ["--yes", `versionary@${versionaryVersion}`, "run", "--json"], {
|
|
124
122
|
cwd,
|
|
125
123
|
encoding: "utf8",
|
|
126
124
|
stdio: ["ignore", "pipe", "pipe"],
|
package/dist/cli/index.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const release_js_1 = require("../release/release.js");
|
|
10
|
-
const verify_project_js_1 = require("../release/verify-project.js");
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import { loadConfig } from "../config/load-config.js";
|
|
4
|
+
import { prependChangelog, renderReleasePlanChangelog, } from "../release/changelog.js";
|
|
5
|
+
import { createReleasePlan } from "../release/plan.js";
|
|
6
|
+
import { closeStaleReviewRequestIfExists, consumeNextReleaseFile, isReleaseCommitMessage, openOrUpdateReviewRequest, prepareReleasePr, pushReleaseBranch, readNextReleaseHighlights, } from "../release/pr.js";
|
|
7
|
+
import { runRelease, runReleaseDetailed } from "../release/release.js";
|
|
8
|
+
import { verifyProject } from "../release/verify-project.js";
|
|
11
9
|
function printVerifyResult() {
|
|
12
|
-
const result =
|
|
10
|
+
const result = verifyProject();
|
|
13
11
|
const categories = [
|
|
14
12
|
{ key: "config", title: "Config" },
|
|
15
13
|
{ key: "paths", title: "Paths" },
|
|
@@ -47,13 +45,13 @@ async function main() {
|
|
|
47
45
|
const flags = parseFlags(args);
|
|
48
46
|
const logger = flags.json ? undefined : console;
|
|
49
47
|
if (!command || command === "run") {
|
|
50
|
-
const commitMessage =
|
|
48
|
+
const commitMessage = execFileSync("git", ["log", "-1", "--pretty=%B"], {
|
|
51
49
|
encoding: "utf8",
|
|
52
50
|
stdio: ["ignore", "pipe", "ignore"],
|
|
53
51
|
}).trim();
|
|
54
|
-
if (
|
|
52
|
+
if (isReleaseCommitMessage(commitMessage)) {
|
|
55
53
|
if (flags["dry-run"] && !flags.json) {
|
|
56
|
-
const release = await
|
|
54
|
+
const release = await runReleaseDetailed(process.cwd(), {
|
|
57
55
|
logger,
|
|
58
56
|
"dry-run": true,
|
|
59
57
|
});
|
|
@@ -63,7 +61,7 @@ async function main() {
|
|
|
63
61
|
}
|
|
64
62
|
}
|
|
65
63
|
if (flags.json) {
|
|
66
|
-
const release = await
|
|
64
|
+
const release = await runReleaseDetailed(process.cwd(), {
|
|
67
65
|
logger,
|
|
68
66
|
"dry-run": flags["dry-run"],
|
|
69
67
|
});
|
|
@@ -94,14 +92,14 @@ async function main() {
|
|
|
94
92
|
});
|
|
95
93
|
return 0;
|
|
96
94
|
}
|
|
97
|
-
const message = await
|
|
95
|
+
const message = await runRelease(process.cwd());
|
|
98
96
|
console.log(message);
|
|
99
97
|
return 0;
|
|
100
98
|
}
|
|
101
|
-
const plan =
|
|
99
|
+
const plan = createReleasePlan();
|
|
102
100
|
if (!plan.nextVersion) {
|
|
103
101
|
if (!flags["dry-run"]) {
|
|
104
|
-
await
|
|
102
|
+
await closeStaleReviewRequestIfExists(process.cwd(), { logger });
|
|
105
103
|
}
|
|
106
104
|
const message = "No releasable commits found. Nothing to do.";
|
|
107
105
|
if (flags.json) {
|
|
@@ -144,7 +142,7 @@ async function main() {
|
|
|
144
142
|
console.log(dryRunMessage);
|
|
145
143
|
return 0;
|
|
146
144
|
}
|
|
147
|
-
const pr =
|
|
145
|
+
const pr = prepareReleasePr(process.cwd(), { logger });
|
|
148
146
|
if (!pr.updated) {
|
|
149
147
|
const message = `Release PR branch ${pr.branch} is already up to date.`;
|
|
150
148
|
if (flags.json) {
|
|
@@ -162,8 +160,8 @@ async function main() {
|
|
|
162
160
|
console.log(`Title: ${pr.title}`);
|
|
163
161
|
return 0;
|
|
164
162
|
}
|
|
165
|
-
|
|
166
|
-
const reviewResult = await
|
|
163
|
+
pushReleaseBranch(process.cwd(), pr.branch);
|
|
164
|
+
const reviewResult = await openOrUpdateReviewRequest(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan, { logger, highlights: pr.highlights });
|
|
167
165
|
const message = `Prepared release PR branch ${pr.branch}`;
|
|
168
166
|
if (flags.json) {
|
|
169
167
|
emitJson({
|
|
@@ -186,37 +184,37 @@ async function main() {
|
|
|
186
184
|
return printVerifyResult();
|
|
187
185
|
}
|
|
188
186
|
if (command === "plan") {
|
|
189
|
-
const plan =
|
|
187
|
+
const plan = createReleasePlan();
|
|
190
188
|
console.log(JSON.stringify(plan, null, 2));
|
|
191
189
|
return 0;
|
|
192
190
|
}
|
|
193
191
|
if (command === "changelog") {
|
|
194
192
|
const write = args.includes("--write");
|
|
195
|
-
const plan =
|
|
193
|
+
const plan = createReleasePlan();
|
|
196
194
|
if (!plan.nextVersion) {
|
|
197
195
|
console.log("No releasable commits found.");
|
|
198
196
|
return 0;
|
|
199
197
|
}
|
|
200
|
-
const loaded =
|
|
201
|
-
const highlightsRead =
|
|
198
|
+
const loaded = loadConfig();
|
|
199
|
+
const highlightsRead = readNextReleaseHighlights(process.cwd(), loaded.config);
|
|
202
200
|
const highlights = highlightsRead?.content ?? "";
|
|
203
|
-
const section =
|
|
201
|
+
const section = renderReleasePlanChangelog(plan, { highlights });
|
|
204
202
|
if (!write) {
|
|
205
203
|
console.log(section);
|
|
206
204
|
return 0;
|
|
207
205
|
}
|
|
208
|
-
|
|
206
|
+
prependChangelog(process.cwd(), plan.changelogFile, section, plan.changelogFormat);
|
|
209
207
|
if (highlightsRead) {
|
|
210
|
-
|
|
208
|
+
consumeNextReleaseFile(process.cwd(), highlightsRead.filePath);
|
|
211
209
|
}
|
|
212
210
|
console.log(`Updated ${plan.changelogFile}`);
|
|
213
211
|
return 0;
|
|
214
212
|
}
|
|
215
213
|
if (command === "pr") {
|
|
216
|
-
const plan =
|
|
214
|
+
const plan = createReleasePlan();
|
|
217
215
|
if (!plan.nextVersion) {
|
|
218
216
|
if (!flags["dry-run"]) {
|
|
219
|
-
await
|
|
217
|
+
await closeStaleReviewRequestIfExists(process.cwd(), {
|
|
220
218
|
logger: console,
|
|
221
219
|
});
|
|
222
220
|
}
|
|
@@ -227,14 +225,14 @@ async function main() {
|
|
|
227
225
|
console.log(`Dry run: would prepare release PR branch ${plan.releaseBranchPrefix} for ${plan.nextVersion}`);
|
|
228
226
|
return 0;
|
|
229
227
|
}
|
|
230
|
-
const pr =
|
|
228
|
+
const pr = prepareReleasePr(process.cwd(), { logger: console });
|
|
231
229
|
if (!pr.updated) {
|
|
232
230
|
console.log(`Release PR branch ${pr.branch} is already up to date.`);
|
|
233
231
|
console.log(`Title: ${pr.title}`);
|
|
234
232
|
return 0;
|
|
235
233
|
}
|
|
236
|
-
|
|
237
|
-
const reviewResult = await
|
|
234
|
+
pushReleaseBranch(process.cwd(), pr.branch);
|
|
235
|
+
const reviewResult = await openOrUpdateReviewRequest(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan, { highlights: pr.highlights });
|
|
238
236
|
console.log(`Prepared release PR branch ${pr.branch}`);
|
|
239
237
|
console.log(`Title: ${pr.title}`);
|
|
240
238
|
console.log(reviewResult);
|
|
@@ -242,7 +240,7 @@ async function main() {
|
|
|
242
240
|
}
|
|
243
241
|
if (command === "release") {
|
|
244
242
|
if (flags["dry-run"]) {
|
|
245
|
-
const result = await
|
|
243
|
+
const result = await runReleaseDetailed(process.cwd(), {
|
|
246
244
|
logger,
|
|
247
245
|
"dry-run": true,
|
|
248
246
|
});
|
|
@@ -257,7 +255,7 @@ async function main() {
|
|
|
257
255
|
}
|
|
258
256
|
return 0;
|
|
259
257
|
}
|
|
260
|
-
const message = await
|
|
258
|
+
const message = await runRelease(process.cwd());
|
|
261
259
|
console.log(message);
|
|
262
260
|
return 0;
|
|
263
261
|
}
|
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
exports.findConfigFile = findConfigFile;
|
|
7
|
-
exports.loadConfig = loadConfig;
|
|
8
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
-
const jsonc_parser_1 = require("jsonc-parser");
|
|
11
|
-
const resolve_js_1 = require("../strategy/resolve.js");
|
|
12
|
-
const schema_js_1 = require("./schema.js");
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { parse as parseJsonc } from "jsonc-parser";
|
|
4
|
+
import { listKnownReleaseTypes, resolveVersionStrategy, } from "../strategy/resolve.js";
|
|
5
|
+
import { configSchema } from "./schema.js";
|
|
13
6
|
const SUPPORTED_FILES = [
|
|
14
7
|
{ file: "versionary.jsonc", format: "jsonc" },
|
|
15
8
|
{ file: "versionary.json", format: "json" },
|
|
16
9
|
];
|
|
17
10
|
function parseConfig(raw, format) {
|
|
18
11
|
if (format === "json" || format === "jsonc") {
|
|
19
|
-
return (
|
|
12
|
+
return parseJsonc(raw);
|
|
20
13
|
}
|
|
21
14
|
throw new Error("Unsupported config format. Use versionary.jsonc or versionary.json.");
|
|
22
15
|
}
|
|
@@ -25,13 +18,13 @@ function isRecord(value) {
|
|
|
25
18
|
}
|
|
26
19
|
function validateReleaseTypes(config) {
|
|
27
20
|
try {
|
|
28
|
-
|
|
21
|
+
resolveVersionStrategy(config);
|
|
29
22
|
}
|
|
30
23
|
catch (error) {
|
|
31
24
|
if (error instanceof Error) {
|
|
32
25
|
throw error;
|
|
33
26
|
}
|
|
34
|
-
const known =
|
|
27
|
+
const known = listKnownReleaseTypes().join(", ");
|
|
35
28
|
throw new Error(`Unsupported release-type. Supported release types: ${known}.`);
|
|
36
29
|
}
|
|
37
30
|
for (const [packagePath, packageConfig] of Object.entries(config.packages ?? {})) {
|
|
@@ -40,32 +33,32 @@ function validateReleaseTypes(config) {
|
|
|
40
33
|
continue;
|
|
41
34
|
}
|
|
42
35
|
try {
|
|
43
|
-
|
|
36
|
+
resolveVersionStrategy({ ...config, "release-type": packageReleaseType });
|
|
44
37
|
}
|
|
45
38
|
catch (error) {
|
|
46
39
|
if (error instanceof Error) {
|
|
47
40
|
throw new Error(`${error.message} (in packages["${packagePath}"])`);
|
|
48
41
|
}
|
|
49
|
-
const known =
|
|
42
|
+
const known = listKnownReleaseTypes().join(", ");
|
|
50
43
|
throw new Error(`Unsupported release-type in packages["${packagePath}"]. Supported release types: ${known}.`);
|
|
51
44
|
}
|
|
52
45
|
}
|
|
53
46
|
}
|
|
54
|
-
function findConfigFile(cwd) {
|
|
47
|
+
export function findConfigFile(cwd) {
|
|
55
48
|
for (const candidate of SUPPORTED_FILES) {
|
|
56
|
-
const candidatePath =
|
|
57
|
-
if (
|
|
49
|
+
const candidatePath = path.join(cwd, candidate.file);
|
|
50
|
+
if (fs.existsSync(candidatePath)) {
|
|
58
51
|
return { path: candidatePath, format: candidate.format };
|
|
59
52
|
}
|
|
60
53
|
}
|
|
61
54
|
return null;
|
|
62
55
|
}
|
|
63
|
-
function loadConfig(cwd = process.cwd()) {
|
|
56
|
+
export function loadConfig(cwd = process.cwd()) {
|
|
64
57
|
const found = findConfigFile(cwd);
|
|
65
58
|
if (!found) {
|
|
66
59
|
throw new Error("No Versionary config found. Create versionary.jsonc (preferred) or versionary.json.");
|
|
67
60
|
}
|
|
68
|
-
const raw =
|
|
61
|
+
const raw = fs.readFileSync(found.path, "utf8");
|
|
69
62
|
const parsed = parseConfig(raw, found.format);
|
|
70
63
|
if (!isRecord(parsed)) {
|
|
71
64
|
throw new Error("Invalid config: expected an object at the root.");
|
|
@@ -73,7 +66,7 @@ function loadConfig(cwd = process.cwd()) {
|
|
|
73
66
|
if (Object.hasOwn(parsed, "plugins")) {
|
|
74
67
|
throw new Error('The "plugins" config key is no longer supported. Versionary uses built-in integrations only.');
|
|
75
68
|
}
|
|
76
|
-
const validated =
|
|
69
|
+
const validated = configSchema.parse(parsed);
|
|
77
70
|
validateReleaseTypes(validated);
|
|
78
71
|
return {
|
|
79
72
|
path: found.path,
|
package/dist/config/schema.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.configSchema = void 0;
|
|
4
|
-
const zod_1 = require("zod");
|
|
5
|
-
const artifactRuleSchema = zod_1.z
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const artifactRuleSchema = z
|
|
6
3
|
.object({
|
|
7
|
-
type:
|
|
8
|
-
path:
|
|
9
|
-
"field-path":
|
|
10
|
-
jsonpath:
|
|
11
|
-
pattern:
|
|
4
|
+
type: z.enum(["json", "toml", "yaml", "nix", "regex"]),
|
|
5
|
+
path: z.string().min(1),
|
|
6
|
+
"field-path": z.string().optional(),
|
|
7
|
+
jsonpath: z.string().optional(),
|
|
8
|
+
pattern: z.string().optional(),
|
|
12
9
|
})
|
|
13
10
|
.superRefine((value, ctx) => {
|
|
14
11
|
const needsJsonPath = value.type === "json" ||
|
|
@@ -18,77 +15,77 @@ const artifactRuleSchema = zod_1.z
|
|
|
18
15
|
const hasFieldPath = Boolean(value["field-path"] ?? value.jsonpath);
|
|
19
16
|
if (needsJsonPath && !hasFieldPath) {
|
|
20
17
|
ctx.addIssue({
|
|
21
|
-
code:
|
|
18
|
+
code: z.ZodIssueCode.custom,
|
|
22
19
|
message: `${value.type} artifact rules require "field-path" (or deprecated "jsonpath").`,
|
|
23
20
|
path: ["field-path"],
|
|
24
21
|
});
|
|
25
22
|
}
|
|
26
23
|
if (needsJsonPath && value.pattern) {
|
|
27
24
|
ctx.addIssue({
|
|
28
|
-
code:
|
|
25
|
+
code: z.ZodIssueCode.custom,
|
|
29
26
|
message: `${value.type} artifact rules do not support "pattern".`,
|
|
30
27
|
path: ["pattern"],
|
|
31
28
|
});
|
|
32
29
|
}
|
|
33
30
|
if (value["field-path"] && value.jsonpath) {
|
|
34
31
|
ctx.addIssue({
|
|
35
|
-
code:
|
|
32
|
+
code: z.ZodIssueCode.custom,
|
|
36
33
|
message: 'Specify only one of "field-path" or deprecated "jsonpath".',
|
|
37
34
|
path: ["field-path"],
|
|
38
35
|
});
|
|
39
36
|
}
|
|
40
37
|
if (value.type === "regex" && !value.pattern) {
|
|
41
38
|
ctx.addIssue({
|
|
42
|
-
code:
|
|
39
|
+
code: z.ZodIssueCode.custom,
|
|
43
40
|
message: 'regex artifact rules require "pattern".',
|
|
44
41
|
path: ["pattern"],
|
|
45
42
|
});
|
|
46
43
|
}
|
|
47
44
|
if (value.type === "regex" && (value["field-path"] || value.jsonpath)) {
|
|
48
45
|
ctx.addIssue({
|
|
49
|
-
code:
|
|
46
|
+
code: z.ZodIssueCode.custom,
|
|
50
47
|
message: 'regex artifact rules do not support "field-path" or deprecated "jsonpath".',
|
|
51
48
|
path: ["field-path"],
|
|
52
49
|
});
|
|
53
50
|
}
|
|
54
51
|
});
|
|
55
|
-
const packageSchema =
|
|
52
|
+
const packageSchema = z
|
|
56
53
|
.object({
|
|
57
|
-
"release-type":
|
|
58
|
-
.union([
|
|
54
|
+
"release-type": z
|
|
55
|
+
.union([z.string().min(1), z.array(z.string().min(1)).min(1)])
|
|
59
56
|
.optional(),
|
|
60
|
-
"package-name":
|
|
61
|
-
"changelog-file":
|
|
62
|
-
"changelog-format":
|
|
63
|
-
"exclude-paths":
|
|
64
|
-
"extra-files":
|
|
65
|
-
follows:
|
|
57
|
+
"package-name": z.string().optional(),
|
|
58
|
+
"changelog-file": z.string().optional(),
|
|
59
|
+
"changelog-format": z.enum(["markdown-changelog", "r-news"]).optional(),
|
|
60
|
+
"exclude-paths": z.array(z.string()).optional(),
|
|
61
|
+
"extra-files": z.array(artifactRuleSchema).optional(),
|
|
62
|
+
follows: z.array(z.string().min(1)).optional(),
|
|
66
63
|
})
|
|
67
64
|
.strict();
|
|
68
|
-
|
|
65
|
+
export const configSchema = z
|
|
69
66
|
.object({
|
|
70
|
-
$schema:
|
|
71
|
-
version:
|
|
72
|
-
"review-mode":
|
|
73
|
-
"version-file":
|
|
74
|
-
"changelog-file":
|
|
75
|
-
"changelog-format":
|
|
76
|
-
"release-draft":
|
|
77
|
-
"release-reference-comments":
|
|
67
|
+
$schema: z.string().optional(),
|
|
68
|
+
version: z.literal(1),
|
|
69
|
+
"review-mode": z.enum(["direct", "pr", "review"]).optional(),
|
|
70
|
+
"version-file": z.string().optional(),
|
|
71
|
+
"changelog-file": z.string().optional(),
|
|
72
|
+
"changelog-format": z.enum(["markdown-changelog", "r-news"]).optional(),
|
|
73
|
+
"release-draft": z.boolean().optional(),
|
|
74
|
+
"release-reference-comments": z
|
|
78
75
|
.enum(["off", "best-effort", "strict"])
|
|
79
76
|
.optional(),
|
|
80
|
-
"release-branch":
|
|
81
|
-
"baseline-file":
|
|
82
|
-
"next-release-file":
|
|
83
|
-
"bootstrap-sha":
|
|
84
|
-
"monorepo-mode":
|
|
85
|
-
"bump-minor-pre-major":
|
|
86
|
-
"allow-stable-major":
|
|
87
|
-
"include-commit-authors":
|
|
88
|
-
"release-type":
|
|
89
|
-
.union([
|
|
77
|
+
"release-branch": z.string().optional(),
|
|
78
|
+
"baseline-file": z.string().optional(),
|
|
79
|
+
"next-release-file": z.string().optional(),
|
|
80
|
+
"bootstrap-sha": z.string().optional(),
|
|
81
|
+
"monorepo-mode": z.enum(["independent", "fixed"]).optional(),
|
|
82
|
+
"bump-minor-pre-major": z.boolean().optional(),
|
|
83
|
+
"allow-stable-major": z.boolean().optional(),
|
|
84
|
+
"include-commit-authors": z.boolean().optional(),
|
|
85
|
+
"release-type": z
|
|
86
|
+
.union([z.string().min(1), z.array(z.string().min(1)).min(1)])
|
|
90
87
|
.optional(),
|
|
91
|
-
packages:
|
|
88
|
+
packages: z.record(z.string().min(1), packageSchema).optional(),
|
|
92
89
|
})
|
|
93
90
|
.strict()
|
|
94
91
|
.superRefine((value, ctx) => {
|
|
@@ -107,7 +104,7 @@ exports.configSchema = zod_1.z
|
|
|
107
104
|
for (const sourcePath of follows) {
|
|
108
105
|
if (sourcePath === packagePath) {
|
|
109
106
|
ctx.addIssue({
|
|
110
|
-
code:
|
|
107
|
+
code: z.ZodIssueCode.custom,
|
|
111
108
|
message: `Package "${packagePath}" cannot follow itself.`,
|
|
112
109
|
path: ["packages", packagePath, "follows"],
|
|
113
110
|
});
|
|
@@ -115,7 +112,7 @@ exports.configSchema = zod_1.z
|
|
|
115
112
|
}
|
|
116
113
|
if (!knownPaths.has(sourcePath)) {
|
|
117
114
|
ctx.addIssue({
|
|
118
|
-
code:
|
|
115
|
+
code: z.ZodIssueCode.custom,
|
|
119
116
|
message: `Package "${packagePath}" follows unknown package "${sourcePath}".`,
|
|
120
117
|
path: ["packages", packagePath, "follows"],
|
|
121
118
|
});
|
|
@@ -125,7 +122,7 @@ exports.configSchema = zod_1.z
|
|
|
125
122
|
if (followsByPath.size > 0 && value["monorepo-mode"] === "fixed") {
|
|
126
123
|
for (const followerPath of followsByPath.keys()) {
|
|
127
124
|
ctx.addIssue({
|
|
128
|
-
code:
|
|
125
|
+
code: z.ZodIssueCode.custom,
|
|
129
126
|
message: 'Package "follows" cannot be combined with monorepo-mode "fixed" (fixed mode already pins all package versions together).',
|
|
130
127
|
path: ["packages", followerPath, "follows"],
|
|
131
128
|
});
|
|
@@ -169,7 +166,7 @@ exports.configSchema = zod_1.z
|
|
|
169
166
|
}
|
|
170
167
|
reportedCycles.add(key);
|
|
171
168
|
ctx.addIssue({
|
|
172
|
-
code:
|
|
169
|
+
code: z.ZodIssueCode.custom,
|
|
173
170
|
message: `Package "follows" cycle detected: ${cycle.join(" -> ")}.`,
|
|
174
171
|
path: ["packages", cycle[0] ?? followerPath, "follows"],
|
|
175
172
|
});
|
package/dist/git/commits.js
CHANGED
|
@@ -1,26 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.parseConventionalCommitMessage = parseConventionalCommitMessage;
|
|
7
|
-
exports.parseConventionalCommitMessageDetailed = parseConventionalCommitMessageDetailed;
|
|
8
|
-
exports.getCommitsSinceLastTag = getCommitsSinceLastTag;
|
|
9
|
-
exports.getCommitsForPath = getCommitsForPath;
|
|
10
|
-
exports.getParsedCommitsSinceLastTag = getParsedCommitsSinceLastTag;
|
|
11
|
-
exports.getParsedCommitsForPath = getParsedCommitsForPath;
|
|
12
|
-
exports.inferReleaseTypeFromParsedCommit = inferReleaseTypeFromParsedCommit;
|
|
13
|
-
exports.inferReleaseTypeFromSubject = inferReleaseTypeFromSubject;
|
|
14
|
-
exports.isReleasableCommit = isReleasableCommit;
|
|
15
|
-
exports.getCommitParseDiagnostics = getCommitParseDiagnostics;
|
|
16
|
-
exports.analyzeCommits = analyzeCommits;
|
|
17
|
-
exports.applyRevertSuppression = applyRevertSuppression;
|
|
18
|
-
exports.analyzeParsedCommits = analyzeParsedCommits;
|
|
19
|
-
exports.isReleasableParsedCommit = isReleasableParsedCommit;
|
|
20
|
-
const node_child_process_1 = require("node:child_process");
|
|
21
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import path from "node:path";
|
|
22
3
|
function getReleaseBranchExcludeArgs(cwd) {
|
|
23
|
-
const releaseBranchesRaw =
|
|
4
|
+
const releaseBranchesRaw = execFileSync("git", ["branch", "--list", "--format", "%(refname:short)"], {
|
|
24
5
|
cwd,
|
|
25
6
|
encoding: "utf8",
|
|
26
7
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -42,7 +23,7 @@ function getLatestReleaseTag(cwd) {
|
|
|
42
23
|
"v[0-9]*",
|
|
43
24
|
...excludeArgs,
|
|
44
25
|
];
|
|
45
|
-
return
|
|
26
|
+
return execFileSync("git", cmd, {
|
|
46
27
|
cwd,
|
|
47
28
|
encoding: "utf8",
|
|
48
29
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -54,7 +35,7 @@ function getLatestReleaseTag(cwd) {
|
|
|
54
35
|
}
|
|
55
36
|
function isValidCommitish(cwd, ref) {
|
|
56
37
|
try {
|
|
57
|
-
|
|
38
|
+
execFileSync("git", ["rev-parse", "--verify", `${ref}^{commit}`], {
|
|
58
39
|
cwd,
|
|
59
40
|
stdio: ["ignore", "pipe", "ignore"],
|
|
60
41
|
});
|
|
@@ -77,7 +58,7 @@ function resolveRange(cwd, baselineSha) {
|
|
|
77
58
|
return latestTag ? `${latestTag}..HEAD` : "HEAD";
|
|
78
59
|
}
|
|
79
60
|
function readGitLog(cwd, range, pathspecs = []) {
|
|
80
|
-
const output =
|
|
61
|
+
const output = execFileSync("git", ["log", range, "--pretty=format:%H%x09%s", "--", ...pathspecs], {
|
|
81
62
|
cwd,
|
|
82
63
|
encoding: "utf8",
|
|
83
64
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -96,7 +77,7 @@ function readGitLog(cwd, range, pathspecs = []) {
|
|
|
96
77
|
function readGitLogFull(cwd, range, pathspecs = []) {
|
|
97
78
|
const recordSeparator = "\x1e";
|
|
98
79
|
const fieldSeparator = "\x1f";
|
|
99
|
-
const output =
|
|
80
|
+
const output = execFileSync("git", [
|
|
100
81
|
"log",
|
|
101
82
|
range,
|
|
102
83
|
`--pretty=format:%H${fieldSeparator}%s${fieldSeparator}%b${recordSeparator}`,
|
|
@@ -344,17 +325,17 @@ function parseCommitMessage(hash, subject, body) {
|
|
|
344
325
|
diagnostics,
|
|
345
326
|
};
|
|
346
327
|
}
|
|
347
|
-
function parseConventionalCommitMessage(subject, body = "") {
|
|
328
|
+
export function parseConventionalCommitMessage(subject, body = "") {
|
|
348
329
|
return parseCommitMessage("", subject.trim(), body.trim());
|
|
349
330
|
}
|
|
350
|
-
function parseConventionalCommitMessageDetailed(header, body = "") {
|
|
331
|
+
export function parseConventionalCommitMessageDetailed(header, body = "") {
|
|
351
332
|
return parseCommitMessage("", header.trim(), body.trim());
|
|
352
333
|
}
|
|
353
|
-
function getCommitsSinceLastTag(cwd = process.cwd(), baselineSha) {
|
|
334
|
+
export function getCommitsSinceLastTag(cwd = process.cwd(), baselineSha) {
|
|
354
335
|
const range = resolveRange(cwd, baselineSha);
|
|
355
336
|
return readGitLog(cwd, range);
|
|
356
337
|
}
|
|
357
|
-
function getCommitsForPath(cwd = process.cwd(), baselineSha, packagePath = ".", excludePaths = []) {
|
|
338
|
+
export function getCommitsForPath(cwd = process.cwd(), baselineSha, packagePath = ".", excludePaths = []) {
|
|
358
339
|
const range = resolveRange(cwd, baselineSha);
|
|
359
340
|
const normalizedPackagePath = packagePath === "." ? "." : packagePath;
|
|
360
341
|
const excludes = excludePaths.flatMap((excludePath) => {
|
|
@@ -363,16 +344,16 @@ function getCommitsForPath(cwd = process.cwd(), baselineSha, packagePath = ".",
|
|
|
363
344
|
.replace(/\/+$/u, "");
|
|
364
345
|
const combined = normalizedPackagePath === "."
|
|
365
346
|
? normalizedExcludePath
|
|
366
|
-
:
|
|
347
|
+
: path.posix.join(normalizedPackagePath, normalizedExcludePath);
|
|
367
348
|
return [`:(exclude)${combined}`, `:(exclude)${combined}/**`];
|
|
368
349
|
});
|
|
369
350
|
return readGitLog(cwd, range, [normalizedPackagePath, ...excludes]);
|
|
370
351
|
}
|
|
371
|
-
function getParsedCommitsSinceLastTag(cwd = process.cwd(), baselineSha) {
|
|
352
|
+
export function getParsedCommitsSinceLastTag(cwd = process.cwd(), baselineSha) {
|
|
372
353
|
const range = resolveRange(cwd, baselineSha);
|
|
373
354
|
return readGitLogFull(cwd, range);
|
|
374
355
|
}
|
|
375
|
-
function getParsedCommitsForPath(cwd = process.cwd(), baselineSha, packagePath = ".", excludePaths = []) {
|
|
356
|
+
export function getParsedCommitsForPath(cwd = process.cwd(), baselineSha, packagePath = ".", excludePaths = []) {
|
|
376
357
|
const range = resolveRange(cwd, baselineSha);
|
|
377
358
|
const normalizedPackagePath = packagePath === "." ? "." : packagePath;
|
|
378
359
|
const excludes = excludePaths.flatMap((excludePath) => {
|
|
@@ -381,12 +362,12 @@ function getParsedCommitsForPath(cwd = process.cwd(), baselineSha, packagePath =
|
|
|
381
362
|
.replace(/\/+$/u, "");
|
|
382
363
|
const combined = normalizedPackagePath === "."
|
|
383
364
|
? normalizedExcludePath
|
|
384
|
-
:
|
|
365
|
+
: path.posix.join(normalizedPackagePath, normalizedExcludePath);
|
|
385
366
|
return [`:(exclude)${combined}`, `:(exclude)${combined}/**`];
|
|
386
367
|
});
|
|
387
368
|
return readGitLogFull(cwd, range, [normalizedPackagePath, ...excludes]);
|
|
388
369
|
}
|
|
389
|
-
function inferReleaseTypeFromParsedCommit(commit) {
|
|
370
|
+
export function inferReleaseTypeFromParsedCommit(commit) {
|
|
390
371
|
if (commit.isBreaking) {
|
|
391
372
|
return "major";
|
|
392
373
|
}
|
|
@@ -405,16 +386,16 @@ function inferReleaseTypeFromParsedCommit(commit) {
|
|
|
405
386
|
}
|
|
406
387
|
return null;
|
|
407
388
|
}
|
|
408
|
-
function inferReleaseTypeFromSubject(subject) {
|
|
389
|
+
export function inferReleaseTypeFromSubject(subject) {
|
|
409
390
|
return inferReleaseTypeFromParsedCommit(parseCommitMessage("", subject.trim(), ""));
|
|
410
391
|
}
|
|
411
|
-
function isReleasableCommit(subject) {
|
|
392
|
+
export function isReleasableCommit(subject) {
|
|
412
393
|
return inferReleaseTypeFromSubject(subject) !== null;
|
|
413
394
|
}
|
|
414
|
-
function getCommitParseDiagnostics(commit) {
|
|
395
|
+
export function getCommitParseDiagnostics(commit) {
|
|
415
396
|
return commit.diagnostics ?? [];
|
|
416
397
|
}
|
|
417
|
-
function analyzeCommits(commits) {
|
|
398
|
+
export function analyzeCommits(commits) {
|
|
418
399
|
let result = null;
|
|
419
400
|
for (const commit of commits) {
|
|
420
401
|
const type = inferReleaseTypeFromSubject(commit.subject);
|
|
@@ -431,7 +412,7 @@ function analyzeCommits(commits) {
|
|
|
431
412
|
}
|
|
432
413
|
return result;
|
|
433
414
|
}
|
|
434
|
-
function applyRevertSuppression(commits) {
|
|
415
|
+
export function applyRevertSuppression(commits) {
|
|
435
416
|
if (commits.length === 0) {
|
|
436
417
|
return commits;
|
|
437
418
|
}
|
|
@@ -458,7 +439,7 @@ function applyRevertSuppression(commits) {
|
|
|
458
439
|
return !reverted.has(hash) && !suppressedReverts.has(hash);
|
|
459
440
|
});
|
|
460
441
|
}
|
|
461
|
-
function analyzeParsedCommits(commits) {
|
|
442
|
+
export function analyzeParsedCommits(commits) {
|
|
462
443
|
let result = null;
|
|
463
444
|
const effectiveCommits = applyRevertSuppression(commits);
|
|
464
445
|
for (const commit of effectiveCommits) {
|
|
@@ -476,6 +457,6 @@ function analyzeParsedCommits(commits) {
|
|
|
476
457
|
}
|
|
477
458
|
return result;
|
|
478
459
|
}
|
|
479
|
-
function isReleasableParsedCommit(commit) {
|
|
460
|
+
export function isReleasableParsedCommit(commit) {
|
|
480
461
|
return inferReleaseTypeFromParsedCommit(commit) !== null;
|
|
481
462
|
}
|