tegami 0.1.0 → 0.1.3
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/checks-Smwtq_Li.js +279 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +212 -209
- package/dist/{error-DBK-9uBa.js → error-qpTCB2ld.js} +10 -6
- package/dist/generators/simple.d.ts +1 -1
- package/dist/generators/simple.js +1 -1
- package/dist/{graph-CUgwuRW5.js → graph-hBQUWKQA.js} +15 -11
- package/dist/index.d.ts +2 -2
- package/dist/index.js +272 -294
- package/dist/plugins/git.d.ts +1 -1
- package/dist/plugins/git.js +4 -4
- package/dist/plugins/github.d.ts +7 -1
- package/dist/plugins/github.js +24 -23
- package/dist/providers/cargo.d.ts +1 -1
- package/dist/providers/cargo.js +32 -14
- package/dist/providers/npm.d.ts +1 -1
- package/dist/providers/npm.js +33 -18
- package/dist/{semver-mWK2Khi2.js → semver-cnZp9koa.js} +16 -5
- package/dist/{types-UjsZkz42.d.ts → types-Di--A9X1.d.ts} +68 -23
- package/package.json +1 -1
- package/dist/checks-BQISvt_o.js +0 -98
package/dist/cli/index.js
CHANGED
|
@@ -1,15 +1,206 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { n as
|
|
1
|
+
import { r as formatNpmDistTag } from "../semver-cnZp9koa.js";
|
|
2
|
+
import { c as renderChangelog, l as changelogFilename, o as generateReplays, t as assertPublishPlanFinished } from "../checks-Smwtq_Li.js";
|
|
3
|
+
import { n as execFailure, r as handlePluginError, t as CancelledError } from "../error-qpTCB2ld.js";
|
|
4
4
|
import { t as isCI } from "../constants-B9qjNfvr.js";
|
|
5
5
|
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
6
|
-
import path, { basename, isAbsolute, join, normalize, relative
|
|
6
|
+
import path, { basename, isAbsolute, join, normalize, relative } from "node:path";
|
|
7
7
|
import { x } from "tinyexec";
|
|
8
|
-
import { dump } from "js-yaml";
|
|
9
8
|
import { detect, resolveCommand } from "package-manager-detector";
|
|
10
9
|
import { autocompleteMultiselect, confirm, intro, isCancel, multiline, note, outro, select, spinner } from "@clack/prompts";
|
|
11
10
|
import { Command, InvalidArgumentError } from "commander";
|
|
12
11
|
import { tmpdir } from "node:os";
|
|
12
|
+
//#region src/utils/git-changes.ts
|
|
13
|
+
async function getChangedPackages(graph, cwd) {
|
|
14
|
+
return resolveChangedPackages(graph, await getChangedFilePaths(cwd), cwd);
|
|
15
|
+
}
|
|
16
|
+
async function getChangedFilePaths(cwd) {
|
|
17
|
+
const files = /* @__PURE__ */ new Set();
|
|
18
|
+
for (const args of [["diff", "--name-only"], [
|
|
19
|
+
"diff",
|
|
20
|
+
"--cached",
|
|
21
|
+
"--name-only"
|
|
22
|
+
]]) await addGitOutput(files, cwd, args);
|
|
23
|
+
return Array.from(files);
|
|
24
|
+
}
|
|
25
|
+
function resolveChangedPackages(graph, files, cwd) {
|
|
26
|
+
const packages = [...graph.getPackages()].sort((a, b) => b.path.length - a.path.length);
|
|
27
|
+
const matched = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const file of files) for (const pkg of packages) if (isUnderDir(file, pkg.path, cwd)) {
|
|
29
|
+
matched.set(pkg.id, pkg);
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
return [...matched.values()];
|
|
33
|
+
}
|
|
34
|
+
function isUnderDir(file, dir, cwd) {
|
|
35
|
+
const absolute = join(cwd, file);
|
|
36
|
+
const rel = relative(normalize(dir), absolute);
|
|
37
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
38
|
+
}
|
|
39
|
+
async function addGitOutput(files, cwd, args) {
|
|
40
|
+
const result = await x("git", args, { nodeOptions: { cwd } });
|
|
41
|
+
if (result.exitCode !== 0) return;
|
|
42
|
+
for (const line of result.stdout.split("\n")) {
|
|
43
|
+
const trimmed = line.trim();
|
|
44
|
+
if (trimmed) files.add(trimmed);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/cli/changelog.ts
|
|
49
|
+
async function runChangelogTui(tegami) {
|
|
50
|
+
const context = await tegami._internal.context();
|
|
51
|
+
await assertPublishPlanFinished(context);
|
|
52
|
+
intro("Create changelogs");
|
|
53
|
+
let selectedPackages = [];
|
|
54
|
+
if (!isCI()) selectedPackages = await promptPackageSelection(context.graph, context.cwd);
|
|
55
|
+
if (selectedPackages.length === 0) {
|
|
56
|
+
if (!isCI()) {
|
|
57
|
+
const confirmed = await confirm({
|
|
58
|
+
message: "Auto-generate changelog files from commits?",
|
|
59
|
+
initialValue: true
|
|
60
|
+
});
|
|
61
|
+
if (isCancel(confirmed)) throw new CancelledError();
|
|
62
|
+
if (!confirmed) {
|
|
63
|
+
outro("No changelogs created.");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
await persistChangelogs(context, (await tegami.generateChangelog({ write: false })).map(({ filename, content, packages }) => ({
|
|
68
|
+
filename,
|
|
69
|
+
content,
|
|
70
|
+
packages
|
|
71
|
+
})), "No matching conventional commits were found.");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const packageBumpMap = await promptPackageBumpTypes(selectedPackages);
|
|
75
|
+
const message = await multiline({
|
|
76
|
+
message: "Describe change (Markdown supported, press tab then enter to exit)",
|
|
77
|
+
placeholder: "The first line is heading\n\nAdditional description.",
|
|
78
|
+
showSubmit: true,
|
|
79
|
+
validate(value) {
|
|
80
|
+
if (!value?.trim()) return "Enter a message.";
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
if (isCancel(message)) throw new CancelledError();
|
|
84
|
+
const packages = generateReplays(context.graph, packageBumpMap);
|
|
85
|
+
await persistChangelogs(context, [{
|
|
86
|
+
filename: changelogFilename(),
|
|
87
|
+
content: renderChangelog({ packages }, `## ${message.trim()}`),
|
|
88
|
+
packages
|
|
89
|
+
}]);
|
|
90
|
+
}
|
|
91
|
+
async function persistChangelogs(context, entries, emptyMessage = "No changelogs created.") {
|
|
92
|
+
const s = spinner();
|
|
93
|
+
s.start("Creating changelog");
|
|
94
|
+
await mkdir(context.changelogDir, { recursive: true });
|
|
95
|
+
await Promise.all(entries.map(({ filename, content }) => writeFile(join(context.changelogDir, filename), content)));
|
|
96
|
+
s.stop(entries.length === 1 ? "Created 1 changelog file" : entries.length > 0 ? `Created ${entries.length} changelog files` : "No changelogs created");
|
|
97
|
+
if (entries.length === 0) note(emptyMessage, "No changelogs created");
|
|
98
|
+
else {
|
|
99
|
+
const lines = [];
|
|
100
|
+
for (const { filename, packages } of entries) {
|
|
101
|
+
lines.push(filename);
|
|
102
|
+
for (const [name, config] of Object.entries(packages)) {
|
|
103
|
+
if (typeof config === "string") {
|
|
104
|
+
lines.push(`${name}: ${config}`);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (config.replay?.length) {
|
|
108
|
+
lines.push(`${name}: ${config.type} (replay on ${config.replay.join(" or ")})`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
lines.push(`${name}: ${config.type}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
note(lines.join("\n"), "Created changelogs");
|
|
115
|
+
}
|
|
116
|
+
outro(entries.length === 1 ? "Changelog ready." : "Changelogs ready.");
|
|
117
|
+
}
|
|
118
|
+
async function promptPackageSelection(graph, cwd) {
|
|
119
|
+
const useShortname = /* @__PURE__ */ new Map();
|
|
120
|
+
for (const pkg of graph.getPackages()) if (useShortname.has(pkg.name)) useShortname.set(pkg.name, false);
|
|
121
|
+
else useShortname.set(pkg.name, true);
|
|
122
|
+
const getPackageLabel = (pkg) => {
|
|
123
|
+
return useShortname.get(pkg.name) ? pkg.name : pkg.id;
|
|
124
|
+
};
|
|
125
|
+
const changedPackages = new Set(await getChangedPackages(graph, cwd));
|
|
126
|
+
const selectOptions = [];
|
|
127
|
+
const groups = [];
|
|
128
|
+
for (const group of graph.getGroups()) {
|
|
129
|
+
const changed = group.packages.some((pkg) => changedPackages.has(pkg));
|
|
130
|
+
groups.push([group, changed]);
|
|
131
|
+
}
|
|
132
|
+
groups.sort((a, b) => (a[1] ? 0 : 1) - (b[1] ? 0 : 1));
|
|
133
|
+
for (const [group, changed] of groups) {
|
|
134
|
+
const members = group.packages.map(getPackageLabel).join(", ");
|
|
135
|
+
selectOptions.push({
|
|
136
|
+
label: `(Group) ${group.name}`,
|
|
137
|
+
value: `group:${group.name}`,
|
|
138
|
+
hint: changed ? `changed · ${members}` : members
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
const packages = graph.getPackages().toSorted((a, b) => (changedPackages.has(a) ? 0 : 1) - (changedPackages.has(b) ? 0 : 1));
|
|
142
|
+
for (const pkg of packages) selectOptions.push({
|
|
143
|
+
label: getPackageLabel(pkg),
|
|
144
|
+
value: pkg.id,
|
|
145
|
+
hint: changedPackages.has(pkg) ? "changed" : void 0
|
|
146
|
+
});
|
|
147
|
+
const selected = await autocompleteMultiselect({
|
|
148
|
+
message: "Select packages (leave empty to auto-generate from commits)",
|
|
149
|
+
required: false,
|
|
150
|
+
options: selectOptions
|
|
151
|
+
});
|
|
152
|
+
if (isCancel(selected)) throw new CancelledError();
|
|
153
|
+
return selected;
|
|
154
|
+
}
|
|
155
|
+
async function promptPackageBumpTypes(selectedPackages) {
|
|
156
|
+
const packageBumpMap = {};
|
|
157
|
+
const bumpType = await select({
|
|
158
|
+
message: "Select release type",
|
|
159
|
+
options: [
|
|
160
|
+
{
|
|
161
|
+
value: "patch",
|
|
162
|
+
label: "patch"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
value: "minor",
|
|
166
|
+
label: "minor"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
value: "major",
|
|
170
|
+
label: "major"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
value: "per-package",
|
|
174
|
+
label: "choose per-package"
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
});
|
|
178
|
+
if (isCancel(bumpType)) throw new CancelledError();
|
|
179
|
+
if (bumpType === "per-package") for (const pkg of selectedPackages) {
|
|
180
|
+
const selectedBump = await select({
|
|
181
|
+
message: `Select release type for "${pkg}"`,
|
|
182
|
+
options: [
|
|
183
|
+
{
|
|
184
|
+
value: "patch",
|
|
185
|
+
label: "patch"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
value: "minor",
|
|
189
|
+
label: "minor"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
value: "major",
|
|
193
|
+
label: "major"
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
});
|
|
197
|
+
if (isCancel(selectedBump)) throw new CancelledError();
|
|
198
|
+
packageBumpMap[pkg] = selectedBump;
|
|
199
|
+
}
|
|
200
|
+
else for (const pkg of selectedPackages) packageBumpMap[pkg] = bumpType;
|
|
201
|
+
return packageBumpMap;
|
|
202
|
+
}
|
|
203
|
+
//#endregion
|
|
13
204
|
//#region src/cli/init-agent.ts
|
|
14
205
|
const CHANGELOG_DOCS_URL$1 = "https://tegami.fuma-nama.dev/changelog";
|
|
15
206
|
async function initAgent(context, options = {}) {
|
|
@@ -101,10 +292,10 @@ async function buildPrPreview(context, draft, options = {}) {
|
|
|
101
292
|
const pendingPackages = [];
|
|
102
293
|
for (const pkg of context.graph.getPackages()) {
|
|
103
294
|
const plan = draft.getPackagePlan(pkg.id);
|
|
104
|
-
if (!plan
|
|
295
|
+
if (!plan || plan.bumpVersion(pkg) === pkg.version) continue;
|
|
105
296
|
pendingPackages.push({
|
|
106
297
|
name: pkg.name,
|
|
107
|
-
type: plan.type,
|
|
298
|
+
type: plan.type ?? "—",
|
|
108
299
|
from: pkg.version,
|
|
109
300
|
to: plan.bumpVersion(pkg),
|
|
110
301
|
distTag: plan.npm?.distTag,
|
|
@@ -144,7 +335,7 @@ async function postPrComment(body) {
|
|
|
144
335
|
"--jq",
|
|
145
336
|
`[.[] | select(.body | startswith("${COMMENT_MARKER}")) | .id][0] // empty`
|
|
146
337
|
]);
|
|
147
|
-
if (listResult.exitCode !== 0) throw
|
|
338
|
+
if (listResult.exitCode !== 0) throw execFailure("Failed to list pull request comments.", listResult);
|
|
148
339
|
const existingId = listResult.stdout.trim();
|
|
149
340
|
if (existingId) {
|
|
150
341
|
const dir = await mkdtemp(join(tmpdir(), "tegami-pr-comment-"));
|
|
@@ -159,7 +350,7 @@ async function postPrComment(body) {
|
|
|
159
350
|
"--input",
|
|
160
351
|
inputPath
|
|
161
352
|
]);
|
|
162
|
-
if (updateResult.exitCode !== 0) throw
|
|
353
|
+
if (updateResult.exitCode !== 0) throw execFailure("Failed to update pull request comment.", updateResult);
|
|
163
354
|
} finally {
|
|
164
355
|
await rm(dir, {
|
|
165
356
|
recursive: true,
|
|
@@ -177,7 +368,7 @@ async function postPrComment(body) {
|
|
|
177
368
|
"--repo",
|
|
178
369
|
repo
|
|
179
370
|
]);
|
|
180
|
-
if (createResult.exitCode !== 0) throw
|
|
371
|
+
if (createResult.exitCode !== 0) throw execFailure("Failed to create pull request comment.", createResult);
|
|
181
372
|
}
|
|
182
373
|
async function readPullRequestNumberFromWorkflowRunEvent() {
|
|
183
374
|
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
@@ -220,7 +411,7 @@ async function readPullRequestFromGh(repo, number) {
|
|
|
220
411
|
"--json",
|
|
221
412
|
"headRefName,baseRefOid,headRefOid,headRepository"
|
|
222
413
|
]);
|
|
223
|
-
if (result.exitCode !== 0) throw
|
|
414
|
+
if (result.exitCode !== 0) throw execFailure(`Failed to resolve pull request #${number}.`, result);
|
|
224
415
|
const data = JSON.parse(result.stdout);
|
|
225
416
|
return {
|
|
226
417
|
repo,
|
|
@@ -258,10 +449,7 @@ async function listPullRequestChangelogFiles(context, baseSha, headSha) {
|
|
|
258
449
|
"--",
|
|
259
450
|
`${dir}/`
|
|
260
451
|
], { nodeOptions: { cwd: context.cwd } });
|
|
261
|
-
if (result.exitCode !== 0)
|
|
262
|
-
const detail = result.stderr.trim();
|
|
263
|
-
throw new Error(detail ? `Failed to list pull request changelog files: ${detail}` : "Failed to list pull request changelog files.");
|
|
264
|
-
}
|
|
452
|
+
if (result.exitCode !== 0) throw execFailure("Failed to list pull request changelog files.", result);
|
|
265
453
|
const files = /* @__PURE__ */ new Set();
|
|
266
454
|
for (const line of result.stdout.split("\n")) {
|
|
267
455
|
const trimmed = line.trim();
|
|
@@ -274,59 +462,12 @@ function createChangelogUrl(context, repo, branch, filename) {
|
|
|
274
462
|
return `https://github.com/${repo}/new/${branch.split("/").map(encodeURIComponent).join("/")}?${new URLSearchParams({ filename: filePath })}`;
|
|
275
463
|
}
|
|
276
464
|
//#endregion
|
|
277
|
-
//#region src/utils/git-changes.ts
|
|
278
|
-
async function getChangedPackages(graph, cwd) {
|
|
279
|
-
return resolveChangedPackages(graph, await getChangedFilePaths(cwd), cwd);
|
|
280
|
-
}
|
|
281
|
-
async function getChangedFilePaths(cwd) {
|
|
282
|
-
const files = /* @__PURE__ */ new Set();
|
|
283
|
-
for (const args of [["diff", "--name-only"], [
|
|
284
|
-
"diff",
|
|
285
|
-
"--cached",
|
|
286
|
-
"--name-only"
|
|
287
|
-
]]) await addGitOutput(files, cwd, args);
|
|
288
|
-
return Array.from(files);
|
|
289
|
-
}
|
|
290
|
-
function resolveChangedPackages(graph, files, cwd) {
|
|
291
|
-
const packages = [...graph.getPackages()].sort((a, b) => b.path.length - a.path.length);
|
|
292
|
-
const matched = /* @__PURE__ */ new Map();
|
|
293
|
-
for (const file of files) for (const pkg of packages) if (isUnderDir(file, pkg.path, cwd)) {
|
|
294
|
-
matched.set(pkg.id, pkg);
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
return [...matched.values()];
|
|
298
|
-
}
|
|
299
|
-
function isUnderDir(file, dir, cwd) {
|
|
300
|
-
const absolute = join(cwd, file);
|
|
301
|
-
const rel = relative(normalize(dir), absolute);
|
|
302
|
-
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
303
|
-
}
|
|
304
|
-
async function addGitOutput(files, cwd, args) {
|
|
305
|
-
const result = await x("git", args, { nodeOptions: { cwd } });
|
|
306
|
-
if (result.exitCode !== 0) return;
|
|
307
|
-
for (const line of result.stdout.split("\n")) {
|
|
308
|
-
const trimmed = line.trim();
|
|
309
|
-
if (trimmed) files.add(trimmed);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
//#endregion
|
|
313
465
|
//#region src/cli/index.ts
|
|
314
|
-
var CancelledError = class extends Error {
|
|
315
|
-
constructor() {
|
|
316
|
-
super("Cancelled.");
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
466
|
function createCli(tegami, options = {}) {
|
|
320
467
|
const program = new Command();
|
|
321
|
-
program.name("tegami").description("create changelogs").action((
|
|
322
|
-
|
|
323
|
-
cli: options
|
|
324
|
-
})));
|
|
325
|
-
program.command("version").description("draft and apply a publish plan").action((commandOptions) => runAction(tegami, async () => {
|
|
326
|
-
await versionPackages(tegami, {
|
|
327
|
-
...commandOptions,
|
|
328
|
-
cli: options
|
|
329
|
-
});
|
|
468
|
+
program.name("tegami").description("create changelogs").action(() => runAction(tegami, () => runChangelogTui(tegami)));
|
|
469
|
+
program.command("version").description("draft and apply a publish plan").action(() => runAction(tegami, async () => {
|
|
470
|
+
await versionPackages(tegami, { cli: options });
|
|
330
471
|
}));
|
|
331
472
|
program.command("ci").description("version and publish packages").action(() => runAction(tegami, async () => {
|
|
332
473
|
if (await versionPackages(tegami, { cli: options })) return;
|
|
@@ -341,10 +482,10 @@ function createCli(tegami, options = {}) {
|
|
|
341
482
|
const context = await tegami._internal.context();
|
|
342
483
|
const body = await buildPrPreview(context, await tegami.draft(), commandOptions);
|
|
343
484
|
if (commandOptions.artifact) {
|
|
344
|
-
const artifactPath = resolve(context.cwd, commandOptions.artifact);
|
|
485
|
+
const artifactPath = path.resolve(context.cwd, commandOptions.artifact);
|
|
345
486
|
await writeFile(artifactPath, body);
|
|
346
487
|
if (!isCI()) {
|
|
347
|
-
note(relative(context.cwd, artifactPath) || commandOptions.artifact, "Release preview");
|
|
488
|
+
note(path.relative(context.cwd, artifactPath) || commandOptions.artifact, "Release preview");
|
|
348
489
|
outro("Release preview ready.");
|
|
349
490
|
}
|
|
350
491
|
return;
|
|
@@ -376,134 +517,6 @@ function createCli(tegami, options = {}) {
|
|
|
376
517
|
program.command("init-agent").description("write AGENTS.md with changelog instructions for AI agents").option("-o, --output <path>", "output path", "AGENTS.md").action((commandOptions) => runAction(tegami, () => runInitAgent(tegami, commandOptions)));
|
|
377
518
|
return program;
|
|
378
519
|
}
|
|
379
|
-
async function createChangelogs(tegami, _options) {
|
|
380
|
-
const context = await tegami._internal.context();
|
|
381
|
-
await assertPublishPlanFinished(context);
|
|
382
|
-
intro("Create changelogs");
|
|
383
|
-
let selectedPackages = [];
|
|
384
|
-
if (!isCI()) {
|
|
385
|
-
const useShortname = /* @__PURE__ */ new Map();
|
|
386
|
-
for (const pkg of context.graph.getPackages()) if (useShortname.has(pkg.name)) useShortname.set(pkg.name, false);
|
|
387
|
-
else useShortname.set(pkg.name, true);
|
|
388
|
-
const getPackageLabel = (pkg) => {
|
|
389
|
-
return useShortname.get(pkg.name) ? pkg.name : pkg.id;
|
|
390
|
-
};
|
|
391
|
-
const changedPackages = new Set(await getChangedPackages(context.graph, context.cwd));
|
|
392
|
-
const selectOptions = [];
|
|
393
|
-
const groups = [];
|
|
394
|
-
for (const group of context.graph.getGroups()) {
|
|
395
|
-
const changed = group.packages.some((pkg) => changedPackages.has(pkg));
|
|
396
|
-
groups.push([group, changed]);
|
|
397
|
-
}
|
|
398
|
-
groups.sort((a, b) => (a[1] ? 0 : 1) - (b[1] ? 0 : 1));
|
|
399
|
-
for (const [group, changed] of groups) {
|
|
400
|
-
const members = group.packages.map(getPackageLabel).join(", ");
|
|
401
|
-
selectOptions.push({
|
|
402
|
-
label: `(Group) ${group.name}`,
|
|
403
|
-
value: `group:${group.name}`,
|
|
404
|
-
hint: changed ? `changed · ${members}` : members
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
const packages = context.graph.getPackages().toSorted((a, b) => (changedPackages.has(a) ? 0 : 1) - (changedPackages.has(b) ? 0 : 1));
|
|
408
|
-
for (const pkg of packages) selectOptions.push({
|
|
409
|
-
label: getPackageLabel(pkg),
|
|
410
|
-
value: pkg.id,
|
|
411
|
-
hint: changedPackages.has(pkg) ? "changed" : void 0
|
|
412
|
-
});
|
|
413
|
-
const selected = await autocompleteMultiselect({
|
|
414
|
-
message: "Select packages (leave empty to auto-generate from commits)",
|
|
415
|
-
required: false,
|
|
416
|
-
options: selectOptions
|
|
417
|
-
});
|
|
418
|
-
if (isCancel(selected)) throw new CancelledError();
|
|
419
|
-
selectedPackages = selected;
|
|
420
|
-
}
|
|
421
|
-
if (selectedPackages.length === 0) {
|
|
422
|
-
if (!isCI()) {
|
|
423
|
-
const confirmed = await confirm({
|
|
424
|
-
message: "Auto-generate changelog files from commits?",
|
|
425
|
-
initialValue: true
|
|
426
|
-
});
|
|
427
|
-
if (isCancel(confirmed)) throw new CancelledError();
|
|
428
|
-
if (!confirmed) {
|
|
429
|
-
outro("No changelogs created.");
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
const s = spinner();
|
|
434
|
-
s.start("Reading commits and creating changelogs");
|
|
435
|
-
const created = await tegami.generateChangelog();
|
|
436
|
-
s.stop(created.length === 1 ? "Created 1 changelog file" : `Created ${created.length} changelog files`);
|
|
437
|
-
if (created.length === 0) note("No matching conventional commits were found.", "No changelogs created");
|
|
438
|
-
else note(created.map((entry) => `${entry.filename} (${entry.changes} changes)`).join("\n"), "Created changelogs");
|
|
439
|
-
outro("Changelogs ready.");
|
|
440
|
-
return;
|
|
441
|
-
}
|
|
442
|
-
const packageBumpMap = {};
|
|
443
|
-
const bumpType = await select({
|
|
444
|
-
message: "Select release type",
|
|
445
|
-
options: [
|
|
446
|
-
{
|
|
447
|
-
value: "patch",
|
|
448
|
-
label: "patch"
|
|
449
|
-
},
|
|
450
|
-
{
|
|
451
|
-
value: "minor",
|
|
452
|
-
label: "minor"
|
|
453
|
-
},
|
|
454
|
-
{
|
|
455
|
-
value: "major",
|
|
456
|
-
label: "major"
|
|
457
|
-
},
|
|
458
|
-
{
|
|
459
|
-
value: "per-package",
|
|
460
|
-
label: "choose per-package"
|
|
461
|
-
}
|
|
462
|
-
]
|
|
463
|
-
});
|
|
464
|
-
if (isCancel(bumpType)) throw new CancelledError();
|
|
465
|
-
if (bumpType === "per-package") for (const pkg of selectedPackages) {
|
|
466
|
-
const bumpType = await select({
|
|
467
|
-
message: `Select release type for "${pkg}"`,
|
|
468
|
-
options: [
|
|
469
|
-
{
|
|
470
|
-
value: "patch",
|
|
471
|
-
label: "patch"
|
|
472
|
-
},
|
|
473
|
-
{
|
|
474
|
-
value: "minor",
|
|
475
|
-
label: "minor"
|
|
476
|
-
},
|
|
477
|
-
{
|
|
478
|
-
value: "major",
|
|
479
|
-
label: "major"
|
|
480
|
-
}
|
|
481
|
-
]
|
|
482
|
-
});
|
|
483
|
-
if (isCancel(bumpType)) throw new CancelledError();
|
|
484
|
-
packageBumpMap[pkg] = bumpType;
|
|
485
|
-
}
|
|
486
|
-
else for (const pkg of selectedPackages) packageBumpMap[pkg] = bumpType;
|
|
487
|
-
const message = await multiline({
|
|
488
|
-
message: "Describe change (Markdown supported, press tab then enter to exit)",
|
|
489
|
-
placeholder: "The first line is heading\n\nAdditional description.",
|
|
490
|
-
showSubmit: true,
|
|
491
|
-
validate(value) {
|
|
492
|
-
if (!value?.trim()) return "Enter a message.";
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
if (isCancel(message)) throw new CancelledError();
|
|
496
|
-
const filename = changelogFilename();
|
|
497
|
-
const s = spinner();
|
|
498
|
-
s.start("Creating changelog");
|
|
499
|
-
await mkdir(context.changelogDir, { recursive: true });
|
|
500
|
-
await writeFile(join(context.changelogDir, filename), renderManualChangelog(packageBumpMap, message.trim()));
|
|
501
|
-
s.stop("Created changelog file");
|
|
502
|
-
const notes = [filename];
|
|
503
|
-
for (const pkg of selectedPackages) notes.push(`${pkg}: ${packageBumpMap[pkg]}`);
|
|
504
|
-
note(notes.join("\n"), "Created changelog");
|
|
505
|
-
outro("Changelog ready.");
|
|
506
|
-
}
|
|
507
520
|
async function versionPackages(tegami, options) {
|
|
508
521
|
intro("Version Packages");
|
|
509
522
|
const { version: customVersion } = options.cli;
|
|
@@ -512,15 +525,15 @@ async function versionPackages(tegami, options) {
|
|
|
512
525
|
if (!draft.canApply()) throw new Error(`The draft plan from custom "version" hook must not be applied`);
|
|
513
526
|
for (const plugin of context.plugins) await handlePluginError(plugin, "cli.publishPlanCreated", () => plugin.cli?.publishPlanCreated?.call(context, draft));
|
|
514
527
|
if (!draft.hasPending()) {
|
|
515
|
-
note("No pending
|
|
528
|
+
note("No pending version changes matched workspace packages.", "Nothing to version");
|
|
516
529
|
outro("No versions changed.");
|
|
517
530
|
return false;
|
|
518
531
|
}
|
|
519
532
|
const planEntries = [];
|
|
520
533
|
for (const pkg of context.graph.getPackages()) {
|
|
521
534
|
const plan = draft.getPackagePlan(pkg.id);
|
|
522
|
-
if (!plan
|
|
523
|
-
planEntries.push(`${pkg.id}: ${plan.
|
|
535
|
+
if (!plan || plan.bumpVersion(pkg) === pkg.version) continue;
|
|
536
|
+
planEntries.push(`${pkg.id}: ${pkg.version} → ${plan.bumpVersion(pkg)} (${plan.changelogs?.length ?? 0} changelogs)`);
|
|
524
537
|
if (plan.bumpReasons) for (const reason of plan.bumpReasons) planEntries.push(` - ${reason}`);
|
|
525
538
|
}
|
|
526
539
|
note(planEntries.join("\n"), "Release plan");
|
|
@@ -571,7 +584,7 @@ async function runInitAgent(tegami, options) {
|
|
|
571
584
|
s.start("Writing AGENTS.md");
|
|
572
585
|
const result = await initAgent(context, options);
|
|
573
586
|
s.stop(result.created ? "Created AGENTS.md" : "Appended to AGENTS.md");
|
|
574
|
-
note(relative(context.cwd, result.path) || "AGENTS.md", "Agent instructions");
|
|
587
|
+
note(path.relative(context.cwd, result.path) || "AGENTS.md", "Agent instructions");
|
|
575
588
|
outro("Agents can follow AGENTS.md to write changelogs.");
|
|
576
589
|
}
|
|
577
590
|
async function runCleanup(tegami) {
|
|
@@ -591,16 +604,6 @@ async function runCleanup(tegami) {
|
|
|
591
604
|
}
|
|
592
605
|
outro(`Publish plan at ${planPath} is still pending. Publish it before cleanup.`);
|
|
593
606
|
}
|
|
594
|
-
function renderManualChangelog(packageBumpMap, message) {
|
|
595
|
-
return [
|
|
596
|
-
"---",
|
|
597
|
-
dump({ packages: packageBumpMap }).trim(),
|
|
598
|
-
"---",
|
|
599
|
-
"",
|
|
600
|
-
`## ${message}`,
|
|
601
|
-
""
|
|
602
|
-
].join("\n");
|
|
603
|
-
}
|
|
604
607
|
async function runAction(tegami, action) {
|
|
605
608
|
try {
|
|
606
609
|
const context = await tegami._internal.context();
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
//#region src/utils/error.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
var CancelledError = class extends Error {
|
|
3
|
+
constructor() {
|
|
4
|
+
super("Cancelled.");
|
|
5
|
+
}
|
|
6
|
+
};
|
|
5
7
|
function execFailure(context, result) {
|
|
6
8
|
const lines = [context, `(exit ${result.exitCode})`];
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
+
const out = result.stdout.trim();
|
|
10
|
+
const err = result.stderr.trim();
|
|
11
|
+
if (out) lines.push(out);
|
|
12
|
+
if (err) lines.push(err);
|
|
9
13
|
return new Error(lines.join("\n"));
|
|
10
14
|
}
|
|
11
15
|
function isNodeError(error) {
|
|
@@ -20,4 +24,4 @@ async function handlePluginError(plugin, hookName, callback) {
|
|
|
20
24
|
}
|
|
21
25
|
}
|
|
22
26
|
//#endregion
|
|
23
|
-
export {
|
|
27
|
+
export { isNodeError as i, execFailure as n, handlePluginError as r, CancelledError as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as bumpVersion } from "./semver-cnZp9koa.js";
|
|
2
2
|
//#region src/graph.ts
|
|
3
3
|
/** Package discovered in the workspace. */
|
|
4
4
|
var WorkspacePackage = class {
|
|
@@ -13,17 +13,21 @@ var WorkspacePackage = class {
|
|
|
13
13
|
setPackageOptions(options) {
|
|
14
14
|
this.opts = options;
|
|
15
15
|
}
|
|
16
|
-
/** create
|
|
17
|
-
|
|
16
|
+
/** create the initial draft plan. */
|
|
17
|
+
initPlan() {
|
|
18
|
+
return { bumpVersion(pkg) {
|
|
19
|
+
return bumpVersion(pkg.version, this.type, this.prerelease);
|
|
20
|
+
} };
|
|
21
|
+
}
|
|
22
|
+
/** configure an initial draft plan to match script-level configs. */
|
|
23
|
+
configurePlan(plan) {
|
|
18
24
|
const { publish, prerelease, npm } = this.opts;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
npm
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
};
|
|
25
|
+
if (publish !== void 0) plan.publish = publish;
|
|
26
|
+
if (prerelease !== void 0) plan.prerelease = prerelease;
|
|
27
|
+
if (npm?.distTag) {
|
|
28
|
+
plan.npm ??= {};
|
|
29
|
+
plan.npm.distTag = npm.distTag;
|
|
30
|
+
}
|
|
27
31
|
}
|
|
28
32
|
};
|
|
29
33
|
/** Dependency graph for discovered workspace packages. */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { type CreateChangelogOptions, type CreatedChangelog, type DraftPlan, type GroupOptions, type LogGenerator, type PackageGraph, type PackageGroup, type PackageOptions, type PackagePlan, type PackagePublishResult, type PublishOptions, type PublishResult, type RegistryClient, Tegami, type TegamiOptions, type TegamiPlugin, type TegamiPluginOption, type WorkspacePackage, tegami };
|
|
1
|
+
import { A as PackagePlan, C as PublishOptions, D as PackageGroup, E as PackageGraph, O as WorkspacePackage, S as PackagePublishResult, a as PublishPreflight, b as CreateChangelogOptions, c as TegamiPlugin, i as PackageOptions, k as DraftPlan, l as TegamiPluginOption, n as GroupOptions, o as RegistryClient, r as LogGenerator, s as TegamiOptions, v as Tegami, w as PublishResult, x as CreatedChangelog, y as tegami } from "./types-Di--A9X1.js";
|
|
2
|
+
export { type CreateChangelogOptions, type CreatedChangelog, type DraftPlan, type GroupOptions, type LogGenerator, type PackageGraph, type PackageGroup, type PackageOptions, type PackagePlan, type PackagePublishResult, type PublishOptions, type PublishPreflight, type PublishResult, type RegistryClient, Tegami, type TegamiOptions, type TegamiPlugin, type TegamiPluginOption, type WorkspacePackage, tegami };
|