versionary 0.6.0 → 0.8.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 +4 -0
- package/dist/action/index.d.ts +1 -0
- package/dist/action/index.js +121 -0
- package/dist/app/release/artifact-rules.js +45 -24
- package/dist/app/release/pr.d.ts +1 -1
- package/dist/app/release/pr.js +29 -3
- package/dist/app/release/release.js +4 -4
- package/dist/cli/index.js +2 -2
- package/dist/config/schema.d.ts +1 -0
- package/dist/config/schema.js +15 -6
- package/dist/types/config.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -125,6 +125,8 @@ Current rust auto-update behavior (phase scope):
|
|
|
125
125
|
- updates crate versions in each targeted crate `[package].version`
|
|
126
126
|
- updates internal workspace dependency versions when the dependency name
|
|
127
127
|
matches another targeted crate name
|
|
128
|
+
- refreshes `Cargo.lock` via `cargo generate-lockfile` when `Cargo.lock` exists
|
|
129
|
+
in repo root
|
|
128
130
|
- applies dependency version rewrites in:
|
|
129
131
|
- `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`
|
|
130
132
|
- `[target.*.dependencies]`, `[target.*.dev-dependencies]`,
|
|
@@ -137,6 +139,8 @@ Current rust non-goals/limits:
|
|
|
137
139
|
- does not add missing `version = ...` fields to dependency inline tables
|
|
138
140
|
- does not perform Cargo publish/release to crates.io
|
|
139
141
|
|
|
142
|
+
If `Cargo.lock` exists, `cargo` must be available in PATH during PR preparation.
|
|
143
|
+
|
|
140
144
|
### Monorepo release names and tag naming
|
|
141
145
|
|
|
142
146
|
For independent monorepo targets, Versionary derives release tags as:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const node_child_process_1 = require("node:child_process");
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
function getInput(name) {
|
|
7
|
+
const canonical = `INPUT_${name.replace(/ /g, "_").toUpperCase()}`;
|
|
8
|
+
const underscoreAlias = canonical.replace(/-/g, "_");
|
|
9
|
+
return (process.env[canonical] ??
|
|
10
|
+
process.env[underscoreAlias] ??
|
|
11
|
+
process.env[`INPUT_${name.toUpperCase()}`] ??
|
|
12
|
+
"").trim();
|
|
13
|
+
}
|
|
14
|
+
function runGit(cwd, args) {
|
|
15
|
+
return (0, node_child_process_1.execFileSync)("git", args, {
|
|
16
|
+
cwd,
|
|
17
|
+
encoding: "utf8",
|
|
18
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
19
|
+
}).trim();
|
|
20
|
+
}
|
|
21
|
+
function hasGitConfig(cwd, key) {
|
|
22
|
+
try {
|
|
23
|
+
runGit(cwd, ["config", key]);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function hasOriginRemote(cwd) {
|
|
31
|
+
try {
|
|
32
|
+
runGit(cwd, ["remote", "get-url", "origin"]);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function setOutput(name, value) {
|
|
40
|
+
const outputPath = process.env.GITHUB_OUTPUT;
|
|
41
|
+
if (!outputPath) {
|
|
42
|
+
throw new Error("GITHUB_OUTPUT is not set.");
|
|
43
|
+
}
|
|
44
|
+
const delimiter = `versionary-${(0, node_crypto_1.randomUUID)()}`;
|
|
45
|
+
(0, node_fs_1.appendFileSync)(outputPath, `${name}<<${delimiter}\n${value}\n${delimiter}\n`, "utf8");
|
|
46
|
+
}
|
|
47
|
+
function main() {
|
|
48
|
+
const token = getInput("token") || getInput("github-token");
|
|
49
|
+
if (!token) {
|
|
50
|
+
throw new Error("Input required and not supplied: token (or deprecated github-token).");
|
|
51
|
+
}
|
|
52
|
+
const versionaryVersion = getInput("versionary-version") || "0.7.0";
|
|
53
|
+
const cwd = getInput("working-directory") || ".";
|
|
54
|
+
process.chdir(cwd);
|
|
55
|
+
if (!hasGitConfig(cwd, "user.name")) {
|
|
56
|
+
runGit(cwd, ["config", "user.name", "github-actions[bot]"]);
|
|
57
|
+
}
|
|
58
|
+
if (!hasGitConfig(cwd, "user.email")) {
|
|
59
|
+
runGit(cwd, [
|
|
60
|
+
"config",
|
|
61
|
+
"user.email",
|
|
62
|
+
"41898282+github-actions[bot]@users.noreply.github.com",
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
if (hasOriginRemote(cwd)) {
|
|
66
|
+
const serverUrl = process.env.GITHUB_SERVER_URL ?? "https://github.com";
|
|
67
|
+
const repository = process.env.GITHUB_REPOSITORY;
|
|
68
|
+
if (!repository) {
|
|
69
|
+
throw new Error("GITHUB_REPOSITORY is not set.");
|
|
70
|
+
}
|
|
71
|
+
const base = serverUrl.replace(/^https?:\/\//u, "");
|
|
72
|
+
const encodedToken = encodeURIComponent(token);
|
|
73
|
+
runGit(cwd, [
|
|
74
|
+
"remote",
|
|
75
|
+
"set-url",
|
|
76
|
+
"origin",
|
|
77
|
+
`https://x-access-token:${encodedToken}@${base}/${repository}.git`,
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
const raw = (0, node_child_process_1.execFileSync)("npx", ["--yes", `versionary@${versionaryVersion}`, "run", "--json"], {
|
|
81
|
+
cwd,
|
|
82
|
+
encoding: "utf8",
|
|
83
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
84
|
+
env: {
|
|
85
|
+
...process.env,
|
|
86
|
+
GITHUB_TOKEN: token,
|
|
87
|
+
},
|
|
88
|
+
}).trim();
|
|
89
|
+
if (!raw) {
|
|
90
|
+
throw new Error("Versionary returned empty JSON output.");
|
|
91
|
+
}
|
|
92
|
+
process.stdout.write(`${raw}\n`);
|
|
93
|
+
let payload;
|
|
94
|
+
try {
|
|
95
|
+
payload = JSON.parse(raw);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
throw new Error(`Failed parsing Versionary JSON output: ${error instanceof Error ? error.message : String(error)}`);
|
|
99
|
+
}
|
|
100
|
+
const tagNames = Array.isArray(payload.tagNames)
|
|
101
|
+
? payload.tagNames.filter((value) => typeof value === "string")
|
|
102
|
+
: [];
|
|
103
|
+
const firstTag = tagNames[0] ?? "";
|
|
104
|
+
const releaseCreated = payload.releaseCreated === true || tagNames.length > 0 ? "true" : "false";
|
|
105
|
+
setOutput("action", payload.action ?? "");
|
|
106
|
+
setOutput("message", payload.message ?? "");
|
|
107
|
+
setOutput("release_created", releaseCreated);
|
|
108
|
+
setOutput("tag_name", firstTag);
|
|
109
|
+
setOutput("tag_names", JSON.stringify(tagNames));
|
|
110
|
+
setOutput("review_url", payload.reviewUrl ?? "");
|
|
111
|
+
setOutput("branch", payload.branch ?? "");
|
|
112
|
+
setOutput("title", payload.title ?? "");
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
main();
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
119
|
+
process.stderr.write(`${message}\n`);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
@@ -11,25 +11,25 @@ const yaml_1 = __importDefault(require("yaml"));
|
|
|
11
11
|
function isRecord(value) {
|
|
12
12
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
13
13
|
}
|
|
14
|
-
function
|
|
15
|
-
if (!
|
|
16
|
-
throw new Error(`Invalid
|
|
14
|
+
function parseFieldPath(fieldPath) {
|
|
15
|
+
if (!fieldPath.startsWith("$")) {
|
|
16
|
+
throw new Error(`Invalid field-path "${fieldPath}". Must start with "$".`);
|
|
17
17
|
}
|
|
18
18
|
const tokens = [];
|
|
19
19
|
let index = 1;
|
|
20
|
-
while (index <
|
|
21
|
-
const current =
|
|
20
|
+
while (index < fieldPath.length) {
|
|
21
|
+
const current = fieldPath[index];
|
|
22
22
|
if (current === ".") {
|
|
23
|
-
const keyMatch =
|
|
23
|
+
const keyMatch = fieldPath.slice(index + 1).match(/^[A-Za-z0-9_-]+/u);
|
|
24
24
|
if (!keyMatch) {
|
|
25
|
-
throw new Error(`Invalid
|
|
25
|
+
throw new Error(`Invalid field-path "${fieldPath}" near index ${index}.`);
|
|
26
26
|
}
|
|
27
27
|
tokens.push(keyMatch[0]);
|
|
28
28
|
index += 1 + keyMatch[0].length;
|
|
29
29
|
continue;
|
|
30
30
|
}
|
|
31
31
|
if (current === "[") {
|
|
32
|
-
const rest =
|
|
32
|
+
const rest = fieldPath.slice(index + 1);
|
|
33
33
|
const numberMatch = rest.match(/^(\d+)\]/u);
|
|
34
34
|
if (numberMatch) {
|
|
35
35
|
tokens.push(Number(numberMatch[1]));
|
|
@@ -42,53 +42,60 @@ function parseJsonPath(jsonpath) {
|
|
|
42
42
|
index += 4 + keyMatch[1].length;
|
|
43
43
|
continue;
|
|
44
44
|
}
|
|
45
|
-
throw new Error(`Invalid
|
|
45
|
+
throw new Error(`Invalid field-path "${fieldPath}" near index ${index}.`);
|
|
46
46
|
}
|
|
47
|
-
throw new Error(`Invalid
|
|
47
|
+
throw new Error(`Invalid field-path "${fieldPath}" near index ${index}.`);
|
|
48
48
|
}
|
|
49
49
|
if (tokens.length === 0) {
|
|
50
|
-
throw new Error(`Invalid
|
|
50
|
+
throw new Error(`Invalid field-path "${fieldPath}". Path must target a field.`);
|
|
51
51
|
}
|
|
52
52
|
return tokens;
|
|
53
53
|
}
|
|
54
|
-
function setVersionAtJsonPath(document,
|
|
55
|
-
const tokens =
|
|
54
|
+
function setVersionAtJsonPath(document, fieldPath, version) {
|
|
55
|
+
const tokens = parseFieldPath(fieldPath);
|
|
56
56
|
let cursor = document;
|
|
57
57
|
for (let index = 0; index < tokens.length - 1; index += 1) {
|
|
58
58
|
const token = tokens[index];
|
|
59
59
|
if (typeof token === "number") {
|
|
60
60
|
if (!Array.isArray(cursor) || token >= cursor.length) {
|
|
61
|
-
throw new Error(`
|
|
61
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
62
62
|
}
|
|
63
63
|
cursor = cursor[token];
|
|
64
64
|
continue;
|
|
65
65
|
}
|
|
66
66
|
if (!isRecord(cursor) || !(token in cursor)) {
|
|
67
|
-
throw new Error(`
|
|
67
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
68
68
|
}
|
|
69
69
|
cursor = cursor[token];
|
|
70
70
|
}
|
|
71
71
|
const leaf = tokens.at(-1);
|
|
72
72
|
if (typeof leaf === "number") {
|
|
73
73
|
if (!Array.isArray(cursor) || leaf >= cursor.length) {
|
|
74
|
-
throw new Error(`
|
|
74
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
75
75
|
}
|
|
76
76
|
const current = cursor[leaf];
|
|
77
77
|
if (typeof current !== "string" && typeof current !== "number") {
|
|
78
|
-
throw new Error(`
|
|
78
|
+
throw new Error(`field-path "${fieldPath}" must point to a string or number field for version updates.`);
|
|
79
79
|
}
|
|
80
80
|
cursor[leaf] = version;
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
83
|
if (!isRecord(cursor) || !(leaf in cursor)) {
|
|
84
|
-
throw new Error(`
|
|
84
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
85
85
|
}
|
|
86
86
|
const current = cursor[leaf];
|
|
87
87
|
if (typeof current !== "string" && typeof current !== "number") {
|
|
88
|
-
throw new Error(`
|
|
88
|
+
throw new Error(`field-path "${fieldPath}" must point to a string or number field for version updates.`);
|
|
89
89
|
}
|
|
90
90
|
cursor[leaf] = version;
|
|
91
91
|
}
|
|
92
|
+
function resolveFieldPath(rule) {
|
|
93
|
+
const fieldPath = rule["field-path"] ?? rule.jsonpath;
|
|
94
|
+
if (!fieldPath) {
|
|
95
|
+
throw new Error(`${rule.type} artifact rules require "field-path" (or deprecated "jsonpath").`);
|
|
96
|
+
}
|
|
97
|
+
return fieldPath;
|
|
98
|
+
}
|
|
92
99
|
function parseRegexPattern(pattern) {
|
|
93
100
|
const slashPattern = pattern.match(/^\/((?:\\\/|[^/])+)\/([a-z]*)$/u);
|
|
94
101
|
if (slashPattern) {
|
|
@@ -116,22 +123,36 @@ function applyRegexRule(content, pattern, version) {
|
|
|
116
123
|
const replacement = typeof groupOne === "string" ? full.replace(groupOne, version) : version;
|
|
117
124
|
return `${content.slice(0, start)}${replacement}${content.slice(start + full.length)}`;
|
|
118
125
|
}
|
|
126
|
+
function applyTomlRulePreservingFormatting(content, fieldPath, version) {
|
|
127
|
+
const simplePath = fieldPath.match(/^\$\.([A-Za-z0-9_-]+)$/u);
|
|
128
|
+
if (!simplePath) {
|
|
129
|
+
const parsed = toml_1.default.parse(content);
|
|
130
|
+
setVersionAtJsonPath(parsed, fieldPath, version);
|
|
131
|
+
return `${toml_1.default.stringify(parsed)}\n`;
|
|
132
|
+
}
|
|
133
|
+
const key = simplePath[1];
|
|
134
|
+
const linePattern = new RegExp(`^(\\s*${key}\\s*=\\s*)(["'])([^"']*)(\\2)(\\s*(?:#.*)?)$`, "mu");
|
|
135
|
+
const match = content.match(linePattern);
|
|
136
|
+
if (!match) {
|
|
137
|
+
throw new Error(`field-path "${fieldPath}" does not resolve to an existing field.`);
|
|
138
|
+
}
|
|
139
|
+
const [, prefix = "", quote = '"', , , suffix = ""] = match;
|
|
140
|
+
return content.replace(linePattern, `${prefix}${quote}${version}${quote}${suffix}`);
|
|
141
|
+
}
|
|
119
142
|
function applyArtifactRuleToContent(content, rule, version) {
|
|
120
143
|
if (rule.type === "regex") {
|
|
121
144
|
return applyRegexRule(content, rule.pattern, version);
|
|
122
145
|
}
|
|
123
146
|
if (rule.type === "json") {
|
|
124
147
|
const parsed = JSON.parse(content);
|
|
125
|
-
setVersionAtJsonPath(parsed, rule
|
|
148
|
+
setVersionAtJsonPath(parsed, resolveFieldPath(rule), version);
|
|
126
149
|
return `${JSON.stringify(parsed, null, 2)}\n`;
|
|
127
150
|
}
|
|
128
151
|
if (rule.type === "toml") {
|
|
129
|
-
|
|
130
|
-
setVersionAtJsonPath(parsed, rule.jsonpath, version);
|
|
131
|
-
return `${toml_1.default.stringify(parsed)}\n`;
|
|
152
|
+
return applyTomlRulePreservingFormatting(content, resolveFieldPath(rule), version);
|
|
132
153
|
}
|
|
133
154
|
const parsed = yaml_1.default.parse(content);
|
|
134
|
-
setVersionAtJsonPath(parsed, rule
|
|
155
|
+
setVersionAtJsonPath(parsed, resolveFieldPath(rule), version);
|
|
135
156
|
return `${yaml_1.default.stringify(parsed)}`;
|
|
136
157
|
}
|
|
137
158
|
function normalizeRelative(base, target) {
|
package/dist/app/release/pr.d.ts
CHANGED
|
@@ -20,4 +20,4 @@ export declare function openOrUpdateSimpleReviewRequest(cwd: string, branch: str
|
|
|
20
20
|
logger?: VersionaryPluginContext["logger"];
|
|
21
21
|
}): Promise<string>;
|
|
22
22
|
export declare function pushReleaseBranch(cwd: string, branch: string): void;
|
|
23
|
-
export declare function isReleaseCommitMessage(
|
|
23
|
+
export declare function isReleaseCommitMessage(commitMessage: string): boolean;
|
package/dist/app/release/pr.js
CHANGED
|
@@ -30,6 +30,7 @@ const SAFE_DIRTY_FILES = new Set([
|
|
|
30
30
|
"bun.lockb",
|
|
31
31
|
"npm-shrinkwrap.json",
|
|
32
32
|
]);
|
|
33
|
+
const VERSIONARY_RELEASE_TRAILER = "Versionary-Release: true";
|
|
33
34
|
function listTrackedDirtyFiles(cwd) {
|
|
34
35
|
const status = (0, node_child_process_1.execFileSync)("git", ["status", "--porcelain", "--untracked-files=no"], {
|
|
35
36
|
cwd,
|
|
@@ -70,6 +71,25 @@ function ensureCleanWorktree(cwd, logger) {
|
|
|
70
71
|
logger?.warn(`Ignoring safe tracked changes before versionary pr:\n${ignored.join("\n")}`);
|
|
71
72
|
}
|
|
72
73
|
}
|
|
74
|
+
function ensureCargoLockUpToDate(cwd) {
|
|
75
|
+
const lockfilePath = node_path_1.default.join(cwd, "Cargo.lock");
|
|
76
|
+
if (!node_fs_1.default.existsSync(lockfilePath)) {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
const before = node_fs_1.default.readFileSync(lockfilePath, "utf8");
|
|
80
|
+
try {
|
|
81
|
+
(0, node_child_process_1.execFileSync)("cargo", ["generate-lockfile"], {
|
|
82
|
+
cwd,
|
|
83
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
88
|
+
throw new Error(`Failed to refresh Cargo.lock via "cargo generate-lockfile". Ensure cargo is installed and available in PATH. Details: ${message}`);
|
|
89
|
+
}
|
|
90
|
+
const after = node_fs_1.default.readFileSync(lockfilePath, "utf8");
|
|
91
|
+
return after !== before ? ["Cargo.lock"] : [];
|
|
92
|
+
}
|
|
73
93
|
function normalizeReleaseNameForTag(releaseName) {
|
|
74
94
|
return releaseName
|
|
75
95
|
.trim()
|
|
@@ -195,6 +215,7 @@ function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
195
215
|
updatedVersionFiles.push(...strategy.writeVersion(cwd, loaded.config, plan.nextVersion));
|
|
196
216
|
}
|
|
197
217
|
const updatedArtifactFiles = (0, artifact_rules_js_1.applyConfiguredArtifactRules)(cwd, loaded.config, plan);
|
|
218
|
+
const updatedRustLockFiles = ensureCargoLockUpToDate(cwd);
|
|
198
219
|
const section = (0, changelog_js_1.renderSimpleChangelog)(plan);
|
|
199
220
|
(0, changelog_js_1.prependChangelog)(cwd, plan.changelogFile, section);
|
|
200
221
|
const releaseTargets = buildReleaseTargets(cwd, plan, loaded.config);
|
|
@@ -208,6 +229,7 @@ function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
208
229
|
...new Set([
|
|
209
230
|
...updatedVersionFiles,
|
|
210
231
|
...updatedArtifactFiles,
|
|
232
|
+
...updatedRustLockFiles,
|
|
211
233
|
plan.changelogFile,
|
|
212
234
|
]),
|
|
213
235
|
];
|
|
@@ -215,7 +237,7 @@ function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
215
237
|
cwd,
|
|
216
238
|
stdio: ["ignore", "pipe", "ignore"],
|
|
217
239
|
});
|
|
218
|
-
(0, node_child_process_1.execFileSync)("git", ["commit", "-m", title], {
|
|
240
|
+
(0, node_child_process_1.execFileSync)("git", ["commit", "-m", title, "-m", VERSIONARY_RELEASE_TRAILER], {
|
|
219
241
|
cwd,
|
|
220
242
|
stdio: ["ignore", "pipe", "ignore"],
|
|
221
243
|
});
|
|
@@ -306,6 +328,10 @@ function pushReleaseBranch(cwd, branch) {
|
|
|
306
328
|
stdio: ["ignore", "pipe", "ignore"],
|
|
307
329
|
});
|
|
308
330
|
}
|
|
309
|
-
function isReleaseCommitMessage(
|
|
310
|
-
|
|
331
|
+
function isReleaseCommitMessage(commitMessage) {
|
|
332
|
+
if (/^Versionary-Release:\s*true$/imu.test(commitMessage)) {
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
const subject = commitMessage.split("\n")[0]?.trim() ?? "";
|
|
336
|
+
return /^chore\(release\):\s+(?:v\d+\.\d+\.\d+|\S+-v\d+\.\d+\.\d+)(?:,\s+(?:v\d+\.\d+\.\d+|\S+-v\d+\.\d+\.\d+))*(?:\s+\(#\d+\))?$/u.test(subject);
|
|
311
337
|
}
|
|
@@ -15,8 +15,8 @@ const runtime_js_1 = require("../../plugins/runtime.js");
|
|
|
15
15
|
const pr_js_1 = require("./pr.js");
|
|
16
16
|
const recovery_js_1 = require("./recovery.js");
|
|
17
17
|
const state_js_1 = require("./state.js");
|
|
18
|
-
function
|
|
19
|
-
return (0, node_child_process_1.execFileSync)("git", ["log", "-1", "--pretty=%
|
|
18
|
+
function getHeadCommitMessage(cwd) {
|
|
19
|
+
return (0, node_child_process_1.execFileSync)("git", ["log", "-1", "--pretty=%B"], {
|
|
20
20
|
cwd,
|
|
21
21
|
encoding: "utf8",
|
|
22
22
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -54,8 +54,8 @@ async function runSimpleRelease(cwd = process.cwd()) {
|
|
|
54
54
|
return result.message;
|
|
55
55
|
}
|
|
56
56
|
async function runSimpleReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
57
|
-
const
|
|
58
|
-
if (!(0, pr_js_1.isReleaseCommitMessage)(
|
|
57
|
+
const commitMessage = getHeadCommitMessage(cwd);
|
|
58
|
+
if (!(0, pr_js_1.isReleaseCommitMessage)(commitMessage)) {
|
|
59
59
|
return {
|
|
60
60
|
action: "release-skipped",
|
|
61
61
|
reason: "No release commit context detected; skipping release stage.",
|
package/dist/cli/index.js
CHANGED
|
@@ -33,11 +33,11 @@ async function main() {
|
|
|
33
33
|
const flags = parseFlags(args);
|
|
34
34
|
const logger = flags.json ? undefined : console;
|
|
35
35
|
if (!command || command === "run") {
|
|
36
|
-
const
|
|
36
|
+
const commitMessage = (0, node_child_process_1.execFileSync)("git", ["log", "-1", "--pretty=%B"], {
|
|
37
37
|
encoding: "utf8",
|
|
38
38
|
stdio: ["ignore", "pipe", "ignore"],
|
|
39
39
|
}).trim();
|
|
40
|
-
if ((0, pr_js_1.isReleaseCommitMessage)(
|
|
40
|
+
if ((0, pr_js_1.isReleaseCommitMessage)(commitMessage)) {
|
|
41
41
|
if (flags.json) {
|
|
42
42
|
const release = await (0, release_js_1.runSimpleReleaseDetailed)(process.cwd(), {
|
|
43
43
|
logger,
|
package/dist/config/schema.d.ts
CHANGED
package/dist/config/schema.js
CHANGED
|
@@ -6,16 +6,18 @@ const artifactRuleSchema = zod_1.z
|
|
|
6
6
|
.object({
|
|
7
7
|
type: zod_1.z.enum(["json", "toml", "yaml", "regex"]),
|
|
8
8
|
path: zod_1.z.string().min(1),
|
|
9
|
+
"field-path": zod_1.z.string().optional(),
|
|
9
10
|
jsonpath: zod_1.z.string().optional(),
|
|
10
11
|
pattern: zod_1.z.string().optional(),
|
|
11
12
|
})
|
|
12
13
|
.superRefine((value, ctx) => {
|
|
13
14
|
const needsJsonPath = value.type === "json" || value.type === "toml" || value.type === "yaml";
|
|
14
|
-
|
|
15
|
+
const hasFieldPath = Boolean(value["field-path"] ?? value.jsonpath);
|
|
16
|
+
if (needsJsonPath && !hasFieldPath) {
|
|
15
17
|
ctx.addIssue({
|
|
16
18
|
code: zod_1.z.ZodIssueCode.custom,
|
|
17
|
-
message: `${value.type} artifact rules require "jsonpath".`,
|
|
18
|
-
path: ["
|
|
19
|
+
message: `${value.type} artifact rules require "field-path" (or deprecated "jsonpath").`,
|
|
20
|
+
path: ["field-path"],
|
|
19
21
|
});
|
|
20
22
|
}
|
|
21
23
|
if (needsJsonPath && value.pattern) {
|
|
@@ -25,6 +27,13 @@ const artifactRuleSchema = zod_1.z
|
|
|
25
27
|
path: ["pattern"],
|
|
26
28
|
});
|
|
27
29
|
}
|
|
30
|
+
if (value["field-path"] && value.jsonpath) {
|
|
31
|
+
ctx.addIssue({
|
|
32
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
33
|
+
message: 'Specify only one of "field-path" or deprecated "jsonpath".',
|
|
34
|
+
path: ["field-path"],
|
|
35
|
+
});
|
|
36
|
+
}
|
|
28
37
|
if (value.type === "regex" && !value.pattern) {
|
|
29
38
|
ctx.addIssue({
|
|
30
39
|
code: zod_1.z.ZodIssueCode.custom,
|
|
@@ -32,11 +41,11 @@ const artifactRuleSchema = zod_1.z
|
|
|
32
41
|
path: ["pattern"],
|
|
33
42
|
});
|
|
34
43
|
}
|
|
35
|
-
if (value.type === "regex" && value.jsonpath) {
|
|
44
|
+
if (value.type === "regex" && (value["field-path"] || value.jsonpath)) {
|
|
36
45
|
ctx.addIssue({
|
|
37
46
|
code: zod_1.z.ZodIssueCode.custom,
|
|
38
|
-
message: 'regex artifact rules do not support "jsonpath".',
|
|
39
|
-
path: ["
|
|
47
|
+
message: 'regex artifact rules do not support "field-path" or deprecated "jsonpath".',
|
|
48
|
+
path: ["field-path"],
|
|
40
49
|
});
|
|
41
50
|
}
|
|
42
51
|
});
|
package/dist/types/config.d.ts
CHANGED