tegami 1.2.2 → 1.2.4
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/{_accessExpressionAsString-QhbUZzwv.js → _accessExpressionAsString-DW_6Xqcp.js} +1 -1
- package/dist/{_assertGuard-BBn2NbSz.js → _assertGuard-CFFC1Up9.js} +2 -2
- package/dist/{_createStandardSchema-BGQyz-uA.js → _createStandardSchema-CrRqJgaE.js} +2 -2
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +10 -8
- package/dist/{generate-Cnd8RiKO.js → generate-Cgl2G5ea.js} +2 -2
- package/dist/generators/simple.d.ts +1 -1
- package/dist/generators/simple.js +1 -1
- package/dist/{graph-BmXTJZxx.js → graph-DaJ28Y4f.js} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +14 -8
- package/dist/{npm-cS-D2xGI.js → npm-CyC2Rk11.js} +221 -133
- package/dist/plugins/cargo.d.ts +1 -1
- package/dist/plugins/cargo.js +37 -34
- package/dist/plugins/git.d.ts +1 -1
- package/dist/plugins/git.js +2 -4
- package/dist/plugins/github.d.ts +7 -7
- package/dist/plugins/github.js +113 -241
- package/dist/plugins/gitlab.d.ts +6 -6
- package/dist/plugins/gitlab.js +118 -245
- package/dist/plugins/go.d.ts +1 -1
- package/dist/plugins/go.js +10 -10
- package/dist/providers/npm.d.ts +1 -1
- package/dist/providers/npm.js +1 -1
- package/dist/{publish-Bt3e1RPs.js → publish-DAMkayLs.js} +11 -15
- package/dist/{semver-EKJ8yK5U.js → semver-DrtaCCZK.js} +15 -3
- package/dist/{shared-C_iSTp_s.js → shared-pTOZU5UZ.js} +11 -3
- package/dist/{types-C_vz41r2.d.ts → types-BMYzG4dR.d.ts} +42 -26
- package/dist/{version-request-DXk_B7O_.d.ts → version-request-BorZZ98V.d.ts} +1 -1
- package/dist/{version-request-DvWVAYj2.js → version-request-CQ4cJHtP.js} +203 -67
- package/package.json +5 -4
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { Agent, AgentName } from "package-manager-detector";
|
|
2
|
-
|
|
3
1
|
//#region src/utils/semver.d.ts
|
|
4
2
|
type BumpType = "major" | "minor" | "patch";
|
|
5
3
|
//#endregion
|
|
@@ -183,7 +181,7 @@ interface PackageDraft {
|
|
|
183
181
|
/** npm dist-tag used when publishing. */distTag?: string;
|
|
184
182
|
};
|
|
185
183
|
/** get the bumped version of a package, return `undefined` if the package doesn't have a `version` field */
|
|
186
|
-
bumpVersion: (pkg: WorkspacePackage) => string | undefined;
|
|
184
|
+
bumpVersion: (pkg: WorkspacePackage$1) => string | undefined;
|
|
187
185
|
}
|
|
188
186
|
/** a draft describes all operations to perform before the actual publishing, such as version bumps. */
|
|
189
187
|
declare class Draft {
|
|
@@ -197,15 +195,15 @@ declare class Draft {
|
|
|
197
195
|
constructor(context: TegamiContext);
|
|
198
196
|
getPackageDrafts(): Map<string, PackageDraft>;
|
|
199
197
|
getPackageDraft(id: string): PackageDraft | undefined;
|
|
200
|
-
bumpPackage(pkg: WorkspacePackage, {
|
|
198
|
+
bumpPackage(pkg: WorkspacePackage$1, {
|
|
201
199
|
type,
|
|
202
200
|
reason
|
|
203
201
|
}: {
|
|
204
202
|
type: BumpType;
|
|
205
203
|
reason?: string;
|
|
206
204
|
}): PackageDraft;
|
|
207
|
-
dispatchPackage(pkg: WorkspacePackage, dispatch: (draft: PackageDraft) => void, onUpdate?: (draft: PackageDraft) => void): PackageDraft;
|
|
208
|
-
getOrInitPackage(pkg: WorkspacePackage): PackageDraft;
|
|
205
|
+
dispatchPackage(pkg: WorkspacePackage$1, dispatch: (draft: PackageDraft) => void, onUpdate?: (draft: PackageDraft) => void): PackageDraft;
|
|
206
|
+
getOrInitPackage(pkg: WorkspacePackage$1): PackageDraft;
|
|
209
207
|
hasPending(): boolean;
|
|
210
208
|
/** get all changelogs, note that this includes replay-only changelogs, as long as they are in the `.tegami` folder. */
|
|
211
209
|
getChangelogs(): ChangelogEntry[];
|
|
@@ -229,13 +227,13 @@ interface DraftPolicy {
|
|
|
229
227
|
id: string;
|
|
230
228
|
onUpdate?: (this: Draft, opts: {
|
|
231
229
|
packageDraft: PackageDraft;
|
|
232
|
-
pkg: WorkspacePackage;
|
|
230
|
+
pkg: WorkspacePackage$1;
|
|
233
231
|
}) => void;
|
|
234
232
|
}
|
|
235
233
|
//#endregion
|
|
236
234
|
//#region src/graph.d.ts
|
|
237
235
|
/** Package discovered in the workspace. */
|
|
238
|
-
declare abstract class WorkspacePackage {
|
|
236
|
+
declare abstract class WorkspacePackage$1 {
|
|
239
237
|
abstract readonly name: string;
|
|
240
238
|
/** absolute path */
|
|
241
239
|
abstract readonly path: string;
|
|
@@ -258,7 +256,7 @@ declare abstract class WorkspacePackage {
|
|
|
258
256
|
interface PackageGroup {
|
|
259
257
|
name: string;
|
|
260
258
|
options: GroupOptions;
|
|
261
|
-
packages: WorkspacePackage[];
|
|
259
|
+
packages: WorkspacePackage$1[];
|
|
262
260
|
}
|
|
263
261
|
/**
|
|
264
262
|
* Unified graph for discovered workspace packages.
|
|
@@ -269,14 +267,14 @@ interface PackageGroup {
|
|
|
269
267
|
declare class PackageGraph {
|
|
270
268
|
private readonly packages;
|
|
271
269
|
private readonly groups;
|
|
272
|
-
constructor(packages?: WorkspacePackage[]);
|
|
273
|
-
getPackages(): WorkspacePackage[];
|
|
270
|
+
constructor(packages?: WorkspacePackage$1[]);
|
|
271
|
+
getPackages(): WorkspacePackage$1[];
|
|
274
272
|
/** Get a package by exact id. */
|
|
275
|
-
get(id: string): WorkspacePackage | undefined;
|
|
273
|
+
get(id: string): WorkspacePackage$1 | undefined;
|
|
276
274
|
/** Get packages by id, `group:name`, or every package matching a name. */
|
|
277
|
-
getByName(nameOrId: string): WorkspacePackage[];
|
|
275
|
+
getByName(nameOrId: string): WorkspacePackage$1[];
|
|
278
276
|
/** scan package into graph, if the package id already exists, replace the existing one in graph */
|
|
279
|
-
add(pkg: WorkspacePackage): void;
|
|
277
|
+
add(pkg: WorkspacePackage$1): void;
|
|
280
278
|
delete(id: string): void;
|
|
281
279
|
getPackageGroup(pkgId: string): PackageGroup | undefined;
|
|
282
280
|
getGroups(): PackageGroup[];
|
|
@@ -287,6 +285,10 @@ declare class PackageGraph {
|
|
|
287
285
|
unregisterGroup(name: string): void;
|
|
288
286
|
}
|
|
289
287
|
//#endregion
|
|
288
|
+
//#region ../../node_modules/.pnpm/package-manager-detector@1.7.0/node_modules/package-manager-detector/dist/shared/package-manager-detector.CqsrLAro.d.mts
|
|
289
|
+
type Agent = 'npm' | 'yarn' | 'yarn@berry' | 'pnpm' | 'pnpm@6' | 'bun' | 'deno' | 'nub' | 'aube';
|
|
290
|
+
type AgentName = 'npm' | 'yarn' | 'pnpm' | 'bun' | 'deno' | 'nub' | 'aube';
|
|
291
|
+
//#endregion
|
|
290
292
|
//#region src/plugins/gitlab/api.d.ts
|
|
291
293
|
interface GitLabToken {
|
|
292
294
|
value: string;
|
|
@@ -360,9 +362,11 @@ declare class CargoToml<Data extends CargoManifest = CargoManifest> {
|
|
|
360
362
|
data: Data;
|
|
361
363
|
private dependencies;
|
|
362
364
|
workspace?: CargoToml<RequireFields<CargoManifest, "workspace">>;
|
|
365
|
+
private readonly originalContent;
|
|
363
366
|
constructor(path: string, content: string, data: Data);
|
|
364
367
|
listDependencies(graph: CargoGraph): ResolvedDependency[];
|
|
365
368
|
patch(path: string, value: unknown): void;
|
|
369
|
+
write(): Promise<void>;
|
|
366
370
|
}
|
|
367
371
|
interface ResolvedDependency {
|
|
368
372
|
path: [...string[], kind: DepKind, key: string];
|
|
@@ -371,7 +375,7 @@ interface ResolvedDependency {
|
|
|
371
375
|
range?: string;
|
|
372
376
|
setRange?: (v: string) => void;
|
|
373
377
|
}
|
|
374
|
-
declare class CargoPackage extends WorkspacePackage {
|
|
378
|
+
declare class CargoPackage extends WorkspacePackage$1 {
|
|
375
379
|
readonly path: string;
|
|
376
380
|
/** a crate must have `package` field defined, otherwise it is merely a virutal workspace file, and Tegami should not include it. */
|
|
377
381
|
readonly file: CargoToml<RequireFields<CargoManifest, "package">>;
|
|
@@ -415,7 +419,7 @@ interface CargoGraph {
|
|
|
415
419
|
}
|
|
416
420
|
//#endregion
|
|
417
421
|
//#region src/providers/npm/graph.d.ts
|
|
418
|
-
declare class NpmPackage extends WorkspacePackage {
|
|
422
|
+
declare class NpmPackage extends WorkspacePackage$1 {
|
|
419
423
|
readonly path: string;
|
|
420
424
|
readonly manifest: PackageManifest;
|
|
421
425
|
readonly manager = "npm";
|
|
@@ -634,6 +638,7 @@ interface GenerateChangelogOptions extends GenerateFromCommitsOptions {
|
|
|
634
638
|
*/
|
|
635
639
|
write?: boolean;
|
|
636
640
|
}
|
|
641
|
+
declare const WorkspacePackage: typeof WorkspacePackage$1;
|
|
637
642
|
interface Tegami {
|
|
638
643
|
/** Create pending changelog files from git commit history. */
|
|
639
644
|
generateChangelog(options?: GenerateChangelogOptions): Promise<CommitChangelog[]>;
|
|
@@ -642,11 +647,22 @@ interface Tegami {
|
|
|
642
647
|
/** Publish packages from the publish lock. */
|
|
643
648
|
publish(options?: PublishOptions): Promise<PublishPlan | "skipped">;
|
|
644
649
|
/**
|
|
645
|
-
*
|
|
646
|
-
*
|
|
647
|
-
* Prefer `publish()` over this if you are publishing packages, it will also check the publish status.
|
|
650
|
+
* @deprecated use `getPublishStatus()` instead
|
|
648
651
|
*/
|
|
649
652
|
publishStatus(options?: PublishOptions): Promise<"pending" | "success" | "idle">;
|
|
653
|
+
/**
|
|
654
|
+
* Check publish plan status.
|
|
655
|
+
*
|
|
656
|
+
* Prefer `publish()` over this if you are publishing packages, this is check-only and can lead to TOCTOU race.
|
|
657
|
+
*/
|
|
658
|
+
getPublishStatus(options?: PublishOptions): Promise<{
|
|
659
|
+
/**
|
|
660
|
+
* - `pending`: has pending tasks.
|
|
661
|
+
* - `success`: all tasks finished.
|
|
662
|
+
* - `none`: there is no existing publish plans. */
|
|
663
|
+
status: "pending" | "success" | "none";
|
|
664
|
+
reason?: string;
|
|
665
|
+
}>;
|
|
650
666
|
/** Remove the publish lock file after publishing has finished successfully. */
|
|
651
667
|
cleanup(options?: PublishOptions): Promise<{
|
|
652
668
|
state: "removed";
|
|
@@ -747,7 +763,7 @@ declare function npm({
|
|
|
747
763
|
/** Generates changelog content for a package release. */
|
|
748
764
|
interface LogGenerator {
|
|
749
765
|
generate(this: TegamiContext, opts: {
|
|
750
|
-
pkg: WorkspacePackage;
|
|
766
|
+
pkg: WorkspacePackage$1;
|
|
751
767
|
packageDraft: PackageDraft;
|
|
752
768
|
draft: Draft;
|
|
753
769
|
}): string | Promise<string>;
|
|
@@ -762,7 +778,7 @@ interface TegamiOptions<Groups extends string = string> {
|
|
|
762
778
|
/** Changelog generator used when applying a draft. */
|
|
763
779
|
generator?: LogGenerator;
|
|
764
780
|
/** Per-package options keyed by package name or a function. */
|
|
765
|
-
packages?: Record<string, PackageOptions<NoInfer<Groups>>> | ((pkg: WorkspacePackage) => PackageOptions<NoInfer<Groups>> | undefined);
|
|
781
|
+
packages?: Record<string, PackageOptions<NoInfer<Groups>>> | ((pkg: WorkspacePackage$1) => PackageOptions<NoInfer<Groups>> | undefined);
|
|
766
782
|
plugins?: TegamiPluginOption[];
|
|
767
783
|
groups?: Record<Groups, GroupOptions>;
|
|
768
784
|
/** Package names, ids, or regex patterns to exclude from the dependency graph. */
|
|
@@ -841,7 +857,7 @@ interface TegamiPlugin {
|
|
|
841
857
|
* If multiple plugins return preflight data for the same package, only the first plugin will be considered.
|
|
842
858
|
*/
|
|
843
859
|
publishPreflight?(this: TegamiContext, opts: {
|
|
844
|
-
pkg: WorkspacePackage;
|
|
860
|
+
pkg: WorkspacePackage$1;
|
|
845
861
|
plan: PublishPlan;
|
|
846
862
|
}): Awaitable<PublishPreflight | void | undefined>;
|
|
847
863
|
/** Called when all preflights finished */
|
|
@@ -850,7 +866,7 @@ interface TegamiPlugin {
|
|
|
850
866
|
}): Awaitable<void>;
|
|
851
867
|
/** Publish package, return a result object indicating if the package is published, skipped, or failed. Return `undefined` if the package is not handled by this plugin. */
|
|
852
868
|
publish?(this: TegamiContext, opts: {
|
|
853
|
-
pkg: WorkspacePackage;
|
|
869
|
+
pkg: WorkspacePackage$1;
|
|
854
870
|
plan: PublishPlan;
|
|
855
871
|
}): Promise<PackagePublishResult | undefined | void>;
|
|
856
872
|
/**
|
|
@@ -867,11 +883,11 @@ interface TegamiPlugin {
|
|
|
867
883
|
}): Awaitable<void>;
|
|
868
884
|
/** Called before a package will be published, return `false` to prevent from publishing. */
|
|
869
885
|
willPublish?(this: TegamiContext, opts: {
|
|
870
|
-
pkg: WorkspacePackage;
|
|
886
|
+
pkg: WorkspacePackage$1;
|
|
871
887
|
}): Awaitable<false | void | undefined>;
|
|
872
888
|
/** Called after a package is published successfully, or failed. */
|
|
873
889
|
afterPublish?(this: TegamiContext, opts: {
|
|
874
|
-
pkg: WorkspacePackage;
|
|
890
|
+
pkg: WorkspacePackage$1;
|
|
875
891
|
plan: PublishPlan;
|
|
876
892
|
}): Awaitable<void>;
|
|
877
893
|
/** Called after all publishing finishes. */
|
|
@@ -906,4 +922,4 @@ interface PublishPreflight {
|
|
|
906
922
|
optionalWait?: string[];
|
|
907
923
|
}
|
|
908
924
|
//#endregion
|
|
909
|
-
export {
|
|
925
|
+
export { type PackageGroup as A, type NpmGraph as C, type CargoPluginOptions as D, CargoPackage as E, BumpType as F, Draft as M, DraftPolicy as N, cargo as O, PackageDraft as P, DependencySpec as S, CargoGraph as T, PackagePublishResult as _, type PublishPreflight as a, type CommitChangelog as b, type TegamiPluginOption as c, type GenerateChangelogOptions as d, Tegami as f, PackagePublishPlan as g, PublishLock as h, PackageOptions as i, WorkspacePackage$1 as j, PackageGraph as k, NpmPluginOptions as l, tegami as m, GroupOptions as n, TegamiOptions as o, WorkspacePackage as p, LogGenerator as r, TegamiPlugin as s, Awaitable as t, npm as u, PublishOptions as v, NpmPackage as w, TegamiContext as x, PublishPlan as y };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { M as Draft, h as PublishLock, t as Awaitable, x as TegamiContext, y as PublishPlan } from "./types-BMYzG4dR.js";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/version-request.d.ts
|
|
4
4
|
interface VersionRequestOptions {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as execFailure, s as isCI } from "./error-CAsrGb6e.js";
|
|
3
|
-
import { t as _accessExpressionAsString } from "./_accessExpressionAsString-
|
|
4
|
-
import { n as _validateReport, t as _createStandardSchema } from "./_createStandardSchema-
|
|
5
|
-
import {
|
|
1
|
+
import { a as formatPackageVersion, i as formatNpmDistTag, r as diffWeight } from "./semver-DrtaCCZK.js";
|
|
2
|
+
import { l as somePromise, n as execFailure, s as isCI } from "./error-CAsrGb6e.js";
|
|
3
|
+
import { t as _accessExpressionAsString } from "./_accessExpressionAsString-DW_6Xqcp.js";
|
|
4
|
+
import { n as _validateReport, t as _createStandardSchema } from "./_createStandardSchema-CrRqJgaE.js";
|
|
5
|
+
import { t as getPackageBumps } from "./shared-pTOZU5UZ.js";
|
|
6
|
+
import { o as PublishLock, r as runPreflights, s as parsePublishLock, t as initPublishPlan } from "./publish-DAMkayLs.js";
|
|
6
7
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
7
8
|
import { join, relative } from "node:path";
|
|
8
9
|
import { x } from "tinyexec";
|
|
@@ -65,8 +66,8 @@ const validatePublishGroupStore = (() => {
|
|
|
65
66
|
};
|
|
66
67
|
});
|
|
67
68
|
})();
|
|
68
|
-
function
|
|
69
|
-
const
|
|
69
|
+
function versionRequestPlugin(provider) {
|
|
70
|
+
const NamespacePublishGroup = `${provider.name}:publish-group`;
|
|
70
71
|
/** package id -> version before applying the CLI draft */
|
|
71
72
|
const snapshots = /* @__PURE__ */ new Map();
|
|
72
73
|
function resolveConfig(graph) {
|
|
@@ -93,6 +94,19 @@ function onVersionRequest(provider) {
|
|
|
93
94
|
...rest
|
|
94
95
|
};
|
|
95
96
|
}
|
|
97
|
+
/** commit the working tree changes onto a detached HEAD */
|
|
98
|
+
async function createVersionCommit(ctx, config) {
|
|
99
|
+
const { title = "Version Packages", body } = await config.commit?.call(ctx, { type: "version-packages" }) ?? {};
|
|
100
|
+
await run(ctx.cwd, ["checkout", "--detach"], "Failed to detach HEAD for version branches.");
|
|
101
|
+
await run(ctx.cwd, ["add", "-A"], "Failed to stage version changes.");
|
|
102
|
+
const args = [
|
|
103
|
+
"commit",
|
|
104
|
+
"-m",
|
|
105
|
+
title
|
|
106
|
+
];
|
|
107
|
+
if (body) args.push("-m", body);
|
|
108
|
+
await run(ctx.cwd, args, "Failed to commit version changes.");
|
|
109
|
+
}
|
|
96
110
|
/**
|
|
97
111
|
* Commit the group's lock state on top of `parent` and force-push its branch.
|
|
98
112
|
*
|
|
@@ -100,8 +114,8 @@ function onVersionRequest(provider) {
|
|
|
100
114
|
*/
|
|
101
115
|
async function syncGroupBranch(context, opts) {
|
|
102
116
|
const lock = new PublishLock(opts.baseLock);
|
|
103
|
-
while (lock.read(
|
|
104
|
-
lock.write(
|
|
117
|
+
while (lock.read(NamespacePublishGroup));
|
|
118
|
+
lock.write(NamespacePublishGroup, opts.store);
|
|
105
119
|
const commit = await createLockCommit(context, opts.parent, lock.serialize(), await opts.config.commit?.call(context, {
|
|
106
120
|
type: "update-lock",
|
|
107
121
|
store: opts.store,
|
|
@@ -117,15 +131,16 @@ function onVersionRequest(provider) {
|
|
|
117
131
|
return false;
|
|
118
132
|
}
|
|
119
133
|
return {
|
|
120
|
-
|
|
134
|
+
name: `${provider.name}:version-request`,
|
|
135
|
+
/** snapshot package versions */
|
|
121
136
|
initCliDraft() {
|
|
122
137
|
for (const pkg of this.graph.getPackages()) snapshots.set(pkg.id, pkg.version);
|
|
123
138
|
},
|
|
124
|
-
/** commit & push version branches, then upsert their requests
|
|
139
|
+
/** commit & push version branches, then upsert their requests */
|
|
125
140
|
async applyCliDraft(draft) {
|
|
141
|
+
if (!provider.canCreate(this)) return;
|
|
126
142
|
const config = resolveConfig(this.graph);
|
|
127
|
-
if (!config || !
|
|
128
|
-
if (!(config.forceCreate || isCI()) || !await hasGitChanges(this.cwd)) return;
|
|
143
|
+
if (!config || !(config.forceCreate || isCI()) || !await hasGitChanges(this.cwd)) return;
|
|
129
144
|
const requests = [];
|
|
130
145
|
const updatedPackages = /* @__PURE__ */ new Map();
|
|
131
146
|
for (const id of draft.getPackageDrafts().keys()) {
|
|
@@ -151,7 +166,7 @@ function onVersionRequest(provider) {
|
|
|
151
166
|
packages: Array.from(updatedPackages.values())
|
|
152
167
|
});
|
|
153
168
|
if (requests.length === 0) return;
|
|
154
|
-
await createVersionCommit(this
|
|
169
|
+
await createVersionCommit(this, config);
|
|
155
170
|
let baseLock;
|
|
156
171
|
let parent;
|
|
157
172
|
const tasks = [];
|
|
@@ -164,10 +179,15 @@ function onVersionRequest(provider) {
|
|
|
164
179
|
getPreviousVersion: (id) => snapshots.get(id)
|
|
165
180
|
};
|
|
166
181
|
const custom = await config.create?.call(this, ctx);
|
|
167
|
-
const
|
|
182
|
+
const resolved = {
|
|
183
|
+
title: custom?.title ?? (publishGroup ? `Release ${packages.map((pkg) => `${pkg.name} (${pkg.manager})`).join(", ")}` : "Version Packages"),
|
|
184
|
+
body: custom?.body ?? renderRequestBody(this, ctx),
|
|
185
|
+
head: branch,
|
|
186
|
+
base: config.base
|
|
187
|
+
};
|
|
168
188
|
if (publishGroup) {
|
|
169
189
|
parent ??= await resolveHead(this.cwd);
|
|
170
|
-
baseLock ??=
|
|
190
|
+
baseLock ??= parsePublishLock(await readFile(this.lockPath, "utf8"));
|
|
171
191
|
const newGroups = {};
|
|
172
192
|
for (const req of requests) {
|
|
173
193
|
if (!req.publishGroup) continue;
|
|
@@ -180,32 +200,33 @@ function onVersionRequest(provider) {
|
|
|
180
200
|
parent,
|
|
181
201
|
store: { groups: newGroups }
|
|
182
202
|
});
|
|
183
|
-
tasks.push(provider.upsert(this,
|
|
184
|
-
title,
|
|
185
|
-
body: custom?.body ?? renderRequestBody(this, ctx),
|
|
186
|
-
head: branch,
|
|
187
|
-
base: config.base
|
|
188
|
-
}, !inSync));
|
|
203
|
+
tasks.push(provider.upsert(this, resolved, !inSync));
|
|
189
204
|
continue;
|
|
190
205
|
}
|
|
191
|
-
await
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
206
|
+
await run(this.cwd, [
|
|
207
|
+
"checkout",
|
|
208
|
+
"-B",
|
|
209
|
+
branch
|
|
210
|
+
], "Failed to create the version branch.");
|
|
211
|
+
await run(this.cwd, [
|
|
212
|
+
"push",
|
|
213
|
+
"--force",
|
|
214
|
+
"-u",
|
|
215
|
+
"origin",
|
|
216
|
+
branch
|
|
217
|
+
], "Failed to push the version branch to origin. Ensure `origin` is configured and you have push access.");
|
|
218
|
+
await provider.upsert(this, resolved, true);
|
|
198
219
|
}
|
|
199
220
|
await Promise.all(tasks);
|
|
200
221
|
},
|
|
201
|
-
/** restore publish groups from the lock into the plan
|
|
222
|
+
/** restore publish groups from the lock into the plan */
|
|
202
223
|
initPublishPlan({ lock, plan }) {
|
|
203
224
|
const config = resolveConfig(this.graph);
|
|
204
225
|
if (!config) return;
|
|
205
226
|
let data;
|
|
206
227
|
const publishGroups = /* @__PURE__ */ new Map();
|
|
207
228
|
plan.$versionRequest = { publishGroups };
|
|
208
|
-
while (data = lock.read(
|
|
229
|
+
while (data = lock.read(NamespacePublishGroup)) {
|
|
209
230
|
const validated = validatePublishGroupStore(data);
|
|
210
231
|
if (!validated.success) continue;
|
|
211
232
|
const store = validated.data;
|
|
@@ -232,7 +253,7 @@ function onVersionRequest(provider) {
|
|
|
232
253
|
if (!publishGroups) return;
|
|
233
254
|
for (const s of publishGroups.values()) if (s === "pending") return "pending";
|
|
234
255
|
},
|
|
235
|
-
/** re-sync the version requests of pending publish groups
|
|
256
|
+
/** re-sync the version requests of pending publish groups */
|
|
236
257
|
async beforePublishAll({ plan }) {
|
|
237
258
|
if (plan.options.dryRun || !provider.canCreate(this)) return;
|
|
238
259
|
const config = resolveConfig(this.graph);
|
|
@@ -261,7 +282,7 @@ function onVersionRequest(provider) {
|
|
|
261
282
|
};
|
|
262
283
|
}
|
|
263
284
|
function renderRequestBody(ctx, { draft, getPreviousVersion, plan }) {
|
|
264
|
-
const
|
|
285
|
+
const bumpedPackages = [];
|
|
265
286
|
const changelogLines = [];
|
|
266
287
|
const publishLines = [];
|
|
267
288
|
const changesets = /* @__PURE__ */ new Map();
|
|
@@ -274,19 +295,31 @@ function renderRequestBody(ctx, { draft, getPreviousVersion, plan }) {
|
|
|
274
295
|
else changesets.set(changelog, [pkg]);
|
|
275
296
|
}
|
|
276
297
|
const from = getPreviousVersion(id);
|
|
277
|
-
if (!from || from === pkg.version) continue;
|
|
278
|
-
|
|
298
|
+
if (!from || !pkg.version || from === pkg.version) continue;
|
|
299
|
+
bumpedPackages.push({
|
|
300
|
+
name: pkg.name,
|
|
301
|
+
from,
|
|
302
|
+
to: pkg.version,
|
|
303
|
+
diff: diffWeight(from, pkg.version)
|
|
304
|
+
});
|
|
279
305
|
}
|
|
306
|
+
const packageLines = bumpedPackages.sort((a, b) => b.diff - a.diff).map(({ name, from, to }) => `| \`${name}\` | \`${from}\` | \`${to}\` |`);
|
|
280
307
|
for (const [entry, linkedPackages] of changesets) {
|
|
281
|
-
|
|
282
|
-
changelogLines.push("<details>", `<summary>Show Bumped Packages (${linkedPackages.length})</summary>`, "",
|
|
308
|
+
const bumps = getPackageBumps(ctx.graph, entry);
|
|
309
|
+
changelogLines.push(`### ${entry.subject ?? `\`${entry.filename}\``}`, "", "<details>", `<summary>Show Bumped Packages (${linkedPackages.length})</summary>`, "", "| Package | Bump |", "| --- | --- |");
|
|
310
|
+
for (const pkg of linkedPackages) changelogLines.push(`| \`${pkg.id}\` | ${bumps.get(pkg) ?? ""} |`);
|
|
311
|
+
changelogLines.push("", "</details>", "");
|
|
283
312
|
for (const section of entry.sections) {
|
|
284
313
|
changelogLines.push(`#### ${section.title}`, "");
|
|
285
314
|
if (section.content) changelogLines.push(section.content);
|
|
286
315
|
}
|
|
287
316
|
}
|
|
288
|
-
if (plan) {
|
|
289
|
-
|
|
317
|
+
if (plan) for (const [id, { preflight, npm }] of plan.packages) {
|
|
318
|
+
if (!preflight.shouldPublish) continue;
|
|
319
|
+
const pkg = ctx.graph.get(id);
|
|
320
|
+
let pm = "";
|
|
321
|
+
if (npm?.distTag) pm += ` (dist-tag: ${npm.distTag})`;
|
|
322
|
+
publishLines.push(`| \`${pkg.name}\` | \`${pkg.version}\`${pm} | \`${pkg.manager}\` |`);
|
|
290
323
|
}
|
|
291
324
|
const sections = [
|
|
292
325
|
"## Summary",
|
|
@@ -296,7 +329,7 @@ function renderRequestBody(ctx, { draft, getPreviousVersion, plan }) {
|
|
|
296
329
|
];
|
|
297
330
|
if (packageLines.length > 0) sections.push("| Package | From | To |", "| --- | --- | --- |", ...packageLines);
|
|
298
331
|
if (changelogLines.length > 0) sections.push("", "## Changelogs", ...changelogLines);
|
|
299
|
-
if (publishLines.length > 0) sections.push("", "## Publish", "", "The following packages will be published if merged:", ...publishLines);
|
|
332
|
+
if (publishLines.length > 0) sections.push("", "## Publish", "", "The following packages will be published if merged:", "", "| Package | Version | Registry |", "| --- | --- | --- |", ...publishLines);
|
|
300
333
|
sections.push("");
|
|
301
334
|
return sections.join("\n");
|
|
302
335
|
}
|
|
@@ -380,32 +413,6 @@ async function resolveRemoteBranches(cwd, branches) {
|
|
|
380
413
|
async function hasGitChanges(cwd) {
|
|
381
414
|
return (await run(cwd, ["status", "--porcelain"], "Failed to check git status.")).length > 0;
|
|
382
415
|
}
|
|
383
|
-
/** commit the working tree changes onto a detached HEAD */
|
|
384
|
-
async function createVersionCommit(cwd, { title = "Version Packages", body } = {}) {
|
|
385
|
-
await run(cwd, ["checkout", "--detach"], "Failed to detach HEAD for version branches.");
|
|
386
|
-
await run(cwd, ["add", "-A"], "Failed to stage version changes.");
|
|
387
|
-
const args = [
|
|
388
|
-
"commit",
|
|
389
|
-
"-m",
|
|
390
|
-
title
|
|
391
|
-
];
|
|
392
|
-
if (body) args.push("-m", body);
|
|
393
|
-
await run(cwd, args, "Failed to commit version changes.");
|
|
394
|
-
}
|
|
395
|
-
async function pushBranch(cwd, branch) {
|
|
396
|
-
await run(cwd, [
|
|
397
|
-
"checkout",
|
|
398
|
-
"-B",
|
|
399
|
-
branch
|
|
400
|
-
], "Failed to create the version branch.");
|
|
401
|
-
await run(cwd, [
|
|
402
|
-
"push",
|
|
403
|
-
"--force",
|
|
404
|
-
"-u",
|
|
405
|
-
"origin",
|
|
406
|
-
branch
|
|
407
|
-
], "Failed to push the version branch to origin. Ensure `origin` is configured and you have push access.");
|
|
408
|
-
}
|
|
409
416
|
async function run(cwd, args, message, env) {
|
|
410
417
|
const result = await x("git", args, { nodeOptions: {
|
|
411
418
|
cwd,
|
|
@@ -423,5 +430,134 @@ function publishGroupId(members) {
|
|
|
423
430
|
if (slugs.length === 0) slugs.push("group");
|
|
424
431
|
return slugs.join("-");
|
|
425
432
|
}
|
|
433
|
+
function formatPreview({ graph, npm }, draft, newChangelogNames, labels) {
|
|
434
|
+
const pendingPackages = [];
|
|
435
|
+
const lines = [
|
|
436
|
+
"### Tegami",
|
|
437
|
+
"",
|
|
438
|
+
`This repository uses [Tegami](https://tegami.fuma-nama.dev) to manage releases. When your changes affect published packages, add a changelog file under \`.tegami/\` before merging.`,
|
|
439
|
+
"",
|
|
440
|
+
`[**Create a changelog →**](${labels["create-a-changelog-href"]}) · [Changelog format](https://tegami.fuma-nama.dev/changelog)`,
|
|
441
|
+
""
|
|
442
|
+
];
|
|
443
|
+
for (const pkg of graph.getPackages()) {
|
|
444
|
+
const plan = draft.getPackageDraft(pkg.id);
|
|
445
|
+
if (!plan) continue;
|
|
446
|
+
const bumped = plan.bumpVersion(pkg);
|
|
447
|
+
if (!bumped || !pkg.version || bumped === pkg.version) continue;
|
|
448
|
+
pendingPackages.push({
|
|
449
|
+
name: pkg.name,
|
|
450
|
+
type: plan.type ?? "—",
|
|
451
|
+
from: pkg.version,
|
|
452
|
+
to: bumped,
|
|
453
|
+
distTag: plan.npm?.distTag
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
if (pendingPackages.length > 0) {
|
|
457
|
+
lines.push("#### Release preview", "", "| Package | Bump | Version |", "| --- | --- | --- |");
|
|
458
|
+
for (const { name, type, from, to, distTag } of pendingPackages.sort((a, b) => diffWeight(b.from, b.to) - diffWeight(a.from, a.to))) lines.push(`| \`${name}\` | ${type} | \`${from}\` → \`${to}\`${formatNpmDistTag(distTag)} |`);
|
|
459
|
+
lines.push("");
|
|
460
|
+
}
|
|
461
|
+
const newChangelogs = draft.getChangelogs().filter((entry) => newChangelogNames.has(entry.filename));
|
|
462
|
+
if (newChangelogs.length > 0) {
|
|
463
|
+
lines.push(`#### Changelogs in this ${labels.pr}`, "", "| Changelog | Title |", "| --- | --- |");
|
|
464
|
+
for (const entry of newChangelogs) for (const section of entry.sections) lines.push(`| \`${entry.filename}\` | ${section.title} |`);
|
|
465
|
+
lines.push("");
|
|
466
|
+
} else if (pendingPackages.length === 0) lines.push("#### No changelogs yet", "", `This ${labels.pr} has no pending changelog files. If your changes require a release, add a changelog before merging.`, "");
|
|
467
|
+
else if (newChangelogNames.size === 0) lines.push(`This ${labels.pr} does not add changelog files. Pending changelogs from other branches are included in the preview above.`, "");
|
|
468
|
+
lines.push(`Run \`${npm?.client ?? "npm"} run tegami\` locally to create a changelog interactively.`, "", `<sub>Managed by [Tegami](https://tegami.fuma-nama.dev).</sub>`, "");
|
|
469
|
+
return lines.join("\n");
|
|
470
|
+
}
|
|
471
|
+
async function resolveFileCommit(ctx, filename) {
|
|
472
|
+
const result = await x("git", [
|
|
473
|
+
"log",
|
|
474
|
+
"--diff-filter=A",
|
|
475
|
+
"-1",
|
|
476
|
+
"--format=%H",
|
|
477
|
+
"--",
|
|
478
|
+
relative(ctx.cwd, join(ctx.changelogDir, filename))
|
|
479
|
+
], { nodeOptions: { cwd: ctx.cwd } });
|
|
480
|
+
if (result.exitCode !== 0) return;
|
|
481
|
+
return result.stdout.trim() || void 0;
|
|
482
|
+
}
|
|
483
|
+
function createAutoRelease({ eager, create, override, overrideGroup, releaseExistsByTag, formatChangelog }) {
|
|
484
|
+
async function defaultNotes(ctx, pkg, packagePlan) {
|
|
485
|
+
if (packagePlan && packagePlan.changelogs.length > 0) return (await Promise.all(packagePlan.changelogs.map(formatChangelog.bind(ctx)))).join("\n\n");
|
|
486
|
+
return `Published ${formatPackageVersion(pkg.name, pkg.version, packagePlan?.npm?.distTag)}.`;
|
|
487
|
+
}
|
|
488
|
+
async function defaultGroupedNotes(ctx, plan, packages) {
|
|
489
|
+
const changelogs = /* @__PURE__ */ new Map();
|
|
490
|
+
for (const pkg of packages) {
|
|
491
|
+
const packagePlan = plan.packages.get(pkg.id);
|
|
492
|
+
if (!packagePlan) continue;
|
|
493
|
+
for (const entry of packagePlan.changelogs) changelogs.set(entry.id, entry);
|
|
494
|
+
}
|
|
495
|
+
const sections = [packages.map((pkg) => {
|
|
496
|
+
const packagePlan = plan.packages.get(pkg.id);
|
|
497
|
+
return `- ${formatPackageVersion(pkg.name, pkg.version, packagePlan?.npm?.distTag)}`;
|
|
498
|
+
}).join("\n")];
|
|
499
|
+
if (changelogs.size > 0) {
|
|
500
|
+
const notes = await Promise.all(Array.from(changelogs.values(), formatChangelog.bind(ctx)));
|
|
501
|
+
sections.push("", notes.join("\n\n"));
|
|
502
|
+
}
|
|
503
|
+
return sections.join("\n");
|
|
504
|
+
}
|
|
505
|
+
return {
|
|
506
|
+
async hasPending(plan) {
|
|
507
|
+
const requiredTags = /* @__PURE__ */ new Set();
|
|
508
|
+
for (const pkg of plan.packages.values()) if (pkg.preflight.shouldPublish && pkg.git?.tag) requiredTags.add(pkg.git.tag);
|
|
509
|
+
return somePromise(Array.from(requiredTags, (tag) => releaseExistsByTag.call(this, tag)), (exists) => !exists);
|
|
510
|
+
},
|
|
511
|
+
async create(plan) {
|
|
512
|
+
const groups = /* @__PURE__ */ new Map();
|
|
513
|
+
for (const [id, { preflight, publishResult, git }] of plan.packages) {
|
|
514
|
+
if (!eager && publishResult.type === "failed") return;
|
|
515
|
+
const tag = git?.tag;
|
|
516
|
+
if (!tag || !preflight.shouldPublish) continue;
|
|
517
|
+
const pkg = this.graph.get(id);
|
|
518
|
+
const group = groups.get(tag);
|
|
519
|
+
if (group) group.push(pkg);
|
|
520
|
+
else groups.set(tag, [pkg]);
|
|
521
|
+
}
|
|
522
|
+
await Promise.all(Array.from(groups, async ([tag, packages]) => {
|
|
523
|
+
for (const member of packages) if (plan.packages.get(member.id).publishResult.type === "failed") return;
|
|
524
|
+
if (await releaseExistsByTag.call(this, tag)) return;
|
|
525
|
+
if (packages.length > 1) {
|
|
526
|
+
const { title = tag, notes = await defaultGroupedNotes(this, plan, packages), ...rest } = await overrideGroup?.call(this, {
|
|
527
|
+
tag,
|
|
528
|
+
packages,
|
|
529
|
+
plan
|
|
530
|
+
}) ?? {};
|
|
531
|
+
await create({
|
|
532
|
+
input: {
|
|
533
|
+
title,
|
|
534
|
+
notes,
|
|
535
|
+
...rest
|
|
536
|
+
},
|
|
537
|
+
tag,
|
|
538
|
+
packages
|
|
539
|
+
});
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
const pkg = packages[0];
|
|
543
|
+
const packagePlan = plan.packages.get(pkg.id);
|
|
544
|
+
const { title = formatPackageVersion(pkg.name, pkg.version, packagePlan?.npm?.distTag), notes = await defaultNotes(this, pkg, packagePlan), ...rest } = await override?.call(this, {
|
|
545
|
+
tag,
|
|
546
|
+
pkg,
|
|
547
|
+
plan
|
|
548
|
+
}) ?? {};
|
|
549
|
+
await create({
|
|
550
|
+
input: {
|
|
551
|
+
title,
|
|
552
|
+
notes,
|
|
553
|
+
...rest
|
|
554
|
+
},
|
|
555
|
+
tag,
|
|
556
|
+
packages
|
|
557
|
+
});
|
|
558
|
+
}));
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
}
|
|
426
562
|
//#endregion
|
|
427
|
-
export {
|
|
563
|
+
export { versionRequestPlugin as i, formatPreview as n, resolveFileCommit as r, createAutoRelease as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tegami",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "A tool to manage changelogs, versioning, and publishing in monorepo",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Fuma Nama",
|
|
@@ -29,17 +29,17 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@clack/prompts": "^1.
|
|
32
|
+
"@clack/prompts": "^1.7.0",
|
|
33
33
|
"@rainbowatcher/toml-edit-js": "^0.6.5",
|
|
34
|
-
"package-manager-detector": "^1.6.0",
|
|
35
34
|
"semver": "^7.8.5",
|
|
36
35
|
"tinyexec": "^1.2.4",
|
|
37
36
|
"tinyglobby": "^0.2.17",
|
|
38
37
|
"yaml": "^2.9.0"
|
|
39
38
|
},
|
|
40
39
|
"devDependencies": {
|
|
41
|
-
"@types/node": "^26.0
|
|
40
|
+
"@types/node": "^26.1.0",
|
|
42
41
|
"@types/semver": "^7.7.1",
|
|
42
|
+
"package-manager-detector": "^1.7.0",
|
|
43
43
|
"tsdown": "^0.22.3",
|
|
44
44
|
"typescript": "6.0.3",
|
|
45
45
|
"typia": "^12.1.1",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"inlinedDependencies": {
|
|
49
49
|
"@typia/interface": "12.1.1",
|
|
50
|
+
"package-manager-detector": "1.7.0",
|
|
50
51
|
"typia": "12.1.1"
|
|
51
52
|
},
|
|
52
53
|
"scripts": {
|