tegami 1.0.0-beta.3 → 1.0.0-beta.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/cli/index.d.ts +7 -5
- package/dist/cli/index.js +206 -219
- package/dist/draft-DtFyGxe8.js +455 -0
- package/dist/generators/simple.d.ts +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +27 -478
- package/dist/{npm-BzhclYfR.js → npm-CMOyacwf.js} +2 -2
- package/dist/plugins/git.d.ts +1 -1
- package/dist/plugins/git.js +3 -3
- package/dist/plugins/github.d.ts +1 -1
- package/dist/plugins/github.js +348 -44
- package/dist/plugins/gitlab.d.ts +1 -3
- package/dist/plugins/gitlab.js +263 -55
- package/dist/plugins/go.d.ts +1 -1
- package/dist/plugins/go.js +2 -2
- package/dist/providers/cargo.d.ts +1 -1
- package/dist/providers/cargo.js +2 -2
- package/dist/providers/npm.d.ts +1 -1
- package/dist/providers/npm.js +1 -1
- package/dist/{types-BHT_9k9p.d.ts → types-DKZsadC8.d.ts} +97 -8
- package/package.json +1 -2
- package/dist/api-CGfXmmEM.js +0 -122
- package/dist/index-syNgzQTi.d.ts +0 -64
package/dist/cli/index.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as Tegami } from "../index-syNgzQTi.js";
|
|
3
|
-
import { Command } from "commander";
|
|
1
|
+
import { O as Draft, _ as PublishPlan, t as Awaitable, u as Tegami } from "../types-DKZsadC8.js";
|
|
4
2
|
|
|
5
3
|
//#region src/cli/index.d.ts
|
|
6
4
|
interface TegamiCLIOptions {
|
|
@@ -8,6 +6,10 @@ interface TegamiCLIOptions {
|
|
|
8
6
|
version?: () => Awaitable<Draft>;
|
|
9
7
|
publish?: () => Awaitable<PublishPlan>;
|
|
10
8
|
}
|
|
11
|
-
|
|
9
|
+
interface TegamiCLI {
|
|
10
|
+
parseAsync(argv?: string[]): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
declare function createCli(tegami: Tegami, options?: TegamiCLIOptions): TegamiCLI;
|
|
13
|
+
declare function runCli(tegami: Tegami, options?: TegamiCLIOptions): Promise<void>;
|
|
12
14
|
//#endregion
|
|
13
|
-
export { TegamiCLIOptions, createCli };
|
|
15
|
+
export { TegamiCLI, TegamiCLIOptions, createCli, runCli };
|
package/dist/cli/index.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import { r as formatNpmDistTag } from "../semver-EKJ8yK5U.js";
|
|
2
1
|
import { i as renderChangelog, n as generateFromCommits, t as changelogFilename } from "../generate-BfYdNTFi.js";
|
|
3
|
-
import {
|
|
4
|
-
import { i as findIssueCommentByPrefix, l as updateIssueComment, o as getPullRequest, t as createIssueComment } from "../api-CGfXmmEM.js";
|
|
2
|
+
import { o as isCI, r as handlePluginError, t as CancelledError } from "../error-We7chQVJ.js";
|
|
5
3
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
6
|
-
import path, {
|
|
4
|
+
import path, { join, relative } from "node:path";
|
|
7
5
|
import { x } from "tinyexec";
|
|
8
|
-
import z from "zod";
|
|
9
|
-
import { resolveCommand } from "package-manager-detector";
|
|
10
6
|
import { autocompleteMultiselect, confirm, intro, isCancel, multiline, note, outro, select, spinner } from "@clack/prompts";
|
|
11
|
-
import {
|
|
7
|
+
import { parseArgs } from "node:util";
|
|
12
8
|
//#region src/utils/git-changes.ts
|
|
13
9
|
async function getChangedPackages(graph, cwd) {
|
|
14
10
|
return resolveChangedPackages(graph, await getChangedFilePaths(cwd), cwd);
|
|
@@ -203,7 +199,6 @@ async function promptPackageBumpTypes(selectedPackages) {
|
|
|
203
199
|
}
|
|
204
200
|
//#endregion
|
|
205
201
|
//#region src/cli/init-agent.ts
|
|
206
|
-
const CHANGELOG_DOCS_URL$1 = "https://tegami.fuma-nama.dev/changelog";
|
|
207
202
|
async function initAgent(context, options = {}) {
|
|
208
203
|
const output = path.resolve(context.cwd, options.output ?? "AGENTS.md");
|
|
209
204
|
const content = renderAgentsMd(context);
|
|
@@ -233,7 +228,7 @@ function renderAgentsMd(context) {
|
|
|
233
228
|
"",
|
|
234
229
|
`Create pending changelog files under \`${changelogDir}/\` as \`YYYY-MM-DD-{hash}.md\`.`,
|
|
235
230
|
"",
|
|
236
|
-
`See the [changelog format docs](
|
|
231
|
+
`See the [changelog format docs](https://tegami.fuma-nama.dev/changelog) for details.`,
|
|
237
232
|
"",
|
|
238
233
|
"### Example",
|
|
239
234
|
"",
|
|
@@ -266,225 +261,231 @@ function renderAgentsMd(context) {
|
|
|
266
261
|
].join("\n");
|
|
267
262
|
}
|
|
268
263
|
//#endregion
|
|
269
|
-
//#region src/cli/
|
|
270
|
-
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const prChangelogFiles = await listPullRequestChangelogFiles(context, pullRequest.baseSha, pullRequest.headSha);
|
|
278
|
-
const createLink = createChangelogUrl(context, pullRequest.headRepo, pullRequest.headRef, changelogFilename());
|
|
279
|
-
const lines = [
|
|
280
|
-
"### Tegami",
|
|
281
|
-
"",
|
|
282
|
-
`This repository uses [Tegami](${TEGAMI_DOCS_URL}) to manage releases. When your changes affect published packages, add a changelog file under \`.tegami/\` before merging.`,
|
|
283
|
-
"",
|
|
284
|
-
`[**Create a changelog →**](${createLink}) · [Changelog format](${CHANGELOG_DOCS_URL})`,
|
|
285
|
-
""
|
|
286
|
-
];
|
|
287
|
-
const pendingPackages = [];
|
|
288
|
-
for (const pkg of context.graph.getPackages()) {
|
|
289
|
-
const plan = draft.getPackageDraft(pkg.id);
|
|
290
|
-
if (!plan) continue;
|
|
291
|
-
const bumped = plan.bumpVersion(pkg);
|
|
292
|
-
if (!bumped || !pkg.version || bumped === pkg.version) continue;
|
|
293
|
-
pendingPackages.push({
|
|
294
|
-
name: pkg.name,
|
|
295
|
-
type: plan.type ?? "—",
|
|
296
|
-
from: pkg.version,
|
|
297
|
-
to: bumped,
|
|
298
|
-
distTag: plan.npm?.distTag
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
const prChangelogs = draft.getChangelogs().filter((entry) => prChangelogFiles.has(entry.filename));
|
|
302
|
-
if (pendingPackages.length > 0) {
|
|
303
|
-
lines.push("#### Release preview", "", "| Package | Bump | Version |", "| --- | --- | --- |");
|
|
304
|
-
for (const { name, type, from, to, distTag } of pendingPackages) lines.push(`| \`${name}\` | ${type} | \`${from}\` → \`${to}\`${formatNpmDistTag(distTag)} |`);
|
|
305
|
-
lines.push("");
|
|
264
|
+
//#region src/cli/core.ts
|
|
265
|
+
function createTegamiCliRegistry(tegami) {
|
|
266
|
+
const commands = /* @__PURE__ */ new Map();
|
|
267
|
+
function getChildCommands(command) {
|
|
268
|
+
const out = [];
|
|
269
|
+
const prefix = command.path.join("\0");
|
|
270
|
+
for (const [key, candidate] of commands) if (key.startsWith(prefix) && key.length > prefix.length) out.push(candidate);
|
|
271
|
+
return out;
|
|
306
272
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
273
|
+
return {
|
|
274
|
+
command(path, options) {
|
|
275
|
+
const definition = {
|
|
276
|
+
path: path.length === 0 ? [] : path.split(/\s+/),
|
|
277
|
+
positionals: [],
|
|
278
|
+
description: options?.description,
|
|
279
|
+
options: [],
|
|
280
|
+
resolve: options?.resolve ?? true
|
|
281
|
+
};
|
|
282
|
+
commands.set(definition.path.join("\0"), definition);
|
|
283
|
+
const api = {
|
|
284
|
+
option(name, { short, description = "", type }) {
|
|
285
|
+
definition.options.push({
|
|
286
|
+
name,
|
|
287
|
+
short,
|
|
288
|
+
type,
|
|
289
|
+
description
|
|
290
|
+
});
|
|
291
|
+
return api;
|
|
292
|
+
},
|
|
293
|
+
positional(name, required) {
|
|
294
|
+
definition.positionals.push({
|
|
295
|
+
name,
|
|
296
|
+
required: required ?? true
|
|
297
|
+
});
|
|
298
|
+
return api;
|
|
299
|
+
},
|
|
300
|
+
action(fn) {
|
|
301
|
+
definition.action = fn;
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
return api;
|
|
305
|
+
},
|
|
306
|
+
help: () => formatRootHelp(commands),
|
|
307
|
+
async parse(argv) {
|
|
308
|
+
if (argv[0] === "--help" || argv[0] === "-h") {
|
|
309
|
+
console.log(formatRootHelp(commands));
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
const match = findCommand(commands, argv);
|
|
313
|
+
if (!match) throw new Error(`Unknown command: ${argv[0]}`);
|
|
314
|
+
const args = argv.slice(match.path.length);
|
|
315
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
316
|
+
console.log(formatCommandHelp(match, getChildCommands(match)));
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (!match.action) {
|
|
320
|
+
if (args.length === 0) {
|
|
321
|
+
console.log(formatCommandHelp(match, getChildCommands(match)));
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
throw new Error(`Unknown command: ${argv.slice(0, match.path.length + 1).join(" ")}`);
|
|
325
|
+
}
|
|
326
|
+
const { values, positionals } = parseCommandArgs(match, args);
|
|
327
|
+
const context = match.resolve ? await tegami._internal.context() : await tegami._internal.contextUnresolved();
|
|
328
|
+
await match.action({
|
|
329
|
+
context,
|
|
330
|
+
values,
|
|
331
|
+
positionals
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
};
|
|
315
335
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
const markedBody = `${COMMENT_MARKER}\n${body}`;
|
|
328
|
-
const token = process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;
|
|
329
|
-
const existingId = await findIssueCommentByPrefix(repo, pr.number, COMMENT_MARKER, token);
|
|
330
|
-
if (existingId) {
|
|
331
|
-
await updateIssueComment(repo, existingId, markedBody, token);
|
|
332
|
-
return;
|
|
336
|
+
function formatUsage(command) {
|
|
337
|
+
return [...command.path, ...command.positionals.map((positional) => positional.required ? `<${positional.name}>` : `[${positional.name}]`)].join(" ");
|
|
338
|
+
}
|
|
339
|
+
function findCommand(commands, argv) {
|
|
340
|
+
if (argv.length === 0) return commands.get("");
|
|
341
|
+
for (let i = 0; i < argv.length; i++) {
|
|
342
|
+
const search = argv.slice(0, argv.length - i).join("\0");
|
|
343
|
+
const res = commands.get(search);
|
|
344
|
+
if (res) return res;
|
|
333
345
|
}
|
|
334
|
-
await createIssueComment(repo, pr.number, markedBody, token);
|
|
335
346
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
found: false,
|
|
345
|
-
reason: "GITHUB_EVENT_PATH is required."
|
|
347
|
+
function parseCommandArgs(command, args) {
|
|
348
|
+
const optionConfig = { help: {
|
|
349
|
+
type: "boolean",
|
|
350
|
+
short: "h"
|
|
351
|
+
} };
|
|
352
|
+
for (const option of command.options) optionConfig[option.name] = {
|
|
353
|
+
type: option.type,
|
|
354
|
+
short: option.short
|
|
346
355
|
};
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
356
|
+
const parsed = parseArgs({
|
|
357
|
+
args,
|
|
358
|
+
options: optionConfig,
|
|
359
|
+
strict: true,
|
|
360
|
+
allowPositionals: command.positionals.length > 0
|
|
361
|
+
});
|
|
362
|
+
const positionals = {};
|
|
363
|
+
if (parsed.positionals.length > command.positionals.length) throw new Error("Too many arguments");
|
|
364
|
+
for (const positional of command.positionals) {
|
|
365
|
+
const value = parsed.positionals.shift();
|
|
366
|
+
if (value === void 0 && positional.required) throw new Error(`missing required argument: ${positional.name}`);
|
|
367
|
+
if (value === void 0) continue;
|
|
368
|
+
positionals[positional.name] = value;
|
|
355
369
|
}
|
|
356
|
-
const { error, data } = eventSchema.safeParse(raw);
|
|
357
|
-
if (error) return {
|
|
358
|
-
found: false,
|
|
359
|
-
reason: z.prettifyError(error)
|
|
360
|
-
};
|
|
361
370
|
return {
|
|
362
|
-
|
|
363
|
-
|
|
371
|
+
values: parsed.values,
|
|
372
|
+
positionals
|
|
364
373
|
};
|
|
365
374
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return {
|
|
375
|
-
repo,
|
|
376
|
-
headRepo: data.headRepository ? `${data.headRepository.owner.login}/${data.headRepository.name}` : repo,
|
|
377
|
-
headRef: data.headRefName,
|
|
378
|
-
baseSha: data.baseRefOid,
|
|
379
|
-
headSha: data.headRefOid
|
|
380
|
-
};
|
|
375
|
+
function formatRootHelp(commands) {
|
|
376
|
+
let width = 0;
|
|
377
|
+
const rows = [];
|
|
378
|
+
for (const command of commands.values()) {
|
|
379
|
+
if (command.path.length === 0) continue;
|
|
380
|
+
const key = formatUsage(command);
|
|
381
|
+
width = Math.max(width, key.length);
|
|
382
|
+
rows.push([key, command.description ?? ""]);
|
|
381
383
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
384
|
+
return `${[
|
|
385
|
+
"Usage: tegami [command]",
|
|
386
|
+
"",
|
|
387
|
+
commands.get("")?.description ?? "create changelogs",
|
|
388
|
+
"",
|
|
389
|
+
"Commands:",
|
|
390
|
+
...rows.map(([usage, description]) => ` ${usage.padEnd(width)} ${description}`),
|
|
391
|
+
"",
|
|
392
|
+
"Run without a command to open the changelog TUI."
|
|
393
|
+
].join("\n")}\n`;
|
|
388
394
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
395
|
+
function formatCommandHelp(command, childCommands) {
|
|
396
|
+
let width = 0;
|
|
397
|
+
let childWidth = 0;
|
|
398
|
+
const optionRows = command.options.map((option) => {
|
|
399
|
+
const short = option.short ? `-${option.short}, ` : "";
|
|
400
|
+
const long = `--${option.name}`;
|
|
401
|
+
const key = option.type === "string" ? `${short}${long} <value>` : `${short}${long}`;
|
|
402
|
+
width = Math.max(width, key.length);
|
|
403
|
+
return [key, option.description ?? ""];
|
|
404
|
+
});
|
|
405
|
+
const childRows = childCommands.map((child) => {
|
|
406
|
+
const key = formatUsage(child);
|
|
407
|
+
childWidth = Math.max(childWidth, key.length);
|
|
408
|
+
return [key, child.description ?? ""];
|
|
409
|
+
});
|
|
410
|
+
const lines = [];
|
|
411
|
+
if (command.action) lines.push(`Usage: ${formatUsage(command)}`, "");
|
|
412
|
+
if (command.description) lines.push(command.description, "");
|
|
413
|
+
if (optionRows.length > 0) {
|
|
414
|
+
lines.push("Options:");
|
|
415
|
+
for (const [flags, description] of optionRows) lines.push(` ${flags.padEnd(width)} ${description}`);
|
|
416
|
+
lines.push("");
|
|
397
417
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
headRef: pullRequest.head.ref,
|
|
403
|
-
baseSha: pullRequest.base.sha,
|
|
404
|
-
headSha: pullRequest.head.sha
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
|
-
async function listPullRequestChangelogFiles(context, baseSha, headSha) {
|
|
408
|
-
const dir = relative(context.cwd, context.changelogDir);
|
|
409
|
-
const result = await x("git", [
|
|
410
|
-
"diff",
|
|
411
|
-
"--name-only",
|
|
412
|
-
"--diff-filter=ACMRD",
|
|
413
|
-
`${baseSha}...${headSha}`,
|
|
414
|
-
"--",
|
|
415
|
-
`${dir}/`
|
|
416
|
-
], { nodeOptions: { cwd: context.cwd } });
|
|
417
|
-
if (result.exitCode !== 0) throw execFailure("Failed to list pull request changelog files.", result);
|
|
418
|
-
const files = /* @__PURE__ */ new Set();
|
|
419
|
-
for (const line of result.stdout.split("\n")) {
|
|
420
|
-
const trimmed = line.trim();
|
|
421
|
-
if (trimmed.endsWith(".md")) files.add(basename(trimmed));
|
|
418
|
+
if (childRows.length > 0) {
|
|
419
|
+
lines.push("Commands:");
|
|
420
|
+
for (const [usage, description] of childRows) lines.push(` ${usage.padEnd(childWidth)} ${description}`);
|
|
421
|
+
lines.push("");
|
|
422
422
|
}
|
|
423
|
-
return
|
|
424
|
-
}
|
|
425
|
-
function createChangelogUrl(context, repo, branch, filename) {
|
|
426
|
-
const filePath = join(relative(context.cwd, context.changelogDir), filename).replaceAll("\\", "/");
|
|
427
|
-
return `https://github.com/${repo}/new/${branch.split("/").map(encodeURIComponent).join("/")}?${new URLSearchParams({ filename: filePath })}`;
|
|
423
|
+
return lines.join("\n");
|
|
428
424
|
}
|
|
429
425
|
//#endregion
|
|
430
426
|
//#region src/cli/index.ts
|
|
431
427
|
function createCli(tegami, options = {}) {
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
|
|
428
|
+
const $cli = init();
|
|
429
|
+
async function init() {
|
|
430
|
+
const ctx = await tegami._internal.contextUnresolved();
|
|
431
|
+
const cli = createTegamiCliRegistry(tegami);
|
|
432
|
+
registerCoreCommands(cli, tegami, options);
|
|
433
|
+
for (const plugin of ctx.plugins) await handlePluginError(plugin, "initCli", () => plugin.initCli?.call(ctx, cli));
|
|
434
|
+
return cli;
|
|
435
|
+
}
|
|
436
|
+
return { async parseAsync(argv = process.argv.slice(2)) {
|
|
437
|
+
try {
|
|
438
|
+
await (await $cli).parse(argv);
|
|
439
|
+
} catch (error) {
|
|
440
|
+
if (error instanceof CancelledError) outro(error.message);
|
|
441
|
+
else {
|
|
442
|
+
note(error instanceof Error ? error.message : String(error), "Error");
|
|
443
|
+
outro("Command failed.");
|
|
444
|
+
}
|
|
445
|
+
process.exit(1);
|
|
446
|
+
}
|
|
447
|
+
} };
|
|
448
|
+
}
|
|
449
|
+
async function runCli(tegami, options = {}) {
|
|
450
|
+
await createCli(tegami, options).parseAsync();
|
|
451
|
+
}
|
|
452
|
+
function registerCoreCommands(cli, tegami, options) {
|
|
453
|
+
cli.command("", { description: "create changelog files interactively" }).action(async () => {
|
|
454
|
+
await runChangelogTui(tegami);
|
|
455
|
+
});
|
|
456
|
+
cli.command("version", { description: "draft version changes and write the publish lock" }).action(async () => {
|
|
435
457
|
await versionPackages(tegami, { cli: options });
|
|
436
|
-
})
|
|
437
|
-
|
|
458
|
+
});
|
|
459
|
+
cli.command("ci", { description: "version and publish packages" }).action(async () => {
|
|
438
460
|
if (await versionPackages(tegami, { cli: options })) return;
|
|
439
461
|
await publishPackages(tegami, { cli: options });
|
|
440
|
-
})
|
|
441
|
-
|
|
462
|
+
});
|
|
463
|
+
cli.command("check-publish", { description: "exit with code 1 if no publishing needed, otherwise 0" }).action(async () => {
|
|
442
464
|
const status = await tegami.publishStatus();
|
|
443
465
|
process.exit(status === "pending" ? 0 : 1);
|
|
444
|
-
}));
|
|
445
|
-
const programPr = program.command("pr");
|
|
446
|
-
programPr.command("preview").description("(should be executed in a GitHub action) show a pull request release preview and changelog guidance").option("--artifact <path>", "write preview markdown to a file").option("--number <number>", "pull request number", (value) => {
|
|
447
|
-
const number = Number(value);
|
|
448
|
-
if (!Number.isInteger(number) || number <= 0) throw new InvalidArgumentError("--number must be a positive integer.");
|
|
449
|
-
return number;
|
|
450
|
-
}).action((commandOptions) => runAction(tegami, async () => {
|
|
451
|
-
const context = await tegami._internal.context();
|
|
452
|
-
const body = await buildPrPreview(context, await tegami.draft(), commandOptions);
|
|
453
|
-
if (commandOptions.artifact) {
|
|
454
|
-
const artifactPath = path.resolve(context.cwd, commandOptions.artifact);
|
|
455
|
-
await writeFile(artifactPath, body);
|
|
456
|
-
if (!isCI()) {
|
|
457
|
-
note(path.relative(context.cwd, artifactPath) || commandOptions.artifact, "Release preview");
|
|
458
|
-
outro("Release preview ready.");
|
|
459
|
-
}
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
if (isCI()) {
|
|
463
|
-
process.stdout.write(`${body}\n`);
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
466
|
-
note(body, "Release preview");
|
|
467
|
-
outro("Release preview ready.");
|
|
468
|
-
}));
|
|
469
|
-
programPr.command("comment").description("(should be used with 'pr preview') post the pull request release preview as a comment").argument("<artifact>", "the file path of GitHub artifact").action(async (artifact) => {
|
|
470
|
-
try {
|
|
471
|
-
await postPrComment(await readFile(artifact, "utf8"));
|
|
472
|
-
outro("Pull request comment updated.");
|
|
473
|
-
} catch (error) {
|
|
474
|
-
note(error instanceof Error ? error.message : String(error), "Error");
|
|
475
|
-
outro("Command failed.");
|
|
476
|
-
process.exit(1);
|
|
477
|
-
}
|
|
478
466
|
});
|
|
479
|
-
|
|
467
|
+
cli.command("publish", { description: "publish packages from the publish lock" }).option("dry-run", {
|
|
468
|
+
type: "boolean",
|
|
469
|
+
description: "validate the publish lock without publishing"
|
|
470
|
+
}).action(async ({ values }) => {
|
|
480
471
|
await publishPackages(tegami, {
|
|
481
|
-
|
|
472
|
+
dryRun: values["dry-run"],
|
|
482
473
|
cli: options
|
|
483
474
|
});
|
|
484
|
-
})
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
475
|
+
});
|
|
476
|
+
cli.command("cleanup", { description: "remove the publish lock after all packages have been published" }).action(async () => {
|
|
477
|
+
await runCleanup(tegami);
|
|
478
|
+
});
|
|
479
|
+
cli.command("init-agent", {
|
|
480
|
+
description: "write AGENTS.md with changelog instructions for AI agents",
|
|
481
|
+
resolve: false
|
|
482
|
+
}).option("output", {
|
|
483
|
+
type: "string",
|
|
484
|
+
short: "o",
|
|
485
|
+
description: "output path"
|
|
486
|
+
}).action(async ({ values }) => {
|
|
487
|
+
await runInitAgent(tegami, { output: values.output ?? "AGENTS.md" });
|
|
488
|
+
});
|
|
488
489
|
}
|
|
489
490
|
async function versionPackages(tegami, options) {
|
|
490
491
|
intro("Version Packages");
|
|
@@ -492,7 +493,7 @@ async function versionPackages(tegami, options) {
|
|
|
492
493
|
const context = await tegami._internal.context();
|
|
493
494
|
const draft = customVersion ? await customVersion() : await tegami.draft();
|
|
494
495
|
if (!draft.canApply()) throw new Error(`The draft from custom "version" hook must not be applied`);
|
|
495
|
-
for (const plugin of context.plugins) await handlePluginError(plugin, "
|
|
496
|
+
for (const plugin of context.plugins) await handlePluginError(plugin, "initCliDraft", () => plugin.initCliDraft?.call(context, draft));
|
|
496
497
|
if (!draft.hasPending()) {
|
|
497
498
|
note("No pending version changes matched workspace packages.", "Nothing to version");
|
|
498
499
|
outro("No versions changed.");
|
|
@@ -522,7 +523,7 @@ async function versionPackages(tegami, options) {
|
|
|
522
523
|
throw error;
|
|
523
524
|
}
|
|
524
525
|
s.stop("Package versions updated");
|
|
525
|
-
for (const plugin of context.plugins) await handlePluginError(plugin, "
|
|
526
|
+
for (const plugin of context.plugins) await handlePluginError(plugin, "applyCliDraft", () => plugin.applyCliDraft?.call(context, draft));
|
|
526
527
|
outro("Publish lock written.");
|
|
527
528
|
return true;
|
|
528
529
|
}
|
|
@@ -589,19 +590,5 @@ async function runCleanup(tegami) {
|
|
|
589
590
|
}
|
|
590
591
|
outro(`Publish lock at ${lockPath} is still pending. Publish it before cleanup.`);
|
|
591
592
|
}
|
|
592
|
-
async function runAction(tegami, action) {
|
|
593
|
-
try {
|
|
594
|
-
const context = await tegami._internal.context();
|
|
595
|
-
for (const plugin of context.plugins) await handlePluginError(plugin, "cli.init", () => plugin.cli?.init?.call(context));
|
|
596
|
-
await action();
|
|
597
|
-
} catch (error) {
|
|
598
|
-
if (error instanceof CancelledError) outro(error.message);
|
|
599
|
-
else {
|
|
600
|
-
note(error instanceof Error ? error.message : String(error), "Error");
|
|
601
|
-
outro("Command failed.");
|
|
602
|
-
}
|
|
603
|
-
process.exit(1);
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
593
|
//#endregion
|
|
607
|
-
export { createCli };
|
|
594
|
+
export { createCli, runCli };
|