versionary 0.2.0 → 0.3.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 +187 -11
- package/dist/{simple → app/release}/pr.d.ts +7 -4
- package/dist/{simple → app/release}/pr.js +89 -74
- package/dist/app/release/recovery.d.ts +17 -0
- package/dist/app/release/recovery.js +101 -0
- package/dist/{simple → app/release}/release.js +37 -24
- package/dist/app/release/state.d.ts +10 -0
- package/dist/{simple → app/release}/state.js +16 -4
- package/dist/app/release/verify.d.ts +2 -0
- package/dist/app/release/verify.js +5 -0
- package/dist/cli/index.js +12 -10
- package/dist/config/load-config.js +2 -12
- package/dist/config/schema.d.ts +1 -0
- package/dist/config/schema.js +1 -0
- package/dist/domain/release/changelog.d.ts +12 -0
- package/dist/domain/release/changelog.js +123 -0
- package/dist/{simple → domain/release}/plan.d.ts +4 -3
- package/dist/{simple → domain/release}/plan.js +32 -15
- package/dist/domain/release/semver.d.ts +15 -0
- package/dist/domain/release/semver.js +111 -0
- package/dist/domain/strategy/node.d.ts +2 -0
- package/dist/domain/strategy/node.js +37 -0
- package/dist/domain/strategy/resolve.d.ts +3 -0
- package/dist/domain/strategy/resolve.js +11 -0
- package/dist/domain/strategy/simple.d.ts +2 -0
- package/dist/domain/strategy/simple.js +28 -0
- package/dist/domain/strategy/types.d.ts +7 -0
- package/dist/domain/strategy/types.js +2 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +5 -1
- package/dist/infra/git/commits.d.ts +65 -0
- package/dist/infra/git/commits.js +436 -0
- package/dist/infra/scm/github/plugin.d.ts +1 -0
- package/dist/infra/scm/github/plugin.js +5 -0
- package/dist/infra/scm/runtime.d.ts +2 -0
- package/dist/infra/scm/runtime.js +24 -0
- package/dist/infra/scm/types.d.ts +1 -0
- package/dist/infra/scm/types.js +2 -0
- package/dist/plugins/runtime.d.ts +1 -2
- package/dist/plugins/runtime.js +3 -22
- package/dist/scm/github-plugin.js +133 -40
- package/dist/strategies/node.d.ts +1 -0
- package/dist/strategies/node.js +5 -0
- package/dist/strategies/resolve.d.ts +1 -0
- package/dist/strategies/resolve.js +5 -0
- package/dist/strategies/simple.d.ts +1 -0
- package/dist/strategies/simple.js +5 -0
- package/dist/strategies/types.d.ts +1 -0
- package/dist/strategies/types.js +2 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/plugins.d.ts +1 -0
- package/dist/verify/verify-project.js +3 -1
- package/package.json +1 -1
- package/dist/simple/changelog.d.ts +0 -3
- package/dist/simple/changelog.js +0 -46
- package/dist/simple/git.d.ts +0 -10
- package/dist/simple/git.js +0 -114
- package/dist/simple/semver.d.ts +0 -8
- package/dist/simple/semver.js +0 -25
- package/dist/simple/state.d.ts +0 -3
- /package/dist/{simple → app/release}/release.d.ts +0 -0
- /package/dist/{simple → infra/git}/repo-url.d.ts +0 -0
- /package/dist/{simple → infra/git}/repo-url.js +0 -0
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function loadRuntimePlugins(cwd?: string): VersionaryPluginRuntime[];
|
|
1
|
+
export { loadRuntimePlugins } from "../infra/scm/runtime.js";
|
package/dist/plugins/runtime.js
CHANGED
|
@@ -1,24 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.loadRuntimePlugins =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const BUILTIN_PLUGIN_FACTORIES = {
|
|
7
|
-
github: github_plugin_js_1.createGitHubPlugin,
|
|
8
|
-
};
|
|
9
|
-
function loadRuntimePlugins(cwd = process.cwd()) {
|
|
10
|
-
const loaded = (0, load_config_js_1.loadConfig)(cwd);
|
|
11
|
-
const configured = loaded.config.plugins ?? [];
|
|
12
|
-
const plugins = [(0, github_plugin_js_1.createGitHubPlugin)()];
|
|
13
|
-
const seen = new Set(plugins.map((plugin) => plugin.name));
|
|
14
|
-
for (const name of configured) {
|
|
15
|
-
const factory = BUILTIN_PLUGIN_FACTORIES[name];
|
|
16
|
-
if (!factory || seen.has(name)) {
|
|
17
|
-
continue;
|
|
18
|
-
}
|
|
19
|
-
const plugin = factory();
|
|
20
|
-
plugins.push(plugin);
|
|
21
|
-
seen.add(plugin.name);
|
|
22
|
-
}
|
|
23
|
-
return plugins;
|
|
24
|
-
}
|
|
3
|
+
exports.loadRuntimePlugins = void 0;
|
|
4
|
+
var runtime_js_1 = require("../infra/scm/runtime.js");
|
|
5
|
+
Object.defineProperty(exports, "loadRuntimePlugins", { enumerable: true, get: function () { return runtime_js_1.loadRuntimePlugins; } });
|
|
@@ -17,13 +17,56 @@ function getRepoFromEnv() {
|
|
|
17
17
|
return parseRepoSlug(slug);
|
|
18
18
|
}
|
|
19
19
|
function getGitHubToken() {
|
|
20
|
-
const token = process.env.VERSIONARY_PR_TOKEN ??
|
|
20
|
+
const token = process.env.VERSIONARY_PR_TOKEN ??
|
|
21
|
+
process.env.GH_TOKEN ??
|
|
22
|
+
process.env.GITHUB_TOKEN;
|
|
21
23
|
if (!token) {
|
|
22
24
|
throw new Error("Missing GitHub token. Set VERSIONARY_PR_TOKEN, GH_TOKEN, or GITHUB_TOKEN.");
|
|
23
25
|
}
|
|
24
26
|
return token;
|
|
25
27
|
}
|
|
26
|
-
|
|
28
|
+
function parseGitHubError(error) {
|
|
29
|
+
const status = typeof error === "object" && error !== null && "status" in error
|
|
30
|
+
? Number(error.status)
|
|
31
|
+
: undefined;
|
|
32
|
+
const message = error instanceof Error ? error.message : "Unknown GitHub API error";
|
|
33
|
+
return { status, message };
|
|
34
|
+
}
|
|
35
|
+
function repoRef(repo) {
|
|
36
|
+
return `${repo.owner}/${repo.repo}`;
|
|
37
|
+
}
|
|
38
|
+
function resolveHeadForList(repo, headBranch) {
|
|
39
|
+
const separator = headBranch.indexOf(":");
|
|
40
|
+
if (separator === -1) {
|
|
41
|
+
return `${repo.owner}:${headBranch}`;
|
|
42
|
+
}
|
|
43
|
+
const owner = headBranch.slice(0, separator);
|
|
44
|
+
const branch = headBranch.slice(separator + 1);
|
|
45
|
+
if (!owner || !branch || branch.includes(":")) {
|
|
46
|
+
throw new Error(`Invalid head branch "${headBranch}". Expected "branch" or "owner:branch".`);
|
|
47
|
+
}
|
|
48
|
+
return `${owner}:${branch}`;
|
|
49
|
+
}
|
|
50
|
+
function toReviewRequestState(pull, context) {
|
|
51
|
+
if (pull.state === "open") {
|
|
52
|
+
return "open";
|
|
53
|
+
}
|
|
54
|
+
if (pull.merged_at) {
|
|
55
|
+
return "merged";
|
|
56
|
+
}
|
|
57
|
+
if (pull.state === "closed") {
|
|
58
|
+
return "closed";
|
|
59
|
+
}
|
|
60
|
+
throw new Error(`Unexpected pull request state "${String(pull.state)}" for ${context}.`);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* GitHub hardening contract (see tests/github-plugin-hardening-matrix.test.ts):
|
|
64
|
+
* - GITHUB_REPOSITORY must exist and use owner/repo format.
|
|
65
|
+
* - Token precedence: VERSIONARY_PR_TOKEN -> GH_TOKEN -> GITHUB_TOKEN.
|
|
66
|
+
* - Label application is best-effort for 404/422, but fails for other statuses.
|
|
67
|
+
* - Release metadata lookup treats 404 as "missing, create release"; non-404 fails.
|
|
68
|
+
*/
|
|
69
|
+
async function ensureLabels(octokit, repo, pullNumber, labels, branchContext) {
|
|
27
70
|
if (labels.length === 0) {
|
|
28
71
|
return;
|
|
29
72
|
}
|
|
@@ -35,8 +78,12 @@ async function ensureLabels(octokit, repo, pullNumber, labels) {
|
|
|
35
78
|
labels,
|
|
36
79
|
});
|
|
37
80
|
}
|
|
38
|
-
catch {
|
|
39
|
-
|
|
81
|
+
catch (error) {
|
|
82
|
+
const { status, message } = parseGitHubError(error);
|
|
83
|
+
if (status === 404 || status === 422) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`Failed applying labels to pull request #${pullNumber}: [${repoRef(repo)} base=${branchContext.baseBranch} head=${branchContext.headBranch}] ${message}`);
|
|
40
87
|
}
|
|
41
88
|
}
|
|
42
89
|
function createGitHubPlugin() {
|
|
@@ -46,45 +93,80 @@ function createGitHubPlugin() {
|
|
|
46
93
|
async createOrUpdateReviewRequest(input, _context) {
|
|
47
94
|
const repo = getRepoFromEnv();
|
|
48
95
|
const octokit = new rest_1.Octokit({ auth: getGitHubToken() });
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
head: `${repo.owner}:${input.headBranch}`,
|
|
54
|
-
base: input.baseBranch,
|
|
55
|
-
per_page: 1,
|
|
56
|
-
});
|
|
57
|
-
if (existing.length > 0) {
|
|
58
|
-
const pr = existing[0];
|
|
59
|
-
const { data: updated } = await octokit.pulls.update({
|
|
96
|
+
const listHead = resolveHeadForList(repo, input.headBranch);
|
|
97
|
+
let existing;
|
|
98
|
+
try {
|
|
99
|
+
const response = await octokit.pulls.list({
|
|
60
100
|
owner: repo.owner,
|
|
61
101
|
repo: repo.repo,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
102
|
+
state: "open",
|
|
103
|
+
head: listHead,
|
|
104
|
+
base: input.baseBranch,
|
|
105
|
+
per_page: 100,
|
|
106
|
+
});
|
|
107
|
+
existing = response.data;
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
const { message } = parseGitHubError(error);
|
|
111
|
+
throw new Error(`Failed listing open pull requests for branch "${input.headBranch}" into "${input.baseBranch}": [${repoRef(repo)}] ${message}`);
|
|
112
|
+
}
|
|
113
|
+
if (existing.length > 1) {
|
|
114
|
+
const matches = existing.map((item) => `#${item.number}`).join(", ");
|
|
115
|
+
throw new Error(`Ambiguous open pull request matches for "${input.headBranch}" into "${input.baseBranch}": [${repoRef(repo)}] ${matches}`);
|
|
116
|
+
}
|
|
117
|
+
if (existing.length > 0) {
|
|
118
|
+
const pr = existing[0];
|
|
119
|
+
let updated;
|
|
120
|
+
try {
|
|
121
|
+
const response = await octokit.pulls.update({
|
|
122
|
+
owner: repo.owner,
|
|
123
|
+
repo: repo.repo,
|
|
124
|
+
pull_number: pr.number,
|
|
125
|
+
title: input.title,
|
|
126
|
+
body: input.body,
|
|
127
|
+
});
|
|
128
|
+
updated = response.data;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
const { message } = parseGitHubError(error);
|
|
132
|
+
throw new Error(`Failed updating pull request #${pr.number}: [${repoRef(repo)} base=${input.baseBranch} head=${input.headBranch}] ${message}`);
|
|
133
|
+
}
|
|
134
|
+
await ensureLabels(octokit, repo, updated.number, input.labels ?? [], {
|
|
135
|
+
baseBranch: input.baseBranch,
|
|
136
|
+
headBranch: input.headBranch,
|
|
65
137
|
});
|
|
66
|
-
await ensureLabels(octokit, repo, updated.number, input.labels ?? []);
|
|
67
138
|
return {
|
|
68
139
|
id: String(updated.id),
|
|
69
140
|
number: updated.number,
|
|
70
141
|
url: updated.html_url,
|
|
71
|
-
state: updated
|
|
142
|
+
state: toReviewRequestState(updated, `pull request #${updated.number} in ${repoRef(repo)}`),
|
|
72
143
|
};
|
|
73
144
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
145
|
+
let created;
|
|
146
|
+
try {
|
|
147
|
+
const response = await octokit.pulls.create({
|
|
148
|
+
owner: repo.owner,
|
|
149
|
+
repo: repo.repo,
|
|
150
|
+
title: input.title,
|
|
151
|
+
head: input.headBranch,
|
|
152
|
+
base: input.baseBranch,
|
|
153
|
+
body: input.body,
|
|
154
|
+
});
|
|
155
|
+
created = response.data;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
const { message } = parseGitHubError(error);
|
|
159
|
+
throw new Error(`Failed creating pull request from "${input.headBranch}" into "${input.baseBranch}": [${repoRef(repo)}] ${message}`);
|
|
160
|
+
}
|
|
161
|
+
await ensureLabels(octokit, repo, created.number, input.labels ?? [], {
|
|
162
|
+
baseBranch: input.baseBranch,
|
|
163
|
+
headBranch: input.headBranch,
|
|
81
164
|
});
|
|
82
|
-
await ensureLabels(octokit, repo, created.number, input.labels ?? []);
|
|
83
165
|
return {
|
|
84
166
|
id: String(created.id),
|
|
85
167
|
number: created.number,
|
|
86
168
|
url: created.html_url,
|
|
87
|
-
state: created
|
|
169
|
+
state: toReviewRequestState(created, `pull request #${created.number} in ${repoRef(repo)}`),
|
|
88
170
|
};
|
|
89
171
|
},
|
|
90
172
|
async createReleaseMetadata(input, _context) {
|
|
@@ -96,19 +178,30 @@ function createGitHubPlugin() {
|
|
|
96
178
|
repo: repo.repo,
|
|
97
179
|
tag: input.tag,
|
|
98
180
|
});
|
|
99
|
-
return { url: existing.data.html_url };
|
|
181
|
+
return { url: existing.data.html_url, status: "exists" };
|
|
100
182
|
}
|
|
101
|
-
catch {
|
|
102
|
-
|
|
183
|
+
catch (error) {
|
|
184
|
+
const { status, message } = parseGitHubError(error);
|
|
185
|
+
if (status !== 404) {
|
|
186
|
+
throw new Error(`Failed checking existing GitHub release for tag "${input.tag}": [${repoRef(repo)}] ${message}`);
|
|
187
|
+
}
|
|
103
188
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
189
|
+
let data;
|
|
190
|
+
try {
|
|
191
|
+
const response = await octokit.repos.createRelease({
|
|
192
|
+
owner: repo.owner,
|
|
193
|
+
repo: repo.repo,
|
|
194
|
+
tag_name: input.tag,
|
|
195
|
+
name: input.tag,
|
|
196
|
+
body: input.notes,
|
|
197
|
+
});
|
|
198
|
+
data = response.data;
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
const { message } = parseGitHubError(error);
|
|
202
|
+
throw new Error(`Failed creating GitHub release for tag "${input.tag}": [${repoRef(repo)}] ${message}`);
|
|
203
|
+
}
|
|
204
|
+
return { url: data.html_url, status: "created" };
|
|
112
205
|
},
|
|
113
206
|
};
|
|
114
207
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { nodeVersionStrategy } from "../domain/strategy/node.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.nodeVersionStrategy = void 0;
|
|
4
|
+
var node_js_1 = require("../domain/strategy/node.js");
|
|
5
|
+
Object.defineProperty(exports, "nodeVersionStrategy", { enumerable: true, get: function () { return node_js_1.nodeVersionStrategy; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { resolveVersionStrategy } from "../domain/strategy/resolve.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveVersionStrategy = void 0;
|
|
4
|
+
var resolve_js_1 = require("../domain/strategy/resolve.js");
|
|
5
|
+
Object.defineProperty(exports, "resolveVersionStrategy", { enumerable: true, get: function () { return resolve_js_1.resolveVersionStrategy; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { simpleVersionStrategy } from "../domain/strategy/simple.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.simpleVersionStrategy = void 0;
|
|
4
|
+
var simple_js_1 = require("../domain/strategy/simple.js");
|
|
5
|
+
Object.defineProperty(exports, "simpleVersionStrategy", { enumerable: true, get: function () { return simple_js_1.simpleVersionStrategy; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { VersionStrategy } from "../domain/strategy/types.js";
|
package/dist/types/config.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export interface VersionaryConfig {
|
|
|
21
21
|
"bootstrap-sha"?: string;
|
|
22
22
|
"monorepo-mode"?: "independent" | "fixed";
|
|
23
23
|
"bump-minor-pre-major"?: boolean;
|
|
24
|
+
"allow-stable-major"?: boolean;
|
|
24
25
|
"include-commit-authors"?: boolean;
|
|
25
26
|
"release-type"?: string;
|
|
26
27
|
packages?: Record<string, VersionaryPackage>;
|
package/dist/types/plugins.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ exports.verifyProject = verifyProject;
|
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const load_config_js_1 = require("../config/load-config.js");
|
|
10
|
+
const resolve_js_1 = require("../domain/strategy/resolve.js");
|
|
10
11
|
function verifyProject(cwd = process.cwd()) {
|
|
11
12
|
const checks = [];
|
|
12
13
|
const config = (0, load_config_js_1.loadConfig)(cwd);
|
|
@@ -15,7 +16,8 @@ function verifyProject(cwd = process.cwd()) {
|
|
|
15
16
|
ok: true,
|
|
16
17
|
details: `Loaded ${node_path_1.default.basename(config.path)} (${config.format})`,
|
|
17
18
|
});
|
|
18
|
-
const
|
|
19
|
+
const strategy = (0, resolve_js_1.resolveVersionStrategy)(config.config);
|
|
20
|
+
const versionFile = strategy.getVersionFile(config.config);
|
|
19
21
|
const exists = node_fs_1.default.existsSync(node_path_1.default.join(cwd, versionFile));
|
|
20
22
|
checks.push({
|
|
21
23
|
name: `version-file:${versionFile}`,
|
package/package.json
CHANGED
package/dist/simple/changelog.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.renderSimpleChangelog = renderSimpleChangelog;
|
|
7
|
-
exports.prependChangelog = prependChangelog;
|
|
8
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
-
const git_js_1 = require("./git.js");
|
|
11
|
-
const repo_url_js_1 = require("./repo-url.js");
|
|
12
|
-
function formatDate() {
|
|
13
|
-
return new Date().toISOString().slice(0, 10);
|
|
14
|
-
}
|
|
15
|
-
function renderSimpleChangelog(plan) {
|
|
16
|
-
if (!plan.nextVersion) {
|
|
17
|
-
return "";
|
|
18
|
-
}
|
|
19
|
-
const repoUrl = (0, repo_url_js_1.resolveRepositoryWebBaseUrl)(process.cwd());
|
|
20
|
-
const versionHeading = repoUrl
|
|
21
|
-
? `## [${plan.nextVersion}](${repoUrl}/compare/v${plan.currentVersion}...v${plan.nextVersion}) (${formatDate()})`
|
|
22
|
-
: `## ${plan.nextVersion} - ${formatDate()}`;
|
|
23
|
-
const lines = [
|
|
24
|
-
versionHeading,
|
|
25
|
-
"",
|
|
26
|
-
...plan.commits
|
|
27
|
-
.filter((commit) => (0, git_js_1.isReleasableCommit)(commit.subject))
|
|
28
|
-
.map((commit) => {
|
|
29
|
-
const short = commit.hash.slice(0, 7);
|
|
30
|
-
if (!repoUrl) {
|
|
31
|
-
return `- ${commit.subject} (\`${short}\`)`;
|
|
32
|
-
}
|
|
33
|
-
return `- ${commit.subject} ([\`${short}\`](${repoUrl}/commit/${commit.hash}))`;
|
|
34
|
-
}),
|
|
35
|
-
"",
|
|
36
|
-
];
|
|
37
|
-
return lines.join("\n");
|
|
38
|
-
}
|
|
39
|
-
function prependChangelog(cwd, changelogFile, section) {
|
|
40
|
-
const changelogPath = node_path_1.default.join(cwd, changelogFile);
|
|
41
|
-
const existing = node_fs_1.default.existsSync(changelogPath) ? node_fs_1.default.readFileSync(changelogPath, "utf8") : "";
|
|
42
|
-
const heading = existing.startsWith("# Changelog") ? "" : "# Changelog\n\n";
|
|
43
|
-
const separator = existing.length > 0 ? "\n" : "";
|
|
44
|
-
const next = `${heading}${section}${separator}${existing.replace(/^# Changelog\s*/u, "")}`.trimEnd() + "\n";
|
|
45
|
-
node_fs_1.default.writeFileSync(changelogPath, next, "utf8");
|
|
46
|
-
}
|
package/dist/simple/git.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { ReleaseType } from "./semver.js";
|
|
2
|
-
export interface CommitInfo {
|
|
3
|
-
hash: string;
|
|
4
|
-
subject: string;
|
|
5
|
-
}
|
|
6
|
-
export declare function getCommitsSinceLastTag(cwd?: string, baselineSha?: string | null): CommitInfo[];
|
|
7
|
-
export declare function getCommitsForPath(cwd?: string, baselineSha?: string | null, packagePath?: string, excludePaths?: string[]): CommitInfo[];
|
|
8
|
-
export declare function inferReleaseTypeFromSubject(subject: string): ReleaseType;
|
|
9
|
-
export declare function isReleasableCommit(subject: string): boolean;
|
|
10
|
-
export declare function analyzeCommits(commits: CommitInfo[]): ReleaseType;
|
package/dist/simple/git.js
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getCommitsSinceLastTag = getCommitsSinceLastTag;
|
|
7
|
-
exports.getCommitsForPath = getCommitsForPath;
|
|
8
|
-
exports.inferReleaseTypeFromSubject = inferReleaseTypeFromSubject;
|
|
9
|
-
exports.isReleasableCommit = isReleasableCommit;
|
|
10
|
-
exports.analyzeCommits = analyzeCommits;
|
|
11
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
-
const node_child_process_1 = require("node:child_process");
|
|
13
|
-
function getReleaseBranchExcludeArgs(cwd) {
|
|
14
|
-
const releaseBranchesRaw = (0, node_child_process_1.execFileSync)("git", ["branch", "--list", "--format", "%(refname:short)"], {
|
|
15
|
-
cwd,
|
|
16
|
-
encoding: "utf8",
|
|
17
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
18
|
-
});
|
|
19
|
-
const releaseBranches = releaseBranchesRaw
|
|
20
|
-
.split("\n")
|
|
21
|
-
.map((line) => line.trim())
|
|
22
|
-
.filter((line) => line.startsWith("versionary/release"));
|
|
23
|
-
return releaseBranches.flatMap((branch) => ["--exclude", branch]);
|
|
24
|
-
}
|
|
25
|
-
function resolveBaseRef(cwd, baselineSha) {
|
|
26
|
-
const excludeArgs = getReleaseBranchExcludeArgs(cwd);
|
|
27
|
-
let baseRef = baselineSha ?? "";
|
|
28
|
-
if (!baseRef) {
|
|
29
|
-
try {
|
|
30
|
-
const cmd = ["describe", "--tags", "--abbrev=0", "--match", "v[0-9]*", ...excludeArgs];
|
|
31
|
-
baseRef = (0, node_child_process_1.execFileSync)("git", cmd, {
|
|
32
|
-
cwd,
|
|
33
|
-
encoding: "utf8",
|
|
34
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
35
|
-
}).trim();
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
baseRef = "";
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return baseRef;
|
|
42
|
-
}
|
|
43
|
-
function readGitLog(cwd, range, pathspecs = []) {
|
|
44
|
-
const output = (0, node_child_process_1.execFileSync)("git", ["log", range, "--pretty=format:%H%x09%s", "--", ...pathspecs], {
|
|
45
|
-
cwd,
|
|
46
|
-
encoding: "utf8",
|
|
47
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
48
|
-
});
|
|
49
|
-
if (!output.trim()) {
|
|
50
|
-
return [];
|
|
51
|
-
}
|
|
52
|
-
return output
|
|
53
|
-
.trim()
|
|
54
|
-
.split("\n")
|
|
55
|
-
.map((line) => {
|
|
56
|
-
const [hash, subject] = line.split("\t");
|
|
57
|
-
return { hash, subject };
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
function getCommitsSinceLastTag(cwd = process.cwd(), baselineSha) {
|
|
61
|
-
const baseRef = resolveBaseRef(cwd, baselineSha);
|
|
62
|
-
const range = baseRef ? `${baseRef}..HEAD` : "HEAD";
|
|
63
|
-
return readGitLog(cwd, range);
|
|
64
|
-
}
|
|
65
|
-
function getCommitsForPath(cwd = process.cwd(), baselineSha, packagePath = ".", excludePaths = []) {
|
|
66
|
-
const baseRef = resolveBaseRef(cwd, baselineSha);
|
|
67
|
-
const range = baseRef ? `${baseRef}..HEAD` : "HEAD";
|
|
68
|
-
const normalizedPackagePath = packagePath === "." ? "." : packagePath;
|
|
69
|
-
const excludes = excludePaths.map((excludePath) => {
|
|
70
|
-
const combined = normalizedPackagePath === "."
|
|
71
|
-
? excludePath
|
|
72
|
-
: node_path_1.default.posix.join(normalizedPackagePath, excludePath);
|
|
73
|
-
return `:(exclude)${combined}`;
|
|
74
|
-
});
|
|
75
|
-
return readGitLog(cwd, range, [normalizedPackagePath, ...excludes]);
|
|
76
|
-
}
|
|
77
|
-
function inferReleaseTypeFromSubject(subject) {
|
|
78
|
-
if (/^revert:\s/i.test(subject)) {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
if (/^chore(\(.+\))?:\s/i.test(subject)) {
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
if (/!:/u.test(subject) || /BREAKING CHANGE/u.test(subject)) {
|
|
85
|
-
return "major";
|
|
86
|
-
}
|
|
87
|
-
if (/^feat(\(.+\))?:\s/i.test(subject)) {
|
|
88
|
-
return "minor";
|
|
89
|
-
}
|
|
90
|
-
if (/^(fix|perf)(\(.+\))?:\s/i.test(subject)) {
|
|
91
|
-
return "patch";
|
|
92
|
-
}
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
function isReleasableCommit(subject) {
|
|
96
|
-
return inferReleaseTypeFromSubject(subject) !== null;
|
|
97
|
-
}
|
|
98
|
-
function analyzeCommits(commits) {
|
|
99
|
-
let result = null;
|
|
100
|
-
for (const commit of commits) {
|
|
101
|
-
const type = inferReleaseTypeFromSubject(commit.subject);
|
|
102
|
-
if (type === "major") {
|
|
103
|
-
return "major";
|
|
104
|
-
}
|
|
105
|
-
if (type === "minor") {
|
|
106
|
-
result = "minor";
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
if (type === "patch" && result === null) {
|
|
110
|
-
result = "patch";
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return result;
|
|
114
|
-
}
|
package/dist/simple/semver.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export type ReleaseType = "major" | "minor" | "patch" | null;
|
|
2
|
-
export interface ParsedVersion {
|
|
3
|
-
major: number;
|
|
4
|
-
minor: number;
|
|
5
|
-
patch: number;
|
|
6
|
-
}
|
|
7
|
-
export declare function parseVersion(version: string): ParsedVersion;
|
|
8
|
-
export declare function bumpVersion(current: string, releaseType: Exclude<ReleaseType, null>): string;
|
package/dist/simple/semver.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseVersion = parseVersion;
|
|
4
|
-
exports.bumpVersion = bumpVersion;
|
|
5
|
-
function parseVersion(version) {
|
|
6
|
-
const match = version.trim().match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
7
|
-
if (!match) {
|
|
8
|
-
throw new Error(`Invalid version in version file: "${version}". Expected x.y.z`);
|
|
9
|
-
}
|
|
10
|
-
return {
|
|
11
|
-
major: Number(match[1]),
|
|
12
|
-
minor: Number(match[2]),
|
|
13
|
-
patch: Number(match[3]),
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
function bumpVersion(current, releaseType) {
|
|
17
|
-
const parsed = parseVersion(current);
|
|
18
|
-
if (releaseType === "major") {
|
|
19
|
-
return `${parsed.major + 1}.0.0`;
|
|
20
|
-
}
|
|
21
|
-
if (releaseType === "minor") {
|
|
22
|
-
return `${parsed.major}.${parsed.minor + 1}.0`;
|
|
23
|
-
}
|
|
24
|
-
return `${parsed.major}.${parsed.minor}.${parsed.patch + 1}`;
|
|
25
|
-
}
|
package/dist/simple/state.d.ts
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|