versionary 0.11.0 → 0.12.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 +35 -19
- package/dist/cli/index.js +7 -18
- package/dist/config/schema.d.ts +9 -0
- package/dist/config/schema.js +3 -0
- package/dist/{infra/git → git}/commits.d.ts +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.js +10 -10
- package/dist/release/artifact-rules.d.ts +3 -0
- package/dist/{domain/release → release}/changelog.d.ts +13 -2
- package/dist/{domain/release → release}/changelog.js +59 -6
- package/dist/{domain/release → release}/plan.d.ts +13 -1
- package/dist/{domain/release → release}/plan.js +50 -19
- package/dist/{app/release → release}/pr.d.ts +3 -3
- package/dist/{app/release → release}/pr.js +60 -66
- package/dist/{app/release → release}/recovery.d.ts +2 -1
- package/dist/{app/release → release}/release.d.ts +2 -2
- package/dist/{app/release → release}/release.js +14 -17
- package/dist/{app/release → release}/state.js +1 -1
- package/dist/{verify → release}/verify-project.js +2 -2
- package/dist/scm/client.d.ts +2 -0
- package/dist/scm/client.js +7 -0
- package/dist/scm/github-plugin.d.ts +2 -1
- package/dist/scm/github-plugin.js +2 -0
- package/dist/scm/types.d.ts +37 -0
- package/dist/{domain/strategy → strategy}/node.js +13 -0
- package/dist/{domain/strategy → strategy}/package-context.d.ts +1 -1
- package/dist/{domain/strategy → strategy}/package-context.js +2 -2
- package/dist/{domain/strategy → strategy}/r.js +14 -0
- package/dist/{domain/strategy → strategy}/resolve.d.ts +2 -1
- package/dist/strategy/resolve.js +21 -0
- package/dist/{domain/strategy → strategy}/rust.js +42 -0
- package/dist/strategy/types.d.ts +21 -0
- package/dist/types/config.d.ts +4 -0
- package/dist/types/plugins.d.ts +7 -30
- package/package.json +1 -1
- package/dist/app/release/artifact-rules.d.ts +0 -3
- package/dist/app/release/verify.d.ts +0 -2
- package/dist/app/release/verify.js +0 -5
- package/dist/domain/strategy/resolve.js +0 -19
- package/dist/domain/strategy/types.d.ts +0 -7
- package/dist/infra/scm/github/plugin.d.ts +0 -1
- package/dist/infra/scm/github/plugin.js +0 -5
- package/dist/infra/scm/runtime.d.ts +0 -2
- package/dist/infra/scm/runtime.js +0 -7
- package/dist/infra/scm/types.d.ts +0 -1
- package/dist/plugins/runtime.d.ts +0 -1
- package/dist/plugins/runtime.js +0 -5
- package/dist/strategies/node.d.ts +0 -1
- package/dist/strategies/node.js +0 -5
- package/dist/strategies/resolve.d.ts +0 -1
- package/dist/strategies/resolve.js +0 -5
- package/dist/strategies/simple.d.ts +0 -1
- package/dist/strategies/simple.js +0 -5
- package/dist/strategies/types.d.ts +0 -1
- package/dist/strategies/types.js +0 -2
- /package/dist/{infra/git → git}/commits.js +0 -0
- /package/dist/{infra/git → git}/repo-url.d.ts +0 -0
- /package/dist/{infra/git → git}/repo-url.js +0 -0
- /package/dist/{app/release → release}/artifact-rules.js +0 -0
- /package/dist/{app/release → release}/recovery.js +0 -0
- /package/dist/{domain/release → release}/semver.d.ts +0 -0
- /package/dist/{domain/release → release}/semver.js +0 -0
- /package/dist/{app/release → release}/state.d.ts +0 -0
- /package/dist/{verify → release}/verify-project.d.ts +0 -0
- /package/dist/{plugins → scm}/capabilities.d.ts +0 -0
- /package/dist/{plugins → scm}/capabilities.js +0 -0
- /package/dist/{domain/strategy → scm}/types.js +0 -0
- /package/dist/{domain/strategy → strategy}/node.d.ts +0 -0
- /package/dist/{domain/strategy → strategy}/r.d.ts +0 -0
- /package/dist/{domain/strategy → strategy}/rust.d.ts +0 -0
- /package/dist/{domain/strategy → strategy}/simple.d.ts +0 -0
- /package/dist/{domain/strategy → strategy}/simple.js +0 -0
- /package/dist/{infra/scm → strategy}/types.js +0 -0
|
@@ -12,16 +12,13 @@ exports.isReleaseCommitMessage = isReleaseCommitMessage;
|
|
|
12
12
|
const node_child_process_1 = require("node:child_process");
|
|
13
13
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const package_context_js_1 = require("../../domain/strategy/package-context.js");
|
|
20
|
-
const resolve_js_1 = require("../../domain/strategy/resolve.js");
|
|
21
|
-
const rust_js_1 = require("../../domain/strategy/rust.js");
|
|
22
|
-
const capabilities_js_1 = require("../../plugins/capabilities.js");
|
|
23
|
-
const runtime_js_1 = require("../../plugins/runtime.js");
|
|
15
|
+
const load_config_js_1 = require("../config/load-config.js");
|
|
16
|
+
const client_js_1 = require("../scm/client.js");
|
|
17
|
+
const package_context_js_1 = require("../strategy/package-context.js");
|
|
18
|
+
const resolve_js_1 = require("../strategy/resolve.js");
|
|
24
19
|
const artifact_rules_js_1 = require("./artifact-rules.js");
|
|
20
|
+
const changelog_js_1 = require("./changelog.js");
|
|
21
|
+
const plan_js_1 = require("./plan.js");
|
|
25
22
|
const state_js_1 = require("./state.js");
|
|
26
23
|
const SAFE_DIRTY_FILES = new Set([
|
|
27
24
|
"pnpm-lock.yaml",
|
|
@@ -133,47 +130,12 @@ function normalizeReleaseNameForTag(releaseName) {
|
|
|
133
130
|
.replaceAll("/", "-")
|
|
134
131
|
.replace(/\s+/gu, "-");
|
|
135
132
|
}
|
|
136
|
-
function
|
|
137
|
-
const raw = JSON.parse(node_fs_1.default.readFileSync(versionPath, "utf8"));
|
|
138
|
-
const name = raw.name;
|
|
139
|
-
if (typeof name !== "string" || name.trim().length === 0) {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
return name.trim();
|
|
143
|
-
}
|
|
144
|
-
function readRustPackageName(versionPath) {
|
|
145
|
-
const parsed = toml_1.default.parse(node_fs_1.default.readFileSync(versionPath, "utf8"));
|
|
146
|
-
const name = parsed.package?.name;
|
|
147
|
-
if (typeof name !== "string" || name.trim().length === 0) {
|
|
148
|
-
return null;
|
|
149
|
-
}
|
|
150
|
-
return name.trim();
|
|
151
|
-
}
|
|
152
|
-
function readRPackageName(versionPath) {
|
|
153
|
-
const content = node_fs_1.default.readFileSync(versionPath, "utf8");
|
|
154
|
-
const match = content.match(/^Package:\s*(.+)\s*$/mu);
|
|
155
|
-
if (!match?.[1]) {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
const name = match[1].trim();
|
|
159
|
-
return name.length > 0 ? name : null;
|
|
160
|
-
}
|
|
161
|
-
function resolveReleaseName(cwd, packagePath, packageConfig, strategyName, versionFile) {
|
|
133
|
+
function resolveReleaseName(cwd, packagePath, packageConfig, strategy, strategyConfig) {
|
|
162
134
|
const configuredName = packageConfig["package-name"]?.trim();
|
|
163
135
|
if (configuredName) {
|
|
164
136
|
return configuredName;
|
|
165
137
|
}
|
|
166
|
-
|
|
167
|
-
if (strategyName === "node") {
|
|
168
|
-
return readNodePackageName(versionPath) ?? packagePath;
|
|
169
|
-
}
|
|
170
|
-
if (strategyName === "rust") {
|
|
171
|
-
return readRustPackageName(versionPath) ?? packagePath;
|
|
172
|
-
}
|
|
173
|
-
if (strategyName === "r") {
|
|
174
|
-
return readRPackageName(versionPath) ?? packagePath;
|
|
175
|
-
}
|
|
176
|
-
return packagePath;
|
|
138
|
+
return strategy.readPackageName?.(cwd, strategyConfig) ?? packagePath;
|
|
177
139
|
}
|
|
178
140
|
function buildReleaseTargets(cwd, plan, loadedConfig) {
|
|
179
141
|
const releaseTargets = plan.packages
|
|
@@ -189,7 +151,7 @@ function buildReleaseTargets(cwd, plan, loadedConfig) {
|
|
|
189
151
|
}
|
|
190
152
|
const packageConfig = loadedConfig.packages?.[pkg.path] ?? {};
|
|
191
153
|
const packageContext = (0, package_context_js_1.resolvePackageStrategyContext)(loadedConfig, pkg.path, packageConfig);
|
|
192
|
-
const releaseName = resolveReleaseName(cwd, pkg.path, packageConfig, packageContext.strategy
|
|
154
|
+
const releaseName = resolveReleaseName(cwd, pkg.path, packageConfig, packageContext.strategy, packageContext.config);
|
|
193
155
|
const tagPrefix = normalizeReleaseNameForTag(releaseName);
|
|
194
156
|
return {
|
|
195
157
|
path: pkg.path,
|
|
@@ -222,7 +184,7 @@ function buildPackageReleaseMetadata(cwd, plan, loadedConfig) {
|
|
|
222
184
|
}
|
|
223
185
|
const packageConfig = loadedConfig.packages?.[pkg.path] ?? {};
|
|
224
186
|
const packageContext = (0, package_context_js_1.resolvePackageStrategyContext)(loadedConfig, pkg.path, packageConfig);
|
|
225
|
-
const releaseName = resolveReleaseName(cwd, pkg.path, packageConfig, packageContext.strategy
|
|
187
|
+
const releaseName = resolveReleaseName(cwd, pkg.path, packageConfig, packageContext.strategy, packageContext.config);
|
|
226
188
|
metadataByPath[pkg.path] = {
|
|
227
189
|
releaseName,
|
|
228
190
|
tagPrefix: normalizeReleaseNameForTag(releaseName),
|
|
@@ -249,7 +211,18 @@ function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
249
211
|
}
|
|
250
212
|
ensureCleanWorktree(cwd, options.logger);
|
|
251
213
|
const updatedVersionFiles = [];
|
|
252
|
-
const
|
|
214
|
+
const writesByStrategy = new Map();
|
|
215
|
+
const addStrategyWrite = (strategy, write) => {
|
|
216
|
+
const existing = writesByStrategy.get(strategy.name);
|
|
217
|
+
if (existing) {
|
|
218
|
+
existing.writes.push(write);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
writesByStrategy.set(strategy.name, {
|
|
222
|
+
strategy,
|
|
223
|
+
writes: [write],
|
|
224
|
+
});
|
|
225
|
+
};
|
|
253
226
|
if (plan.packages && plan.packages.length > 0) {
|
|
254
227
|
for (const packagePlan of plan.packages) {
|
|
255
228
|
if (!packagePlan.nextVersion) {
|
|
@@ -259,21 +232,29 @@ function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
259
232
|
const packageContext = (0, package_context_js_1.resolvePackageStrategyContext)(loaded.config, packagePlan.path, packageConfig);
|
|
260
233
|
const packageUpdated = packageContext.strategy.writeVersion(cwd, packageContext.config, packagePlan.nextVersion);
|
|
261
234
|
updatedVersionFiles.push(...packageUpdated);
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
235
|
+
addStrategyWrite(packageContext.strategy, {
|
|
236
|
+
packagePath: packagePlan.path,
|
|
237
|
+
versionFile: packageContext.versionFile,
|
|
238
|
+
version: packagePlan.nextVersion,
|
|
239
|
+
});
|
|
266
240
|
}
|
|
267
|
-
updatedVersionFiles.push(...(0, rust_js_1.applyRustWorkspaceDependencyUpdates)(cwd, rustManifestVersionTargets));
|
|
268
241
|
}
|
|
269
242
|
else {
|
|
270
243
|
updatedVersionFiles.push(...strategy.writeVersion(cwd, loaded.config, plan.nextVersion));
|
|
244
|
+
addStrategyWrite(strategy, {
|
|
245
|
+
packagePath: ".",
|
|
246
|
+
versionFile: strategy.getVersionFile(loaded.config),
|
|
247
|
+
version: plan.nextVersion,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
for (const strategyGroup of writesByStrategy.values()) {
|
|
251
|
+
updatedVersionFiles.push(...(strategyGroup.strategy.finalizeVersionWrites?.(cwd, strategyGroup.writes) ?? []));
|
|
271
252
|
}
|
|
272
253
|
const updatedArtifactFiles = (0, artifact_rules_js_1.applyConfiguredArtifactRules)(cwd, loaded.config, plan);
|
|
273
254
|
const updatedRustLockFiles = ensureCargoLockUpToDate(cwd);
|
|
274
255
|
const packageReleaseMetadata = buildPackageReleaseMetadata(cwd, plan, loaded.config);
|
|
275
256
|
const section = (0, changelog_js_1.renderSimpleChangelog)(plan);
|
|
276
|
-
(0, changelog_js_1.prependChangelog)(cwd, plan.changelogFile, section);
|
|
257
|
+
(0, changelog_js_1.prependChangelog)(cwd, plan.changelogFile, section, plan.changelogFormat);
|
|
277
258
|
const updatedChangelogFiles = [plan.changelogFile];
|
|
278
259
|
for (const packagePlan of plan.packages ?? []) {
|
|
279
260
|
if (!packagePlan.nextVersion || packagePlan.path === ".") {
|
|
@@ -295,7 +276,7 @@ function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
295
276
|
tagPrefix: packageMetadata.tagPrefix,
|
|
296
277
|
cwd,
|
|
297
278
|
});
|
|
298
|
-
(0, changelog_js_1.prependChangelog)(cwd, node_path_1.default.posix.join(packagePlan.path, packageChangelogFile), packageSection);
|
|
279
|
+
(0, changelog_js_1.prependChangelog)(cwd, node_path_1.default.posix.join(packagePlan.path, packageChangelogFile), packageSection, "markdown-changelog");
|
|
299
280
|
updatedChangelogFiles.push(node_path_1.default.posix.join(packagePlan.path, packageChangelogFile));
|
|
300
281
|
}
|
|
301
282
|
const releaseTargets = buildReleaseTargets(cwd, plan, loaded.config);
|
|
@@ -342,16 +323,37 @@ function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
|
|
|
342
323
|
function renderSimpleReviewRequestBody(version, previousVersion, commits, plan = null, cwd = process.cwd()) {
|
|
343
324
|
const rootPackageLabel = node_path_1.default.basename(cwd);
|
|
344
325
|
const formatPackageLabel = (packagePath) => packagePath === "." ? rootPackageLabel : packagePath;
|
|
326
|
+
const isDirectBump = (pkg) => pkg.bumpReason === "direct" ||
|
|
327
|
+
(pkg.bumpReason === undefined &&
|
|
328
|
+
Boolean(pkg.nextVersion) &&
|
|
329
|
+
pkg.commits.length > 0);
|
|
330
|
+
const findPropagatedDependencies = (packagePath, packages) => {
|
|
331
|
+
const target = packages.find((pkg) => pkg.path === packagePath);
|
|
332
|
+
if (!target || target.bumpReason !== "dependency-propagation") {
|
|
333
|
+
return [];
|
|
334
|
+
}
|
|
335
|
+
const directSources = packages
|
|
336
|
+
.filter((pkg) => isDirectBump(pkg))
|
|
337
|
+
.map((pkg) => ({
|
|
338
|
+
name: formatPackageLabel(pkg.path),
|
|
339
|
+
version: pkg.nextVersion ?? "",
|
|
340
|
+
}))
|
|
341
|
+
.filter((dependency) => dependency.version.length > 0)
|
|
342
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
343
|
+
return directSources;
|
|
344
|
+
};
|
|
345
345
|
if (plan?.packages && plan.packages.length > 1) {
|
|
346
346
|
const sections = plan.packages
|
|
347
347
|
.filter((pkg) => pkg.nextVersion)
|
|
348
348
|
.map((pkg) => {
|
|
349
349
|
const packageLabel = formatPackageLabel(pkg.path);
|
|
350
|
+
const propagatedDependencies = findPropagatedDependencies(pkg.path, plan.packages ?? []);
|
|
350
351
|
const notes = (0, changelog_js_1.renderSimpleReleaseNotes)({
|
|
351
352
|
currentVersion: pkg.currentVersion,
|
|
352
353
|
nextVersion: pkg.nextVersion ?? "",
|
|
353
354
|
commits: pkg.commits,
|
|
354
355
|
cwd,
|
|
356
|
+
dependencies: propagatedDependencies,
|
|
355
357
|
}, { includeFooter: false });
|
|
356
358
|
const linkedHeader = notes.match(/^##\s+\[([^\]]+)\]\(([^)]+)\)\s+\(([^)]+)\)/u);
|
|
357
359
|
if (linkedHeader) {
|
|
@@ -381,16 +383,8 @@ async function openOrUpdateSimpleReviewRequest(cwd, branch, title, version, prev
|
|
|
381
383
|
if (releaseFlow === "direct") {
|
|
382
384
|
return "Release flow mode is direct; skipping review request creation.";
|
|
383
385
|
}
|
|
384
|
-
const
|
|
385
|
-
const
|
|
386
|
-
if (scmPlugins.length === 0) {
|
|
387
|
-
throw new Error("review-mode is pr but no scm.reviewRequest plugin is available.");
|
|
388
|
-
}
|
|
389
|
-
const plugin = scmPlugins[0];
|
|
390
|
-
if (!plugin?.createOrUpdateReviewRequest) {
|
|
391
|
-
throw new Error(`Plugin "${plugin?.name ?? "unknown"}" does not implement createOrUpdateReviewRequest.`);
|
|
392
|
-
}
|
|
393
|
-
const result = await plugin.createOrUpdateReviewRequest({
|
|
386
|
+
const scmClient = (0, client_js_1.getScmClient)();
|
|
387
|
+
const result = await scmClient.createOrUpdateReviewRequest({
|
|
394
388
|
baseBranch: process.env.VERSIONARY_BASE_BRANCH ?? "main",
|
|
395
389
|
headBranch: branch,
|
|
396
390
|
title,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { VersionaryScmReleaseMetadataResult } from "
|
|
1
|
+
import type { VersionaryScmReleaseMetadataResult } from "../types/plugins.js";
|
|
2
2
|
export type TagStepResult = "created" | "exists";
|
|
3
3
|
export interface ReleaseTargetInput {
|
|
4
4
|
tag: string;
|
|
5
5
|
version: string;
|
|
6
6
|
notes: string;
|
|
7
|
+
draft?: boolean;
|
|
7
8
|
}
|
|
8
9
|
export interface ReleaseExecutionContext {
|
|
9
10
|
createReleaseMetadata: (input: ReleaseTargetInput) => Promise<VersionaryScmReleaseMetadataResult>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { VersionaryConfig } from "
|
|
2
|
-
import type { VersionaryPluginContext } from "
|
|
1
|
+
import type { VersionaryConfig } from "../types/config.js";
|
|
2
|
+
import type { VersionaryPluginContext } from "../types/plugins.js";
|
|
3
3
|
export declare function resolveTargetChangelogFile(config: VersionaryConfig, rootChangelogFile: string, targetPath: string): string;
|
|
4
4
|
export declare function runSimpleRelease(cwd?: string): Promise<string>;
|
|
5
5
|
export type SimpleRunReleaseResult = {
|
|
@@ -9,10 +9,10 @@ exports.runSimpleReleaseDetailed = runSimpleReleaseDetailed;
|
|
|
9
9
|
const node_child_process_1 = require("node:child_process");
|
|
10
10
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
11
11
|
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
-
const load_config_js_1 = require("
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
12
|
+
const load_config_js_1 = require("../config/load-config.js");
|
|
13
|
+
const client_js_1 = require("../scm/client.js");
|
|
14
|
+
const resolve_js_1 = require("../strategy/resolve.js");
|
|
15
|
+
const plan_js_1 = require("./plan.js");
|
|
16
16
|
const pr_js_1 = require("./pr.js");
|
|
17
17
|
const recovery_js_1 = require("./recovery.js");
|
|
18
18
|
const state_js_1 = require("./state.js");
|
|
@@ -30,7 +30,12 @@ function readReleaseNotes(cwd, version, changelogFile) {
|
|
|
30
30
|
}
|
|
31
31
|
const content = node_fs_1.default.readFileSync(changelogPath, "utf8");
|
|
32
32
|
const lines = content.split("\n");
|
|
33
|
-
const
|
|
33
|
+
const shortVersion = version.replace(/\.\d+$/u, "");
|
|
34
|
+
const start = lines.findIndex((line) => line.startsWith(`## ${version} -`) ||
|
|
35
|
+
line.startsWith(`## [${version}](`) ||
|
|
36
|
+
line.startsWith(`# ${shortVersion} -`) ||
|
|
37
|
+
line.startsWith(`# [${shortVersion}](`) ||
|
|
38
|
+
new RegExp(`^#\\s+.+\\s+${shortVersion}\\s*$`, "u").test(line));
|
|
34
39
|
if (start < 0) {
|
|
35
40
|
return `Automated release for v${version}`;
|
|
36
41
|
}
|
|
@@ -74,7 +79,7 @@ async function runSimpleReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
|
74
79
|
}
|
|
75
80
|
const loaded = (0, load_config_js_1.loadConfig)(cwd);
|
|
76
81
|
const strategy = (0, resolve_js_1.resolveVersionStrategy)(loaded.config);
|
|
77
|
-
const changelogFile = loaded.config
|
|
82
|
+
const { changelogFile } = (0, plan_js_1.getChangelogDefaults)(loaded.config);
|
|
78
83
|
const version = strategy.readVersion(cwd, loaded.config);
|
|
79
84
|
const defaultTag = `v${version}`;
|
|
80
85
|
const releaseTargets = (0, state_js_1.readReleaseTargets)(cwd);
|
|
@@ -98,16 +103,7 @@ async function runSimpleReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
|
98
103
|
message: `Dry run: would publish releases ${targetList.join(", ")}`,
|
|
99
104
|
};
|
|
100
105
|
}
|
|
101
|
-
const
|
|
102
|
-
const scmPlugins = (0, capabilities_js_1.findPluginsByCapability)(plugins, "scm.releaseMetadata");
|
|
103
|
-
if (scmPlugins.length === 0) {
|
|
104
|
-
throw new Error("No scm.releaseMetadata plugin is available.");
|
|
105
|
-
}
|
|
106
|
-
const plugin = scmPlugins[0];
|
|
107
|
-
if (!plugin?.createReleaseMetadata) {
|
|
108
|
-
throw new Error(`Plugin "${plugin?.name ?? "unknown"}" does not implement createReleaseMetadata.`);
|
|
109
|
-
}
|
|
110
|
-
const createReleaseMetadata = plugin.createReleaseMetadata;
|
|
106
|
+
const scmClient = (0, client_js_1.getScmClient)();
|
|
111
107
|
const releases = [];
|
|
112
108
|
for (const target of targets) {
|
|
113
109
|
const targetChangelogFile = resolveTargetChangelogFile(loaded.config, changelogFile, target.path);
|
|
@@ -115,8 +111,9 @@ async function runSimpleReleaseDetailed(cwd = process.cwd(), options = {}) {
|
|
|
115
111
|
tag: target.tag,
|
|
116
112
|
version: target.version,
|
|
117
113
|
notes: readReleaseNotes(cwd, target.version, targetChangelogFile),
|
|
114
|
+
draft: loaded.config["release-draft"] ?? false,
|
|
118
115
|
}, {
|
|
119
|
-
createReleaseMetadata: (input) => createReleaseMetadata(input, {
|
|
116
|
+
createReleaseMetadata: (input) => scmClient.createReleaseMetadata(input, {
|
|
120
117
|
cwd,
|
|
121
118
|
logger: options.logger,
|
|
122
119
|
}),
|
|
@@ -10,7 +10,7 @@ exports.writeBaselineSha = writeBaselineSha;
|
|
|
10
10
|
const node_child_process_1 = require("node:child_process");
|
|
11
11
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
12
12
|
const node_path_1 = __importDefault(require("node:path"));
|
|
13
|
-
const load_config_js_1 = require("
|
|
13
|
+
const load_config_js_1 = require("../config/load-config.js");
|
|
14
14
|
const MANIFEST_VERSION_KEY = "manifest-version";
|
|
15
15
|
const BASELINE_SHA_KEY = "baseline-sha";
|
|
16
16
|
const RELEASE_TARGETS_KEY = "release-targets";
|
|
@@ -7,8 +7,8 @@ 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 package_context_js_1 = require("../
|
|
11
|
-
const resolve_js_1 = require("../
|
|
10
|
+
const package_context_js_1 = require("../strategy/package-context.js");
|
|
11
|
+
const resolve_js_1 = require("../strategy/resolve.js");
|
|
12
12
|
function verifyProject(cwd = process.cwd()) {
|
|
13
13
|
const checks = [];
|
|
14
14
|
const config = (0, load_config_js_1.loadConfig)(cwd);
|
|
@@ -90,6 +90,7 @@ function createGitHubPlugin() {
|
|
|
90
90
|
return {
|
|
91
91
|
name: "github",
|
|
92
92
|
capabilities: ["scm.reviewRequest", "scm.releaseMetadata"],
|
|
93
|
+
provider: "github",
|
|
93
94
|
async createOrUpdateReviewRequest(input, _context) {
|
|
94
95
|
const repo = getRepoFromEnv();
|
|
95
96
|
const octokit = new rest_1.Octokit({ auth: getGitHubToken() });
|
|
@@ -194,6 +195,7 @@ function createGitHubPlugin() {
|
|
|
194
195
|
tag_name: input.tag,
|
|
195
196
|
name: input.tag,
|
|
196
197
|
body: input.notes,
|
|
198
|
+
draft: input.draft ?? false,
|
|
197
199
|
});
|
|
198
200
|
data = response.data;
|
|
199
201
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type ScmProvider = "github";
|
|
2
|
+
export interface ScmClientContext {
|
|
3
|
+
cwd: string;
|
|
4
|
+
logger?: {
|
|
5
|
+
info: (message: string) => void;
|
|
6
|
+
warn: (message: string) => void;
|
|
7
|
+
error: (message: string) => void;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export interface ScmReviewRequestInput {
|
|
11
|
+
baseBranch: string;
|
|
12
|
+
headBranch: string;
|
|
13
|
+
title: string;
|
|
14
|
+
body: string;
|
|
15
|
+
labels?: string[];
|
|
16
|
+
}
|
|
17
|
+
export interface ScmReviewRequestResult {
|
|
18
|
+
id: string;
|
|
19
|
+
number?: number;
|
|
20
|
+
url: string;
|
|
21
|
+
state: "open" | "closed" | "merged";
|
|
22
|
+
}
|
|
23
|
+
export interface ScmReleaseMetadataInput {
|
|
24
|
+
tag: string;
|
|
25
|
+
version: string;
|
|
26
|
+
notes: string;
|
|
27
|
+
draft?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface ScmReleaseMetadataResult {
|
|
30
|
+
url: string;
|
|
31
|
+
status?: "created" | "exists";
|
|
32
|
+
}
|
|
33
|
+
export interface ScmClient {
|
|
34
|
+
provider: ScmProvider;
|
|
35
|
+
createOrUpdateReviewRequest: (input: ScmReviewRequestInput, context: ScmClientContext) => Promise<ScmReviewRequestResult>;
|
|
36
|
+
createReleaseMetadata: (input: ScmReleaseMetadataInput, context: ScmClientContext) => Promise<ScmReleaseMetadataResult>;
|
|
37
|
+
}
|
|
@@ -64,4 +64,17 @@ exports.nodeVersionStrategy = {
|
|
|
64
64
|
];
|
|
65
65
|
return updatedFiles;
|
|
66
66
|
},
|
|
67
|
+
readPackageName(cwd, config) {
|
|
68
|
+
const versionFile = this.getVersionFile(config);
|
|
69
|
+
const versionPath = node_path_1.default.join(cwd, versionFile);
|
|
70
|
+
if (!node_fs_1.default.existsSync(versionPath)) {
|
|
71
|
+
throw new Error(`Versionary requires ${versionFile} to exist.`);
|
|
72
|
+
}
|
|
73
|
+
const packageJson = readJsonFile(versionPath);
|
|
74
|
+
const name = packageJson.name;
|
|
75
|
+
if (typeof name !== "string" || name.trim().length === 0) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return name.trim();
|
|
79
|
+
},
|
|
67
80
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { VersionaryConfig, VersionaryPackage } from "
|
|
1
|
+
import type { VersionaryConfig, VersionaryPackage } from "../types/config.js";
|
|
2
2
|
import type { VersionStrategy } from "./types.js";
|
|
3
3
|
export declare function resolvePackageStrategyContext(rootConfig: VersionaryConfig, packagePath: string, packageConfig: VersionaryPackage): {
|
|
4
4
|
strategy: VersionStrategy;
|
|
@@ -34,7 +34,7 @@ function resolvePackageStrategyContext(rootConfig, packagePath, packageConfig) {
|
|
|
34
34
|
}));
|
|
35
35
|
const config = withVersionFile({
|
|
36
36
|
...baseConfig,
|
|
37
|
-
packages: undefined,
|
|
37
|
+
packages: packagePath === "." ? baseConfig.packages : undefined,
|
|
38
38
|
}, versionFile);
|
|
39
39
|
return {
|
|
40
40
|
strategy: baseStrategy,
|
|
@@ -50,7 +50,7 @@ function resolvePackageStrategyContext(rootConfig, packagePath, packageConfig) {
|
|
|
50
50
|
}));
|
|
51
51
|
const config = withVersionFile({
|
|
52
52
|
...baseConfig,
|
|
53
|
-
packages: undefined,
|
|
53
|
+
packages: packagePath === "." ? baseConfig.packages : undefined,
|
|
54
54
|
}, packageVersionFile);
|
|
55
55
|
const strategy = (0, resolve_js_1.resolveVersionStrategy)(config);
|
|
56
56
|
return {
|
|
@@ -43,4 +43,18 @@ exports.rVersionStrategy = {
|
|
|
43
43
|
node_fs_1.default.writeFileSync(versionPath, updated, "utf8");
|
|
44
44
|
return [versionFile];
|
|
45
45
|
},
|
|
46
|
+
readPackageName(cwd, config) {
|
|
47
|
+
const versionFile = this.getVersionFile(config);
|
|
48
|
+
const versionPath = node_path_1.default.join(cwd, versionFile);
|
|
49
|
+
if (!node_fs_1.default.existsSync(versionPath)) {
|
|
50
|
+
throw new Error(`Versionary requires ${versionFile} to exist.`);
|
|
51
|
+
}
|
|
52
|
+
const content = node_fs_1.default.readFileSync(versionPath, "utf8");
|
|
53
|
+
const match = content.match(/^Package:\s*(.+)\s*$/mu);
|
|
54
|
+
if (!match?.[1]) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const name = match[1].trim();
|
|
58
|
+
return name.length > 0 ? name : null;
|
|
59
|
+
},
|
|
46
60
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type { VersionaryConfig } from "
|
|
1
|
+
import type { VersionaryConfig } from "../types/config.js";
|
|
2
2
|
import type { VersionStrategy } from "./types.js";
|
|
3
|
+
export declare function listKnownReleaseTypes(): string[];
|
|
3
4
|
export declare function resolveVersionStrategy(config: VersionaryConfig): VersionStrategy;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listKnownReleaseTypes = listKnownReleaseTypes;
|
|
4
|
+
exports.resolveVersionStrategy = resolveVersionStrategy;
|
|
5
|
+
const node_js_1 = require("./node.js");
|
|
6
|
+
const r_js_1 = require("./r.js");
|
|
7
|
+
const rust_js_1 = require("./rust.js");
|
|
8
|
+
const simple_js_1 = require("./simple.js");
|
|
9
|
+
const strategyRegistry = {
|
|
10
|
+
simple: simple_js_1.simpleVersionStrategy,
|
|
11
|
+
node: node_js_1.nodeVersionStrategy,
|
|
12
|
+
rust: rust_js_1.rustVersionStrategy,
|
|
13
|
+
r: r_js_1.rVersionStrategy,
|
|
14
|
+
};
|
|
15
|
+
function listKnownReleaseTypes() {
|
|
16
|
+
return Object.keys(strategyRegistry).sort((a, b) => a.localeCompare(b));
|
|
17
|
+
}
|
|
18
|
+
function resolveVersionStrategy(config) {
|
|
19
|
+
const releaseType = config["release-type"] ?? "simple";
|
|
20
|
+
return strategyRegistry[releaseType] ?? simple_js_1.simpleVersionStrategy;
|
|
21
|
+
}
|
|
@@ -613,4 +613,46 @@ exports.rustVersionStrategy = {
|
|
|
613
613
|
}
|
|
614
614
|
return updatedFiles.sort((a, b) => a.localeCompare(b));
|
|
615
615
|
},
|
|
616
|
+
readPackageName(cwd, config) {
|
|
617
|
+
const versionFile = this.getVersionFile(config);
|
|
618
|
+
const manifests = collectRustTargetManifests(cwd, versionFile, !config.packages);
|
|
619
|
+
const selectedManifest = manifests[0];
|
|
620
|
+
if (!selectedManifest) {
|
|
621
|
+
throw new Error(`Configured rust target "${versionFile}" did not resolve to a Rust crate manifest.`);
|
|
622
|
+
}
|
|
623
|
+
const versionPath = node_path_1.default.join(cwd, selectedManifest);
|
|
624
|
+
if (!node_fs_1.default.existsSync(versionPath)) {
|
|
625
|
+
throw new Error(`Versionary requires ${selectedManifest} to exist.`);
|
|
626
|
+
}
|
|
627
|
+
const cargoTomlRaw = node_fs_1.default.readFileSync(versionPath, "utf8");
|
|
628
|
+
if (!isCrateManifest(selectedManifest, cargoTomlRaw)) {
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
return readCargoPackageName(cargoTomlRaw, selectedManifest);
|
|
632
|
+
},
|
|
633
|
+
propagateDependentPatchImpacts(cwd, packages) {
|
|
634
|
+
const manifestToVersion = {};
|
|
635
|
+
const candidateManifests = [];
|
|
636
|
+
const manifestToPath = new Map();
|
|
637
|
+
for (const pkg of packages) {
|
|
638
|
+
const manifest = pkg.versionFile;
|
|
639
|
+
candidateManifests.push(manifest);
|
|
640
|
+
manifestToPath.set(manifest, pkg.packagePath);
|
|
641
|
+
if (pkg.nextVersion) {
|
|
642
|
+
manifestToVersion[manifest] = pkg.nextVersion;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
const impactedManifests = detectRustDependencyImpact(cwd, manifestToVersion, candidateManifests);
|
|
646
|
+
return impactedManifests
|
|
647
|
+
.map((manifest) => manifestToPath.get(manifest))
|
|
648
|
+
.filter((pkgPath) => Boolean(pkgPath))
|
|
649
|
+
.sort((a, b) => a.localeCompare(b));
|
|
650
|
+
},
|
|
651
|
+
finalizeVersionWrites(cwd, writes) {
|
|
652
|
+
const manifestToVersion = {};
|
|
653
|
+
for (const write of writes) {
|
|
654
|
+
manifestToVersion[write.versionFile] = write.version;
|
|
655
|
+
}
|
|
656
|
+
return applyRustWorkspaceDependencyUpdates(cwd, manifestToVersion);
|
|
657
|
+
},
|
|
616
658
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { VersionaryConfig } from "../types/config.js";
|
|
2
|
+
export interface StrategyPackagePlanContext {
|
|
3
|
+
packagePath: string;
|
|
4
|
+
versionFile: string;
|
|
5
|
+
currentVersion: string;
|
|
6
|
+
nextVersion: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface StrategyVersionWriteContext {
|
|
9
|
+
packagePath: string;
|
|
10
|
+
versionFile: string;
|
|
11
|
+
version: string;
|
|
12
|
+
}
|
|
13
|
+
export interface VersionStrategy {
|
|
14
|
+
name: string;
|
|
15
|
+
getVersionFile(config: VersionaryConfig): string;
|
|
16
|
+
readVersion(cwd: string, config: VersionaryConfig): string;
|
|
17
|
+
writeVersion(cwd: string, config: VersionaryConfig, version: string): string[];
|
|
18
|
+
readPackageName?(cwd: string, config: VersionaryConfig): string | null;
|
|
19
|
+
propagateDependentPatchImpacts?(cwd: string, packages: StrategyPackagePlanContext[]): string[];
|
|
20
|
+
finalizeVersionWrites?(cwd: string, writes: StrategyVersionWriteContext[]): string[];
|
|
21
|
+
}
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type ConfigFileFormat = "jsonc" | "json" | "toml" | "js";
|
|
2
|
+
export type VersionaryChangelogFormat = "markdown-changelog" | "r-news";
|
|
2
3
|
export interface VersionaryArtifactRule {
|
|
3
4
|
type: "json" | "toml" | "yaml" | "regex";
|
|
4
5
|
path: string;
|
|
@@ -10,6 +11,7 @@ export interface VersionaryPackage {
|
|
|
10
11
|
"release-type"?: string;
|
|
11
12
|
"package-name"?: string;
|
|
12
13
|
"changelog-file"?: string;
|
|
14
|
+
"changelog-format"?: VersionaryChangelogFormat;
|
|
13
15
|
"exclude-paths"?: string[];
|
|
14
16
|
"extra-files"?: VersionaryArtifactRule[];
|
|
15
17
|
}
|
|
@@ -18,6 +20,8 @@ export interface VersionaryConfig {
|
|
|
18
20
|
"review-mode"?: "direct" | "pr" | "review";
|
|
19
21
|
"version-file"?: string;
|
|
20
22
|
"changelog-file"?: string;
|
|
23
|
+
"changelog-format"?: VersionaryChangelogFormat;
|
|
24
|
+
"release-draft"?: boolean;
|
|
21
25
|
"release-branch"?: string;
|
|
22
26
|
"baseline-file"?: string;
|
|
23
27
|
"bootstrap-sha"?: string;
|
package/dist/types/plugins.d.ts
CHANGED
|
@@ -1,37 +1,14 @@
|
|
|
1
|
+
import type { ScmClientContext, ScmProvider, ScmReleaseMetadataInput, ScmReleaseMetadataResult, ScmReviewRequestInput, ScmReviewRequestResult } from "../scm/types.js";
|
|
1
2
|
export type VersionaryPluginCapability = "scm.reviewRequest" | "scm.releaseMetadata";
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
labels?: string[];
|
|
8
|
-
}
|
|
9
|
-
export interface VersionaryScmReviewRequestResult {
|
|
10
|
-
id: string;
|
|
11
|
-
number?: number;
|
|
12
|
-
url: string;
|
|
13
|
-
state: "open" | "closed" | "merged";
|
|
14
|
-
}
|
|
15
|
-
export interface VersionaryScmReleaseMetadataInput {
|
|
16
|
-
tag: string;
|
|
17
|
-
version: string;
|
|
18
|
-
notes: string;
|
|
19
|
-
}
|
|
20
|
-
export interface VersionaryScmReleaseMetadataResult {
|
|
21
|
-
url: string;
|
|
22
|
-
status?: "created" | "exists";
|
|
23
|
-
}
|
|
24
|
-
export interface VersionaryPluginContext {
|
|
25
|
-
cwd: string;
|
|
26
|
-
logger?: {
|
|
27
|
-
info: (message: string) => void;
|
|
28
|
-
warn: (message: string) => void;
|
|
29
|
-
error: (message: string) => void;
|
|
30
|
-
};
|
|
31
|
-
}
|
|
3
|
+
export type VersionaryScmReviewRequestInput = ScmReviewRequestInput;
|
|
4
|
+
export type VersionaryScmReviewRequestResult = ScmReviewRequestResult;
|
|
5
|
+
export type VersionaryScmReleaseMetadataInput = ScmReleaseMetadataInput;
|
|
6
|
+
export type VersionaryScmReleaseMetadataResult = ScmReleaseMetadataResult;
|
|
7
|
+
export type VersionaryPluginContext = ScmClientContext;
|
|
32
8
|
export interface VersionaryPluginRuntime {
|
|
33
9
|
name: string;
|
|
34
10
|
capabilities: VersionaryPluginCapability[];
|
|
11
|
+
provider?: ScmProvider;
|
|
35
12
|
createOrUpdateReviewRequest?: (input: VersionaryScmReviewRequestInput, context: VersionaryPluginContext) => Promise<VersionaryScmReviewRequestResult>;
|
|
36
13
|
createReleaseMetadata?: (input: VersionaryScmReleaseMetadataInput, context: VersionaryPluginContext) => Promise<VersionaryScmReleaseMetadataResult>;
|
|
37
14
|
}
|
package/package.json
CHANGED