versionary 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action/index.js +4 -0
- package/dist/cli/index.js +211 -24
- package/dist/config/schema.d.ts +2 -0
- package/dist/config/schema.js +32 -0
- package/dist/index.d.ts +2 -2
- package/dist/release/artifact-rules.js +27 -28
- package/dist/release/cohorts.d.ts +6 -0
- package/dist/release/cohorts.js +125 -0
- package/dist/release/plan.js +49 -45
- package/dist/release/pr.d.ts +69 -0
- package/dist/release/pr.js +555 -22
- package/dist/release/release.d.ts +12 -0
- package/dist/release/release.js +26 -7
- package/dist/release/state.d.ts +16 -1
- package/dist/release/state.js +182 -9
- package/dist/release/targets.d.ts +21 -0
- package/dist/release/targets.js +85 -0
- package/dist/scm/github-plugin.js +44 -0
- package/dist/scm/types.d.ts +11 -0
- package/dist/strategy/cmake.d.ts +2 -0
- package/dist/strategy/cmake.js +283 -0
- package/dist/strategy/resolve.js +2 -0
- package/dist/types/config.d.ts +2 -0
- package/dist/types/plugins.d.ts +3 -1
- package/package.json +3 -1
package/dist/release/plan.js
CHANGED
|
@@ -259,6 +259,50 @@ export function createReleasePlan(cwd = process.cwd()) {
|
|
|
259
259
|
}
|
|
260
260
|
return reachable;
|
|
261
261
|
};
|
|
262
|
+
const withReleasingDependencies = (plans) => {
|
|
263
|
+
const releasingPaths = new Set(plans
|
|
264
|
+
.filter((pkgPlan) => pkgPlan.nextVersion)
|
|
265
|
+
.map((pkgPlan) => pkgPlan.path));
|
|
266
|
+
for (const pkgPlan of plans) {
|
|
267
|
+
const strategyContext = strategyContextByPath.get(pkgPlan.path);
|
|
268
|
+
if (strategyContext) {
|
|
269
|
+
strategyContext.nextVersion = pkgPlan.nextVersion;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const dependencySourcePathsByPackage = new Map();
|
|
273
|
+
for (const sourcePackage of plans) {
|
|
274
|
+
if (!sourcePackage.nextVersion) {
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
for (const impactedPath of findDependents(sourcePackage.path)) {
|
|
278
|
+
if (impactedPath === sourcePackage.path) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
const existing = dependencySourcePathsByPackage.get(impactedPath);
|
|
282
|
+
if (existing) {
|
|
283
|
+
existing.add(sourcePackage.path);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
dependencySourcePathsByPackage.set(impactedPath, new Set([sourcePackage.path]));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return plans.map((pkgPlan) => {
|
|
291
|
+
const dependencySourcePaths = [
|
|
292
|
+
...(dependencySourcePathsByPackage.get(pkgPlan.path) ??
|
|
293
|
+
new Set()),
|
|
294
|
+
]
|
|
295
|
+
.filter((sourcePath) => releasingPaths.has(sourcePath))
|
|
296
|
+
.sort((a, b) => a.localeCompare(b));
|
|
297
|
+
if (dependencySourcePaths.length === 0) {
|
|
298
|
+
return pkgPlan;
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
...pkgPlan,
|
|
302
|
+
dependencySourcePaths,
|
|
303
|
+
};
|
|
304
|
+
});
|
|
305
|
+
};
|
|
262
306
|
// Both rules below can enable each other: forcing a bump creates a dependent
|
|
263
307
|
// whose requirement must be rewritten, and rewriting a dependent can in turn
|
|
264
308
|
// expose a stale dependency a further level up. Iterating to a fixpoint
|
|
@@ -302,51 +346,9 @@ export function createReleasePlan(cwd = process.cwd()) {
|
|
|
302
346
|
break;
|
|
303
347
|
}
|
|
304
348
|
}
|
|
305
|
-
const packageNextVersionByPath = {};
|
|
306
|
-
for (const pkgPlan of workingPlans) {
|
|
307
|
-
if (pkgPlan.nextVersion) {
|
|
308
|
-
packageNextVersionByPath[pkgPlan.path] = pkgPlan.nextVersion;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
const dependencySourcePathsByPackage = new Map();
|
|
312
|
-
const addDependencySourcePath = (targetPath, sourcePath) => {
|
|
313
|
-
if (targetPath === sourcePath) {
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
const existing = dependencySourcePathsByPackage.get(targetPath);
|
|
317
|
-
if (existing) {
|
|
318
|
-
existing.add(sourcePath);
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
dependencySourcePathsByPackage.set(targetPath, new Set([sourcePath]));
|
|
322
|
-
};
|
|
323
349
|
// Attribute each dependent's requirement rewrite to the specific sources
|
|
324
350
|
// driving it, using the settled version set so chained bumps are credited.
|
|
325
|
-
|
|
326
|
-
for (const sourcePackage of strategyGroup.packages) {
|
|
327
|
-
if (!sourcePackage.nextVersion) {
|
|
328
|
-
continue;
|
|
329
|
-
}
|
|
330
|
-
for (const impactedPath of findDependents(sourcePackage.packagePath)) {
|
|
331
|
-
addDependencySourcePath(impactedPath, sourcePackage.packagePath);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
const propagatedPackages = workingPlans.map((pkgPlan) => {
|
|
336
|
-
const dependencySourcePaths = [
|
|
337
|
-
...(dependencySourcePathsByPackage.get(pkgPlan.path) ??
|
|
338
|
-
new Set()),
|
|
339
|
-
]
|
|
340
|
-
.filter((sourcePath) => Boolean(packageNextVersionByPath[sourcePath]))
|
|
341
|
-
.sort((a, b) => a.localeCompare(b));
|
|
342
|
-
if (dependencySourcePaths.length === 0) {
|
|
343
|
-
return pkgPlan;
|
|
344
|
-
}
|
|
345
|
-
return {
|
|
346
|
-
...pkgPlan,
|
|
347
|
-
dependencySourcePaths,
|
|
348
|
-
};
|
|
349
|
-
});
|
|
351
|
+
const propagatedPackages = withReleasingDependencies(workingPlans);
|
|
350
352
|
const followsByPath = new Map();
|
|
351
353
|
for (const [packagePath, packageConfig] of Object.entries(loaded.config.packages ?? {})) {
|
|
352
354
|
const follows = packageConfig.follows ?? [];
|
|
@@ -429,11 +431,13 @@ export function createReleasePlan(cwd = process.cwd()) {
|
|
|
429
431
|
: analyzedFixedType
|
|
430
432
|
? bumpVersion(fixedBaseVersion, analyzedFixedType, { allowStableMajor })
|
|
431
433
|
: null;
|
|
432
|
-
|
|
434
|
+
// Fixed mode can promote unchanged dependencies into the release, so the
|
|
435
|
+
// final shared version set must drive dependency attribution.
|
|
436
|
+
const adjusted = withReleasingDependencies(adjustedPackages.map((pkgPlan) => ({
|
|
433
437
|
...pkgPlan,
|
|
434
438
|
releaseType: fixedType,
|
|
435
439
|
nextVersion: fixedNextVersion,
|
|
436
|
-
}));
|
|
440
|
+
})));
|
|
437
441
|
return {
|
|
438
442
|
mode: "simple",
|
|
439
443
|
releaseType: fixedType,
|
package/dist/release/pr.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ParsedCommit } from "../git/commits.js";
|
|
|
2
2
|
import type { VersionaryChangelogFormat, VersionaryConfig } from "../types/config.js";
|
|
3
3
|
import type { VersionaryPluginContext } from "../types/plugins.js";
|
|
4
4
|
import { type ReleasePlan } from "./plan.js";
|
|
5
|
+
import { type ReleaseTargetState } from "./state.js";
|
|
5
6
|
/**
|
|
6
7
|
* Read the manual-notes ("Unreleased") prose from the top of a changelog file.
|
|
7
8
|
* Returns an empty string when the file is absent or has no notes block.
|
|
@@ -20,6 +21,31 @@ export declare function splitSafeDirtyFiles(files: string[]): {
|
|
|
20
21
|
ignored: string[];
|
|
21
22
|
blocking: string[];
|
|
22
23
|
};
|
|
24
|
+
export interface PendingReleasePrResult {
|
|
25
|
+
branch: string;
|
|
26
|
+
title: string;
|
|
27
|
+
updated: boolean;
|
|
28
|
+
targets: ReleaseTargetState[];
|
|
29
|
+
body: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function renderPendingReleaseReviewRequestBody(targets: ReleaseTargetState[]): string;
|
|
32
|
+
/**
|
|
33
|
+
* Recreate the release marker on the corrected base without advancing an
|
|
34
|
+
* untagged version. The empty commit is intentional: the version and
|
|
35
|
+
* changelog changes were already reviewed in the original release PR.
|
|
36
|
+
*/
|
|
37
|
+
export declare function preparePendingReleasePr(cwd?: string, options?: {
|
|
38
|
+
logger?: VersionaryPluginContext["logger"];
|
|
39
|
+
}): PendingReleasePrResult;
|
|
40
|
+
/**
|
|
41
|
+
* Recreate each unpublished package cohort on its own corrected-base branch.
|
|
42
|
+
* A temporary worktree keeps the caller on the trunk commit that triggered
|
|
43
|
+
* recovery while still leaving local branch refs available for pushing.
|
|
44
|
+
*/
|
|
45
|
+
export declare function preparePendingSeparateReleasePrs(cwd?: string, options?: {
|
|
46
|
+
logger?: VersionaryPluginContext["logger"];
|
|
47
|
+
"dry-run"?: boolean;
|
|
48
|
+
}): SeparateReviewCandidate[];
|
|
23
49
|
export declare function prepareReleasePr(cwd?: string, options?: {
|
|
24
50
|
logger?: VersionaryPluginContext["logger"];
|
|
25
51
|
}): {
|
|
@@ -32,11 +58,54 @@ export declare function prepareReleasePr(cwd?: string, options?: {
|
|
|
32
58
|
updated: boolean;
|
|
33
59
|
highlights: string;
|
|
34
60
|
};
|
|
61
|
+
export interface PreparedSeparateReleasePr {
|
|
62
|
+
branch: string;
|
|
63
|
+
title: string;
|
|
64
|
+
version: string;
|
|
65
|
+
previousVersion: string;
|
|
66
|
+
commits: ParsedCommit[];
|
|
67
|
+
plan: ReleasePlan;
|
|
68
|
+
updated: boolean;
|
|
69
|
+
highlights: string;
|
|
70
|
+
packagePaths: string[];
|
|
71
|
+
targets: ReleaseTargetState[];
|
|
72
|
+
body: string;
|
|
73
|
+
}
|
|
74
|
+
export interface SeparateReviewCandidate {
|
|
75
|
+
branch: string;
|
|
76
|
+
title: string;
|
|
77
|
+
updated: boolean;
|
|
78
|
+
packagePaths: string[];
|
|
79
|
+
targets: ReleaseTargetState[];
|
|
80
|
+
body: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Build every independently mergeable release branch from the same immutable
|
|
84
|
+
* base without moving or modifying the caller's worktree.
|
|
85
|
+
*/
|
|
86
|
+
export declare function prepareSeparateReleasePrs(cwd?: string, options?: {
|
|
87
|
+
logger?: VersionaryPluginContext["logger"];
|
|
88
|
+
"dry-run"?: boolean;
|
|
89
|
+
}): PreparedSeparateReleasePr[];
|
|
35
90
|
export declare function renderSimpleReviewRequestBody(version: string, previousVersion: string, commits: ParsedCommit[], plan?: ReleasePlan | null, cwd?: string, highlights?: string, loadedConfig?: VersionaryConfig): string;
|
|
36
91
|
export declare function openOrUpdateReviewRequest(cwd: string, branch: string, title: string, version: string, previousVersion: string, commits: ParsedCommit[], plan?: ReleasePlan | null, options?: {
|
|
37
92
|
logger?: VersionaryPluginContext["logger"];
|
|
38
93
|
highlights?: string;
|
|
94
|
+
body?: string;
|
|
39
95
|
}): Promise<string>;
|
|
96
|
+
export interface ReviewRequestRunResult {
|
|
97
|
+
packagePaths: string[];
|
|
98
|
+
branch: string;
|
|
99
|
+
title: string;
|
|
100
|
+
reviewUrl?: string;
|
|
101
|
+
status: "prepared" | "up-to-date" | "dry-run" | "recovered";
|
|
102
|
+
targets: ReleaseTargetState[];
|
|
103
|
+
}
|
|
104
|
+
export declare function reconcileSeparateReviewRequests(cwd: string, prepared: SeparateReviewCandidate[], options?: {
|
|
105
|
+
logger?: VersionaryPluginContext["logger"];
|
|
106
|
+
"dry-run"?: boolean;
|
|
107
|
+
recovered?: boolean;
|
|
108
|
+
}): Promise<ReviewRequestRunResult[]>;
|
|
40
109
|
export declare function closeStaleReviewRequestIfExists(cwd?: string, options?: {
|
|
41
110
|
logger?: VersionaryPluginContext["logger"];
|
|
42
111
|
}): Promise<{
|