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.
Files changed (31) hide show
  1. package/dist/{_accessExpressionAsString-QhbUZzwv.js → _accessExpressionAsString-DW_6Xqcp.js} +1 -1
  2. package/dist/{_assertGuard-BBn2NbSz.js → _assertGuard-CFFC1Up9.js} +2 -2
  3. package/dist/{_createStandardSchema-BGQyz-uA.js → _createStandardSchema-CrRqJgaE.js} +2 -2
  4. package/dist/cli/index.d.ts +1 -1
  5. package/dist/cli/index.js +10 -8
  6. package/dist/{generate-Cnd8RiKO.js → generate-Cgl2G5ea.js} +2 -2
  7. package/dist/generators/simple.d.ts +1 -1
  8. package/dist/generators/simple.js +1 -1
  9. package/dist/{graph-BmXTJZxx.js → graph-DaJ28Y4f.js} +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +14 -8
  12. package/dist/{npm-cS-D2xGI.js → npm-CyC2Rk11.js} +221 -133
  13. package/dist/plugins/cargo.d.ts +1 -1
  14. package/dist/plugins/cargo.js +37 -34
  15. package/dist/plugins/git.d.ts +1 -1
  16. package/dist/plugins/git.js +2 -4
  17. package/dist/plugins/github.d.ts +7 -7
  18. package/dist/plugins/github.js +113 -241
  19. package/dist/plugins/gitlab.d.ts +6 -6
  20. package/dist/plugins/gitlab.js +118 -245
  21. package/dist/plugins/go.d.ts +1 -1
  22. package/dist/plugins/go.js +10 -10
  23. package/dist/providers/npm.d.ts +1 -1
  24. package/dist/providers/npm.js +1 -1
  25. package/dist/{publish-Bt3e1RPs.js → publish-DAMkayLs.js} +11 -15
  26. package/dist/{semver-EKJ8yK5U.js → semver-DrtaCCZK.js} +15 -3
  27. package/dist/{shared-C_iSTp_s.js → shared-pTOZU5UZ.js} +11 -3
  28. package/dist/{types-C_vz41r2.d.ts → types-BMYzG4dR.d.ts} +42 -26
  29. package/dist/{version-request-DXk_B7O_.d.ts → version-request-BorZZ98V.d.ts} +1 -1
  30. package/dist/{version-request-DvWVAYj2.js → version-request-CQ4cJHtP.js} +203 -67
  31. package/package.json +5 -4
@@ -1,8 +1,8 @@
1
1
  import { n as execFailure, r as fetchFailure } from "../error-CAsrGb6e.js";
2
- import { t as _accessExpressionAsString } from "../_accessExpressionAsString-QhbUZzwv.js";
3
- import { t as _assertGuard } from "../_assertGuard-BBn2NbSz.js";
4
- import { n as WorkspacePackage } from "../graph-BmXTJZxx.js";
5
- import { readFile, writeFile } from "node:fs/promises";
2
+ import { t as _accessExpressionAsString } from "../_accessExpressionAsString-DW_6Xqcp.js";
3
+ import { t as _assertGuard } from "../_assertGuard-CFFC1Up9.js";
4
+ import { n as WorkspacePackage } from "../graph-DaJ28Y4f.js";
5
+ import fs from "node:fs/promises";
6
6
  import path from "node:path";
7
7
  import { x } from "tinyexec";
8
8
  import * as semver$1 from "semver";
@@ -510,17 +510,47 @@ var CargoToml = class {
510
510
  data;
511
511
  dependencies;
512
512
  workspace;
513
+ originalContent;
513
514
  constructor(path, content, data) {
514
515
  this.path = path;
515
516
  this.content = content;
516
517
  this.data = data;
518
+ this.originalContent = content;
517
519
  }
518
520
  listDependencies(graph) {
519
- return this.dependencies ??= listDependencies(graph, this);
521
+ if (this.dependencies) return this.dependencies;
522
+ const out = this.dependencies = [];
523
+ const scan = (obj, prefix = []) => {
524
+ for (const field of DEP_FIELDS) {
525
+ const table = obj[field];
526
+ if (!table) continue;
527
+ const tablePath = [...prefix, field];
528
+ for (const [key, spec] of Object.entries(table)) {
529
+ const { linked, range, setRange } = resolveLinkedDep(this, graph, tablePath, key, spec) ?? {};
530
+ out.push({
531
+ path: [...tablePath, key],
532
+ spec,
533
+ resolved: linked,
534
+ range,
535
+ setRange: setRange && ((v) => {
536
+ table[key] = setRange(v);
537
+ })
538
+ });
539
+ }
540
+ }
541
+ };
542
+ scan(this.data);
543
+ if (this.data.target) for (const [key, config] of Object.entries(this.data.target)) scan(config, ["target", key]);
544
+ if (this.data.workspace) scan(this.data.workspace);
545
+ return out;
520
546
  }
521
547
  patch(path, value) {
522
548
  this.content = edit(this.content, path, value);
523
549
  }
550
+ async write() {
551
+ if (this.content === this.originalContent) return;
552
+ await fs.writeFile(this.path, this.content);
553
+ }
524
554
  };
525
555
  var CargoPackage = class extends WorkspacePackage {
526
556
  path;
@@ -561,7 +591,6 @@ var CargoPackage = class extends WorkspacePackage {
561
591
  function cargo({ updateLockFile = true, bumpDep: getBumpDepType } = {}) {
562
592
  return {
563
593
  name: "cargo",
564
- enforce: "pre",
565
594
  async init() {
566
595
  await initToml();
567
596
  },
@@ -623,7 +652,7 @@ function cargo({ updateLockFile = true, bumpDep: getBumpDepType } = {}) {
623
652
  else updatedRange = resolved.version;
624
653
  setRange(updatedRange);
625
654
  }
626
- await Promise.all(Array.from(graph.files.values(), (file) => writeFile(file.path, file.content + "\n")));
655
+ await Promise.all(Array.from(graph.files.values(), (file) => file.write()));
627
656
  },
628
657
  async applyCliDraft() {
629
658
  if (!this.cargo || !updateLockFile) return;
@@ -691,7 +720,7 @@ async function isPackagePublished(name, version) {
691
720
  async function buildEntry(dir) {
692
721
  try {
693
722
  const filePath = path.join(dir, "Cargo.toml");
694
- const content = await readFile(filePath, "utf8");
723
+ const content = await fs.readFile(filePath, "utf8");
695
724
  return new CargoToml(filePath, content, assertCargoManifest(parse$1(content)));
696
725
  } catch {
697
726
  return;
@@ -736,32 +765,6 @@ async function expandWorkspaceMembers(cwd, members, exclude = []) {
736
765
  return item.endsWith(path.sep) ? item.slice(0, -1) : item;
737
766
  });
738
767
  }
739
- function listDependencies(graph, file) {
740
- const out = [];
741
- function scan(obj, prefix = []) {
742
- for (const field of DEP_FIELDS) {
743
- const table = obj[field];
744
- if (!table) continue;
745
- const tablePath = [...prefix, field];
746
- for (const [key, spec] of Object.entries(table)) {
747
- const { linked, range, setRange } = resolveLinkedDep(file, graph, tablePath, key, spec) ?? {};
748
- out.push({
749
- path: [...tablePath, key],
750
- spec,
751
- resolved: linked,
752
- range,
753
- setRange: setRange && ((v) => {
754
- table[key] = setRange(v);
755
- })
756
- });
757
- }
758
- }
759
- }
760
- scan(file.data);
761
- if (file.data.target) for (const [key, config] of Object.entries(file.data.target)) scan(config, ["target", key]);
762
- if (file.data.workspace) scan(file.data.workspace);
763
- return out;
764
- }
765
768
  function resolveLinkedDep(file, graph, tablePath, key, spec) {
766
769
  if (typeof spec === "string") {
767
770
  const linked = graph.packages.get(key);
@@ -1,4 +1,4 @@
1
- import { s as TegamiPlugin } from "../types-C_vz41r2.js";
1
+ import { s as TegamiPlugin } from "../types-BMYzG4dR.js";
2
2
 
3
3
  //#region src/plugins/git.d.ts
4
4
  interface GitPluginOptions {
@@ -22,7 +22,6 @@ function git(options = {}) {
22
22
  }
23
23
  return {
24
24
  name: "git",
25
- enforce: "pre",
26
25
  async initCli() {
27
26
  if (!isCI()) return;
28
27
  const gitOptions = { nodeOptions: { cwd: this.cwd } };
@@ -43,9 +42,8 @@ function git(options = {}) {
43
42
  const { graph } = this;
44
43
  for (const [id, packagePlan] of plan.packages) {
45
44
  const pkg = graph.get(id);
46
- packagePlan.git ??= {};
47
- if (pkg.group?.options.syncGitTag && pkg.version) packagePlan.git.tag = `${pkg.group.name}@${pkg.version}`;
48
- else if (pkg.version) packagePlan.git.tag = `${pkg.name}@${pkg.version}`;
45
+ const git = packagePlan.git ??= {};
46
+ if (pkg.version) git.tag ??= pkg.group?.options.syncGitTag ? `${pkg.group.name}@${pkg.version}` : `${pkg.name}@${pkg.version}`;
49
47
  }
50
48
  },
51
49
  async resolvePlanStatus({ plan }) {
@@ -1,15 +1,15 @@
1
- import { A as WorkspacePackage, b as TegamiContext, s as TegamiPlugin, t as Awaitable, v as PublishPlan } from "../types-C_vz41r2.js";
1
+ import { j as WorkspacePackage, s as TegamiPlugin, t as Awaitable, x as TegamiContext, y as PublishPlan } from "../types-BMYzG4dR.js";
2
2
  import { GitPluginOptions } from "./git.js";
3
- import { t as VersionRequestOptions } from "../version-request-DXk_B7O_.js";
3
+ import { t as VersionRequestOptions } from "../version-request-BorZZ98V.js";
4
4
 
5
5
  //#region src/plugins/github.d.ts
6
6
  interface GithubRelease {
7
7
  /** Release title */
8
- title?: string;
8
+ title: string;
9
9
  /** Release notes */
10
- notes?: string;
10
+ notes: string;
11
11
  /** Whether to mark release as prerelease */
12
- prerelease?: boolean;
12
+ prerelease: boolean;
13
13
  }
14
14
  /** Options for creating GitHub releases after a successful publish. */
15
15
  interface GitHubPluginOptions extends GitPluginOptions {
@@ -33,12 +33,12 @@ interface GitHubPluginOptions extends GitPluginOptions {
33
33
  tag: string;
34
34
  pkg: WorkspacePackage;
35
35
  plan: PublishPlan;
36
- }) => Awaitable<GithubRelease>; /** Override release details when multiple packages share a git tag. */
36
+ }) => Awaitable<Partial<GithubRelease>>; /** Override release details when multiple packages share a git tag. */
37
37
  createGrouped?: (this: TegamiContext, opts: {
38
38
  tag: string;
39
39
  packages: WorkspacePackage[];
40
40
  plan: PublishPlan;
41
- }) => Awaitable<GithubRelease>;
41
+ }) => Awaitable<Partial<GithubRelease>>;
42
42
  };
43
43
  /**
44
44
  * (CLI only) Open a version pull request after versioning.
@@ -1,14 +1,12 @@
1
- import { i as formatPackageVersion, r as formatNpmDistTag } from "../semver-EKJ8yK5U.js";
2
- import { t as changelogFilename } from "../generate-Cnd8RiKO.js";
1
+ import { t as changelogFilename } from "../generate-Cgl2G5ea.js";
3
2
  import { n as execFailure, o as cached, r as fetchFailure, s as isCI } from "../error-CAsrGb6e.js";
4
- import { a as createDraft, l as readChangelogEntries } from "../publish-Bt3e1RPs.js";
3
+ import { a as createDraft, l as readChangelogEntries } from "../publish-DAMkayLs.js";
5
4
  import { git } from "./git.js";
6
- import { t as onVersionRequest } from "../version-request-DvWVAYj2.js";
5
+ import { i as versionRequestPlugin, n as formatPreview, r as resolveFileCommit, t as createAutoRelease } from "../version-request-CQ4cJHtP.js";
7
6
  import { readFile, writeFile } from "node:fs/promises";
8
7
  import { basename, join, relative, resolve } from "node:path";
9
8
  import { x } from "tinyexec";
10
9
  import semver from "semver";
11
- import { resolveCommand } from "package-manager-detector";
12
10
  import { note, outro } from "@clack/prompts";
13
11
  //#region src/plugins/github/api.ts
14
12
  function parseGitHubRepo(repo) {
@@ -36,9 +34,9 @@ async function releaseExistsByTag(repo, tag, token) {
36
34
  if (!response.ok) throw await fetchFailure(`Failed to get GitHub release for ${tag}`, response);
37
35
  return true;
38
36
  }
39
- async function createRelease(repo, options) {
40
- const { owner, repo: name } = parseGitHubRepo(repo);
41
- const response = await githubRequest(`/repos/${owner}/${name}/releases`, options.token, {
37
+ async function createRelease(options) {
38
+ const { owner, repo } = parseGitHubRepo(options.repo);
39
+ const response = await githubRequest(`/repos/${owner}/${repo}/releases`, options.token, {
42
40
  method: "POST",
43
41
  headers: { "Content-Type": "application/json" },
44
42
  body: JSON.stringify({
@@ -172,46 +170,10 @@ function registerPrCli(cli) {
172
170
  }
173
171
  async function buildPrPreview(context, draft, options = {}) {
174
172
  const pullRequest = await resolvePullRequest(context, options);
175
- const tegamiCommandRaw = resolveCommand(context.npm?.client ?? "npm", "run", ["tegami"]);
176
- const tegamiCommand = [tegamiCommandRaw.command, ...tegamiCommandRaw.args].join(" ");
177
- const changelogFiles = await listPullRequestChangelogFiles(context, pullRequest.baseSha, pullRequest.headSha);
178
- const createLink = createChangelogUrl(context, pullRequest.headRepo, pullRequest.headRef, changelogFilename());
179
- const pendingPackages = [];
180
- const lines = [
181
- "### Tegami",
182
- "",
183
- `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.`,
184
- "",
185
- `[**Create a changelog →**](${createLink}) · [Changelog format](https://tegami.fuma-nama.dev/changelog)`,
186
- ""
187
- ];
188
- for (const pkg of context.graph.getPackages()) {
189
- const plan = draft.getPackageDraft(pkg.id);
190
- if (!plan) continue;
191
- const bumped = plan.bumpVersion(pkg);
192
- if (!bumped || !pkg.version || bumped === pkg.version) continue;
193
- pendingPackages.push({
194
- name: pkg.name,
195
- type: plan.type ?? "—",
196
- from: pkg.version,
197
- to: bumped,
198
- distTag: plan.npm?.distTag
199
- });
200
- }
201
- const requestChangelogs = draft.getChangelogs().filter((entry) => changelogFiles.has(entry.filename));
202
- if (pendingPackages.length > 0) {
203
- lines.push("#### Release preview", "", "| Package | Bump | Version |", "| --- | --- | --- |");
204
- for (const { name, type, from, to, distTag } of pendingPackages) lines.push(`| \`${name}\` | ${type} | \`${from}\` → \`${to}\`${formatNpmDistTag(distTag)} |`);
205
- lines.push("");
206
- }
207
- if (requestChangelogs.length > 0) {
208
- lines.push("#### Changelogs in this PR", "", "| Changelog | Title |", "| --- | --- |");
209
- for (const entry of requestChangelogs) for (const section of entry.sections) lines.push(`| \`${entry.filename}\` | ${section.title} |`);
210
- lines.push("");
211
- } else if (pendingPackages.length === 0) lines.push("#### No changelogs yet", "", "This PR has no pending changelog files. If your changes require a release, add a changelog before merging.", "");
212
- else if (changelogFiles.size === 0) lines.push("This PR does not add changelog files. Pending changelogs from other branches are included in the preview above.", "");
213
- lines.push(`Run \`${tegamiCommand}\` locally to create a changelog interactively.`, "", `<sub>Managed by [Tegami](https://tegami.fuma-nama.dev).</sub>`, "");
214
- return lines.join("\n");
173
+ return formatPreview(context, draft, await listPullRequestChangelogFiles(context, pullRequest.baseSha, pullRequest.headSha), {
174
+ "create-a-changelog-href": createChangelogUrl(context, pullRequest.headRepo, pullRequest.headRef, changelogFilename()),
175
+ pr: "PR"
176
+ });
215
177
  }
216
178
  async function postPrComment(context, body) {
217
179
  const { repo, token } = context.github ?? {};
@@ -236,7 +198,6 @@ async function resolvePullRequest(context, options) {
236
198
  const { repo, token } = context.github ?? {};
237
199
  if (!repo) throw new Error("GitHub plugin context is required.");
238
200
  if (options.number !== void 0) {
239
- parsePositiveInt(String(options.number), "--number");
240
201
  const data = await getPullRequest(repo, options.number, token);
241
202
  return {
242
203
  headRepo: data.headRepository ? `${data.headRepository.owner.login}/${data.headRepository.name}` : repo,
@@ -347,201 +308,112 @@ function parsePositiveInt(value, option) {
347
308
  /** Create GitHub releases for successfully published packages after the whole plan succeeds. */
348
309
  function github(options = {}) {
349
310
  const { release: releaseOptions = true } = options;
350
- let renderer;
351
- function getRenderer(context) {
352
- return renderer ??= createChangelogRenderer(context);
353
- }
354
- const versionRequests = onVersionRequest({
355
- name: "github",
356
- options: options.versionPr,
357
- canCreate(context) {
358
- const { repo, token } = context.github ?? {};
359
- return Boolean(repo && token);
360
- },
361
- async upsert(context, request, update) {
362
- const { repo, token } = context.github;
363
- const openPr = await findOpenPullRequest(repo, request.head, token);
364
- if (openPr === void 0) await createPullRequest(repo, {
365
- title: request.title,
366
- body: request.body,
367
- head: request.head,
368
- base: request.base,
369
- token
370
- });
371
- else if (update) await updatePullRequest(repo, openPr, {
372
- title: request.title,
373
- body: request.body,
374
- token
375
- });
376
- }
377
- });
378
- const plugin = {
379
- ...versionRequests,
380
- name: "github",
381
- init() {
382
- this.github = {
383
- repo: options.repo ?? process.env.GITHUB_REPOSITORY,
384
- token: options.token ?? process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN
385
- };
386
- },
387
- async resolvePlanStatus({ plan }) {
388
- if (versionRequests.resolvePlanStatus.call(this, { plan }) === "pending") return "pending";
389
- const { repo, token } = this.github;
390
- if (!repo || !token || releaseOptions === false) return;
391
- const requiredTags = /* @__PURE__ */ new Set();
392
- for (const pkg of plan.packages.values()) if (pkg.preflight.shouldPublish && pkg.git?.tag) requiredTags.add(pkg.git.tag);
393
- return Array.from(requiredTags, async (tag) => {
394
- if (!await releaseExistsByTag(repo, tag, token)) return "pending";
395
- });
396
- },
397
- async afterPublishAll({ plan }) {
398
- const { repo, token } = this.github;
399
- if (!repo || !token || releaseOptions === false) return;
400
- const { eager = false, create, createGrouped } = releaseOptions === true ? {} : releaseOptions;
401
- const groups = /* @__PURE__ */ new Map();
402
- for (const [id, { preflight, publishResult, git }] of plan.packages) {
403
- if (!eager && publishResult.type === "failed") return;
404
- const tag = git?.tag;
405
- if (!tag || !preflight.shouldPublish) continue;
406
- const pkg = this.graph.get(id);
407
- const group = groups.get(tag);
408
- if (group) group.push(pkg);
409
- else groups.set(tag, [pkg]);
410
- }
411
- await Promise.all(Array.from(groups, async ([tag, packages]) => {
412
- for (const member of packages) if (plan.packages.get(member.id).publishResult.type === "failed") return;
413
- if (await releaseExistsByTag(repo, tag, token)) return;
414
- let release;
415
- if (packages.length > 1) {
416
- const overrides = await createGrouped?.call(this, {
417
- tag,
418
- packages,
419
- plan
420
- }) ?? {};
421
- release = {
422
- title: overrides.title ?? tag,
423
- notes: overrides.notes ?? await defaultGroupedNotes(getRenderer(this), plan, packages),
424
- prerelease: overrides.prerelease ?? packages.some((pkg) => pkg.version && semver.prerelease(pkg.version))
425
- };
426
- } else {
427
- const pkg = packages[0];
428
- const overrides = await create?.call(this, {
429
- tag,
430
- pkg,
431
- plan
432
- }) ?? {};
433
- const packagePlan = plan.packages.get(pkg.id);
434
- release = {
435
- title: overrides.title ?? formatPackageVersion(pkg.name, pkg.version, packagePlan?.npm?.distTag),
436
- notes: overrides.notes ?? await defaultNotes(getRenderer(this), pkg, packagePlan),
437
- prerelease: overrides.prerelease ?? (pkg.version !== void 0 && semver.prerelease(pkg.version) !== null)
438
- };
311
+ let autoRelease;
312
+ return [
313
+ git(options),
314
+ {
315
+ name: "github",
316
+ init() {
317
+ const { repo, token } = this.github = {
318
+ repo: options.repo ?? process.env.GITHUB_REPOSITORY,
319
+ token: options.token ?? process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN
320
+ };
321
+ if (repo && token && releaseOptions !== false) {
322
+ const { eager = false, create, createGrouped } = releaseOptions === true ? {} : releaseOptions;
323
+ const resolveEntryMeta = cached((entry) => entry.id, async (entry) => {
324
+ const commit = await resolveFileCommit(this, entry.filename);
325
+ if (!commit) return {
326
+ commit,
327
+ pullRequests: []
328
+ };
329
+ return {
330
+ commit,
331
+ pullRequests: await listPullRequestsForCommit(repo, commit, token).catch(() => [])
332
+ };
333
+ });
334
+ autoRelease = createAutoRelease({
335
+ eager,
336
+ override: create,
337
+ overrideGroup: createGrouped,
338
+ async formatChangelog(entry) {
339
+ const meta = await resolveEntryMeta(entry);
340
+ const lines = [];
341
+ const commitSuffix = meta.commit ? ` ([${meta.commit.slice(0, 7)}](https://github.com/${repo}/commit/${meta.commit}))` : "";
342
+ for (const section of entry.sections) {
343
+ lines.push(`### ${section.title}${commitSuffix}`, "");
344
+ if (section.content) lines.push(section.content, "");
345
+ }
346
+ if (meta.pullRequests.length > 0) {
347
+ lines.push("<details>", "<summary>Pull request & contributors</summary>", "");
348
+ for (const pr of meta.pullRequests) {
349
+ let line = `- [#${pr.number} ${pr.title}](https://github.com/${repo}/pull/${pr.number})`;
350
+ if (pr.user) line += ` by @${pr.user.login}`;
351
+ lines.push(line);
352
+ }
353
+ lines.push("", "</details>");
354
+ }
355
+ return lines.join("\n").trim();
356
+ },
357
+ create({ input, packages, tag }) {
358
+ return createRelease({
359
+ ...input,
360
+ repo,
361
+ tag,
362
+ token,
363
+ prerelease: input.prerelease ?? packages.some((pkg) => pkg.version && semver.prerelease(pkg.version))
364
+ });
365
+ },
366
+ releaseExistsByTag(tag) {
367
+ return releaseExistsByTag(repo, tag, token);
368
+ }
369
+ });
439
370
  }
440
- await createRelease(repo, {
441
- tag,
442
- title: release.title,
443
- notes: release.notes,
444
- prerelease: release.prerelease,
371
+ },
372
+ async resolvePlanStatus({ plan }) {
373
+ if (await autoRelease?.hasPending.call(this, plan)) return "pending";
374
+ },
375
+ async afterPublishAll({ plan }) {
376
+ await autoRelease?.create.call(this, plan);
377
+ },
378
+ async initCli(cli) {
379
+ registerPrCli(cli);
380
+ if (!isCI()) return;
381
+ const { repo, token } = this.github ?? {};
382
+ if (!token || !repo) return;
383
+ const result = await x("git", [
384
+ "remote",
385
+ "set-url",
386
+ "origin",
387
+ `https://x-access-token:${token}@github.com/${repo}.git`
388
+ ], { nodeOptions: { cwd: this.cwd } });
389
+ if (result.exitCode !== 0) throw execFailure("Failed to configure git remote for GitHub Actions.", result);
390
+ }
391
+ },
392
+ versionRequestPlugin({
393
+ name: "github",
394
+ options: options.versionPr,
395
+ canCreate(context) {
396
+ const { repo, token } = context.github ?? {};
397
+ return Boolean(repo && token);
398
+ },
399
+ async upsert(context, request, update) {
400
+ const { repo, token } = context.github;
401
+ const openPr = await findOpenPullRequest(repo, request.head, token);
402
+ if (openPr === void 0) await createPullRequest(repo, {
403
+ title: request.title,
404
+ body: request.body,
405
+ head: request.head,
406
+ base: request.base,
445
407
  token
446
408
  });
447
- }));
448
- },
449
- async initCli(cli) {
450
- registerPrCli(cli);
451
- if (!isCI()) return;
452
- const { repo, token } = this.github ?? {};
453
- if (!token || !repo) return;
454
- const result = await x("git", [
455
- "remote",
456
- "set-url",
457
- "origin",
458
- `https://x-access-token:${token}@github.com/${repo}.git`
459
- ], { nodeOptions: { cwd: this.cwd } });
460
- if (result.exitCode !== 0) throw execFailure("Failed to configure git remote for GitHub Actions.", result);
461
- }
462
- };
463
- return [git(options), plugin];
464
- }
465
- function createChangelogRenderer(context) {
466
- const { repo, token } = context.github;
467
- const resolveFileCommit = cached((filename) => filename, async (filename) => {
468
- const result = await x("git", [
469
- "log",
470
- "--diff-filter=A",
471
- "-1",
472
- "--format=%H",
473
- "--",
474
- relative(context.cwd, join(context.changelogDir, filename))
475
- ], { nodeOptions: { cwd: context.cwd } });
476
- if (result.exitCode !== 0) return;
477
- return result.stdout.trim() || void 0;
478
- });
479
- const resolveEntryMeta = cached((entry) => entry.id, async (entry) => {
480
- const commit = await resolveFileCommit(entry.filename);
481
- if (!commit || !repo) return {
482
- commit,
483
- pullRequests: []
484
- };
485
- return {
486
- commit,
487
- pullRequests: await listPullRequestsForCommit(repo, commit, token).catch(() => [])
488
- };
489
- });
490
- function formatEntryDetails(meta) {
491
- if (meta.pullRequests.length === 0) return;
492
- const lines = [];
493
- for (const pr of meta.pullRequests) {
494
- let line = repo ? `- [#${pr.number} ${pr.title}](https://github.com/${repo}/pull/${pr.number})` : `- #${pr.number} ${pr.title}`;
495
- if (pr.user) line += ` by @${pr.user.login}`;
496
- lines.push(line);
497
- }
498
- return [
499
- "<details>",
500
- "<summary>Pull request & contributors</summary>",
501
- "",
502
- ...lines,
503
- "",
504
- "</details>"
505
- ].join("\n");
506
- }
507
- return async (entry) => {
508
- const meta = await resolveEntryMeta(entry);
509
- let commitSuffix = "";
510
- if (meta.commit) {
511
- const short = meta.commit.slice(0, 7);
512
- const link = repo ? `[${short}](https://github.com/${repo}/commit/${meta.commit})` : `\`${short}\``;
513
- commitSuffix += ` (${link})`;
514
- }
515
- const lines = [];
516
- for (const section of entry.sections) {
517
- lines.push(`### ${section.title}${commitSuffix}`, "");
518
- if (section.content) lines.push(section.content, "");
519
- }
520
- const details = formatEntryDetails(meta);
521
- if (details) lines.push(details);
522
- return lines.join("\n").trim();
523
- };
524
- }
525
- async function defaultNotes(renderer, pkg, packagePlan) {
526
- if (packagePlan && packagePlan.changelogs.length > 0) return (await Promise.all(packagePlan.changelogs.map(renderer))).join("\n\n");
527
- return `Published ${formatPackageVersion(pkg.name, pkg.version, packagePlan?.npm?.distTag)}.`;
528
- }
529
- async function defaultGroupedNotes(renderer, plan, packages) {
530
- const changelogs = /* @__PURE__ */ new Map();
531
- for (const pkg of packages) {
532
- const packagePlan = plan.packages.get(pkg.id);
533
- if (!packagePlan) continue;
534
- for (const entry of packagePlan.changelogs) changelogs.set(entry.id, entry);
535
- }
536
- const sections = [packages.map((pkg) => {
537
- const packagePlan = plan.packages.get(pkg.id);
538
- return `- ${formatPackageVersion(pkg.name, pkg.version, packagePlan?.npm?.distTag)}`;
539
- }).join("\n")];
540
- if (changelogs.size > 0) {
541
- const notes = await Promise.all(Array.from(changelogs.values(), renderer));
542
- sections.push("", notes.join("\n\n"));
543
- }
544
- return sections.join("\n");
409
+ else if (update) await updatePullRequest(repo, openPr, {
410
+ title: request.title,
411
+ body: request.body,
412
+ token
413
+ });
414
+ }
415
+ })
416
+ ];
545
417
  }
546
418
  //#endregion
547
419
  export { github };
@@ -1,13 +1,13 @@
1
- import { A as WorkspacePackage, b as TegamiContext, s as TegamiPlugin, t as Awaitable, v as PublishPlan } from "../types-C_vz41r2.js";
1
+ import { j as WorkspacePackage, s as TegamiPlugin, t as Awaitable, x as TegamiContext, y as PublishPlan } from "../types-BMYzG4dR.js";
2
2
  import { GitPluginOptions } from "./git.js";
3
- import { t as VersionRequestOptions } from "../version-request-DXk_B7O_.js";
3
+ import { t as VersionRequestOptions } from "../version-request-BorZZ98V.js";
4
4
 
5
5
  //#region src/plugins/gitlab.d.ts
6
6
  interface GitlabRelease {
7
7
  /** Release title */
8
- title?: string;
8
+ title: string;
9
9
  /** Release notes */
10
- notes?: string;
10
+ notes: string;
11
11
  }
12
12
  /** Options for creating GitLab releases after a successful publish. */
13
13
  interface GitLabPluginOptions extends GitPluginOptions {
@@ -35,12 +35,12 @@ interface GitLabPluginOptions extends GitPluginOptions {
35
35
  tag: string;
36
36
  pkg: WorkspacePackage;
37
37
  plan: PublishPlan;
38
- }) => Awaitable<GitlabRelease>; /** Override release details when multiple packages share a git tag. */
38
+ }) => Awaitable<Partial<GitlabRelease>>; /** Override release details when multiple packages share a git tag. */
39
39
  createGrouped?: (this: TegamiContext, opts: {
40
40
  tag: string;
41
41
  packages: WorkspacePackage[];
42
42
  plan: PublishPlan;
43
- }) => Awaitable<GitlabRelease>;
43
+ }) => Awaitable<Partial<GitlabRelease>>;
44
44
  };
45
45
  /**
46
46
  * (CLI only) Open a version merge request after versioning.