@peiyanlu/release 0.0.7 → 0.0.9

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/README.md CHANGED
@@ -296,18 +296,63 @@ GitHub Release 可基于 Git Tag 自动创建,并支持附带:
296
296
  当 Tag 推送到远端后,CI/CD 自动执行:
297
297
 
298
298
  - 发布到 npm
299
- - 创建 GItHub release
299
+ - 创建 GitHub Release
300
300
 
301
+ ### 示例用法
302
+
303
+ - 发布到 npm
301
304
  ```ts
302
305
  // publishCI.ts
306
+
303
307
  import { publishTagToNpm } from '@peiyanlu/release'
308
+ await publishTagToNpm({})
309
+ ```
304
310
 
311
+ ```json5
312
+ // package.json
305
313
 
306
- await publishTagToNpm({
307
- gitTag: '1.0.16',
308
- getPkgDir: () => '.',
309
- defaultPackage: '.',
310
- })
314
+ {
315
+ "scripts": {
316
+ "ci-publish": "tsx src/publishCI.ts"
317
+ }
318
+ }
319
+ ```
320
+
321
+ ```yaml
322
+ # .github/workflows/publish.yml
323
+
324
+ jobs:
325
+ publish:
326
+ name: Publish
327
+ runs-on: ubuntu-latest
328
+
329
+ steps:
330
+ - name: Publish
331
+ run: npm i -g npm@^11.5.2 && pnpm run ci-publish "$REF_NAME"
332
+ env:
333
+ REF_NAME: ${{ github.ref_name }}
334
+ ```
335
+
336
+ - 创建 GitHub Release
337
+ ```yaml
338
+ # .github/workflows/release.yml
339
+
340
+ jobs:
341
+ release:
342
+ name: Release
343
+ runs-on: ubuntu-latest
344
+
345
+ steps:
346
+ - name: Release
347
+ uses: peiyanlu/release
348
+ env:
349
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
350
+ with:
351
+ tag_name: ${{ github.ref_name }}
352
+ release_name: Release ${{ github.ref_name }}
353
+ body: |
354
+ Please refer to [CHANGELOG.md](./CHANGELOG.md) for details.
355
+ draft: false
311
356
  ```
312
357
 
313
358
  ## Dry Run
package/dist/cli.mjs CHANGED
@@ -1,13 +1,13 @@
1
1
  import path, { join, resolve } from "node:path";
2
2
  import { fileURLToPath, pathToFileURL } from "node:url";
3
- import { bumpPackageVersion, coloredChangeset, eol, execAsync, getAllRemotes, getAuthenticatedUser, getCurrentBranch, getGithubReleaseUrl, getGithubUrl, getLatestTag, getLog, getPackageInfo, getPackageUrl, getPublishedVersion, getRemote, getStatus, gitAddAll, gitAddTracked, gitCommit, gitTagAnnotated, hasWriteAccess, isGitRepo, isPrerelease, isValid, isWorkingDirClean, parseGitHubRepo, parseVersion, pingRegistry, publishPackage, pushBranch, pushTag, readJsonFile, resolveChangelogRange } from "@peiyanlu/cli-utils";
3
+ import { bumpPackageVersion, coloredChangeset, eol, execAsync, getAllRemotes, getAuthenticatedUser, getCurrentBranch, getGithubReleaseUrl, getGithubUrl, getLatestTag, getLog, getPackageInfo, getPackageUrl, getPublishedVersion, getRemote, getStatus, gitAddAll, gitAddTracked, gitCommit, gitTagAnnotated, hasWriteAccess, isGitRepo, isOtpError, isPrerelease, isValid, isWorkingDirClean, parseGitHubRepo, parseVersion, pingRegistry, publishPackage, pushBranch, pushTag, readJsonFile, resolveChangelogRange, resolvePublishTag } from "@peiyanlu/cli-utils";
4
4
  import { dim, green, red, rgb, underline, yellow } from "ansis";
5
5
  import { program } from "commander";
6
6
  import { createReadStream, createWriteStream, existsSync, readFileSync, statSync, writeFileSync } from "node:fs";
7
7
  import { cancel, confirm, group, intro, isCancel, log, outro, select, tasks, text } from "@clack/prompts";
8
8
  import { publint } from "publint";
9
9
  import { formatMessage } from "publint/utils";
10
- import { inc, lt, neq } from "semver";
10
+ import { inc, neq } from "semver";
11
11
  import { castArray, isFunction, isPlainObject, isUndefined } from "@peiyanlu/ts-utils";
12
12
  import { spawnSync } from "node:child_process";
13
13
  import { inspect } from "node:util";
@@ -19,12 +19,10 @@ import { Octokit } from "@octokit/rest";
19
19
  import { contentType } from "mime-types";
20
20
  import open from "open";
21
21
  import { glob } from "tinyglobby";
22
-
23
- //#region node_modules/.pnpm/tsdown@0.18.4_publint@0.3.17_typescript@5.9.3/node_modules/tsdown/esm-shims.js
22
+ //#region node_modules/.pnpm/tsdown@0.21.7_publint@0.3.18_typescript@6.0.2/node_modules/tsdown/esm-shims.js
24
23
  const getFilename = () => fileURLToPath(import.meta.url);
25
24
  const getDirname = () => path.dirname(getFilename());
26
25
  const __dirname = /* @__PURE__ */ getDirname();
27
-
28
26
  //#endregion
29
27
  //#region src/config.ts
30
28
  const findConfigFile = (cwd = process.cwd()) => {
@@ -34,8 +32,8 @@ const findConfigFile = (cwd = process.cwd()) => {
34
32
  "js",
35
33
  "mjs"
36
34
  ]) {
37
- const path$1 = resolve(cwd, `release.config.${ext}`);
38
- if (existsSync(path$1)) return path$1;
35
+ const path = resolve(cwd, `release.config.${ext}`);
36
+ if (existsSync(path)) return path;
39
37
  }
40
38
  };
41
39
  const loadConfig = async (file) => {
@@ -70,7 +68,6 @@ const mergeConfig = (defaults, overrides) => {
70
68
  }
71
69
  return result;
72
70
  };
73
-
74
71
  //#endregion
75
72
  //#region src/messages.ts
76
73
  const n = (b) => b ? "(dry run)" : "";
@@ -93,11 +90,11 @@ const MSG = {
93
90
  },
94
91
  NPM: {
95
92
  CHECKING: "Checking npm registry",
96
- CHECKED: (registry, msg$1) => `NPM registry: ${underline(dim(registry))} ${underline(dim(msg$1))}`
93
+ CHECKED: (registry, msg) => `NPM registry: ${underline(dim(registry))} ${underline(dim(msg))}`
97
94
  },
98
95
  GITHUB: {
99
96
  CHECKING: "Checking github repository",
100
- CHECKED: (repository, msg$1) => `GitHub repository: ${underline(dim(repository))} ${underline(dim(msg$1))}`
97
+ CHECKED: (repository, msg) => `GitHub repository: ${underline(dim(repository))} ${underline(dim(msg))}`
101
98
  }
102
99
  },
103
100
  TASK: {
@@ -126,11 +123,11 @@ const MSG = {
126
123
  SELECT_PACKAGE: "Select package release:",
127
124
  SELECT_VERSION: "Select version bump:",
128
125
  INPUT_VERSION: "Enter custom version:",
129
- NPM_PUBLISH: (pkg$1) => `Publish to npm ${underline(dim`(${pkg$1})`)}?`,
126
+ NPM_PUBLISH: (pkg) => `Publish to npm ${underline(dim`(${pkg})`)}?`,
130
127
  NPM_OTP: "Enter npm one-time password (OTP):",
131
128
  GITHUB_RELEASE: (title) => `Create a new GitHub release ${underline(dim`(${title})`)}?`,
132
- GIT_COMMIT: (msg$1) => `Create git commit ${underline(dim`(${msg$1})`)}?`,
133
- GIT_TAG: (msg$1) => `Create git tag ${underline(dim`(${msg$1})`)}?`,
129
+ GIT_COMMIT: (msg) => `Create git commit ${underline(dim`(${msg})`)}?`,
130
+ GIT_TAG: (msg) => `Create git tag ${underline(dim`(${msg})`)}?`,
134
131
  GIT_PUSH: "Push commits and tags to remote?"
135
132
  },
136
133
  ERROR: {
@@ -152,10 +149,9 @@ const MSG = {
152
149
  },
153
150
  INFO: {
154
151
  TOOL: (name, version) => `${name} ${dim(`v${version}`)}`,
155
- CONFIG: (path$1) => `config file: ${underline(dim(path$1 || "not found"))}`
152
+ CONFIG: (path) => `config file: ${underline(dim(path || "not found"))}`
156
153
  }
157
154
  };
158
-
159
155
  //#endregion
160
156
  //#region src/git/commit.ts
161
157
  const gitCheck = async (ctx, config) => {
@@ -197,9 +193,9 @@ const commitAndTag = async (ctx, config) => {
197
193
  }
198
194
  if (push) {
199
195
  const remotes = await getAllRemotes();
200
- for (const remoteName$1 of remotes) {
201
- await pushTag(remoteName$1, currentTag, args);
202
- await pushBranch(remoteName$1, await getCurrentBranch(), [...pushArgs, ...args]);
196
+ for (const remoteName of remotes) {
197
+ await pushTag(remoteName, currentTag, args);
198
+ await pushBranch(remoteName, await getCurrentBranch(), [...pushArgs, ...args]);
203
199
  }
204
200
  if (!dryRun) Object.assign(ctx.git, { isPushed: true });
205
201
  }
@@ -219,11 +215,10 @@ const gitRollback = (ctx) => {
219
215
  isCommitted ? "HEAD~1" : "HEAD"
220
216
  ]);
221
217
  };
222
-
223
218
  //#endregion
224
219
  //#region src/prompts.ts
225
- const abortTask = (msg$1) => {
226
- cancel(`${red("✕")} ${msg$1}`);
220
+ const abortTask = (msg) => {
221
+ cancel(`${red("✕")} ${msg}`);
227
222
  process.exit(0);
228
223
  };
229
224
  const abortSinglePrompt = (value) => {
@@ -235,34 +230,33 @@ const abortGroupPrompt = (ctx) => {
235
230
  };
236
231
  const abortOnError = (err, ctx) => {
237
232
  ctx && gitRollback(ctx);
238
- const msg$1 = err.message.replace(/^\[(github|npm|git)]/, (a) => red(a));
239
- log.message(`\n${msg$1}\n`);
233
+ const msg = err.message.replace(/^\[(github|npm|git)]/, (a) => red(a));
234
+ log.message(`\n${msg}\n`);
240
235
  process.exit(1);
241
236
  };
242
- const taskEnd = (msg$1) => {
243
- outro(msg$1);
237
+ const taskEnd = (msg) => {
238
+ outro(msg);
244
239
  process.exit(0);
245
240
  };
246
-
247
241
  //#endregion
248
242
  //#region src/utils.ts
249
- const info = (msg$1) => {
250
- console.log(`${rgb(33, 91, 184)(`i`)} ${msg$1}`);
243
+ const info = (msg) => {
244
+ console.log(`${rgb(33, 91, 184)(`i`)} ${msg}`);
251
245
  };
252
- const msg = (prefix, msg$1) => {
253
- log.message(`${rgb(33, 91, 184)(`[${prefix}]`)} ${dim(msg$1)}`);
246
+ const msg = (prefix, msg) => {
247
+ log.message(`${rgb(33, 91, 184)(`[${prefix}]`)} ${dim(msg)}`);
254
248
  };
255
- const question = (msg$1, type) => {
249
+ const question = (msg, type) => {
256
250
  return `${{
257
251
  package: yellow,
258
252
  version: green,
259
253
  git: rgb(220, 94, 62),
260
254
  npm: rgb(186, 70, 61),
261
255
  github: rgb(64, 110, 228)
262
- }[type]`?`} ${msg$1}`;
256
+ }[type]`?`} ${msg}`;
263
257
  };
264
- const success = (msg$1, dryRun) => {
265
- return `${(dryRun ? rgb(123, 115, 66) : green)("✔")} ${msg$1}`;
258
+ const success = (msg, dryRun) => {
259
+ return `${(dryRun ? rgb(123, 115, 66) : green)("✔")} ${msg}`;
266
260
  };
267
261
  const runLifeCycleHook = async (hooks, key, dryRun) => {
268
262
  const handler = hooks[key];
@@ -297,32 +291,31 @@ const formatTemplate = async (ctx, config) => {
297
291
  });
298
292
  Object.assign(ctx.github, { releaseName });
299
293
  };
300
-
301
294
  //#endregion
302
295
  //#region src/version/prompts.ts
303
- let Release = /* @__PURE__ */ function(Release$1) {
304
- Release$1["MAJOR"] = "major";
305
- Release$1["MINOR"] = "minor";
306
- Release$1["PATCH"] = "patch";
307
- Release$1["RELEASE"] = "release";
308
- return Release$1;
296
+ let Release = /* @__PURE__ */ function(Release) {
297
+ Release["MAJOR"] = "major";
298
+ Release["MINOR"] = "minor";
299
+ Release["PATCH"] = "patch";
300
+ Release["RELEASE"] = "release";
301
+ return Release;
309
302
  }({});
310
- let PreRelease = /* @__PURE__ */ function(PreRelease$1) {
311
- PreRelease$1["MAJOR"] = "premajor";
312
- PreRelease$1["MINOR"] = "preminor";
313
- PreRelease$1["PATCH"] = "prepatch";
314
- PreRelease$1["RELEASE"] = "prerelease";
315
- return PreRelease$1;
303
+ let PreRelease = /* @__PURE__ */ function(PreRelease) {
304
+ PreRelease["MAJOR"] = "premajor";
305
+ PreRelease["MINOR"] = "preminor";
306
+ PreRelease["PATCH"] = "prepatch";
307
+ PreRelease["RELEASE"] = "prerelease";
308
+ return PreRelease;
316
309
  }({});
317
- let PreId = /* @__PURE__ */ function(PreId$1) {
318
- PreId$1["ALPHA"] = "alpha";
319
- PreId$1["BETA"] = "beta";
320
- PreId$1["RC"] = "rc";
321
- PreId$1["NET"] = "next";
322
- PreId$1["CANARY"] = "canary";
323
- PreId$1["NIGHT"] = "nightly";
324
- PreId$1["DEV"] = "dev";
325
- return PreId$1;
310
+ let PreId = /* @__PURE__ */ function(PreId) {
311
+ PreId["ALPHA"] = "alpha";
312
+ PreId["BETA"] = "beta";
313
+ PreId["RC"] = "rc";
314
+ PreId["NET"] = "next";
315
+ PreId["CANARY"] = "canary";
316
+ PreId["NIGHT"] = "nightly";
317
+ PreId["DEV"] = "dev";
318
+ return PreId;
326
319
  }({});
327
320
  const createVersionMap = (current) => ({
328
321
  patch: inc(current, Release.PATCH),
@@ -375,14 +368,13 @@ const runVersionPrompts = async (ctx, config) => {
375
368
  abortSinglePrompt(version);
376
369
  return version;
377
370
  };
378
- const resolveNextVersion = async (type, current$1) => {
379
- if (type === "ignore") return current$1;
371
+ const resolveNextVersion = async (type, current) => {
372
+ if (type === "ignore") return current;
380
373
  if (type === "custom") return inputVersion();
381
- return createVersionMap(current$1)[type];
374
+ return createVersionMap(current)[type];
382
375
  };
383
376
  return await resolveNextVersion(await selectVersion(), current);
384
377
  };
385
-
386
378
  //#endregion
387
379
  //#region src/defaults.ts
388
380
  const createDefaultContext = () => {
@@ -460,10 +452,10 @@ const createDefaultConfig = (isCI) => {
460
452
  },
461
453
  isMonorepo: false,
462
454
  packages: [],
463
- getPkgDir(pkg$1) {
455
+ getPkgDir(pkg) {
464
456
  return ".";
465
457
  },
466
- toTag(pkg$1, version) {
458
+ toTag(pkg, version) {
467
459
  return `v${version}`;
468
460
  },
469
461
  tagPrefix: void 0,
@@ -498,7 +490,6 @@ const createDefaultConfig = (isCI) => {
498
490
  }
499
491
  };
500
492
  };
501
-
502
493
  //#endregion
503
494
  //#region src/git/changetype.ts
504
495
  const defaultTypes = [
@@ -593,13 +584,11 @@ const defaultTypes = [
593
584
  description: "紧急修复"
594
585
  }
595
586
  ];
596
-
597
587
  //#endregion
598
588
  //#region src/git/changelog.ts
599
- const createGenerator = async ({ getPkgDir, tagPrefix }) => {
600
- const pkgDir = getPkgDir();
601
- const preset = await createPreset({ types: defaultTypes.map((t$1) => ({
602
- ...t$1,
589
+ const parsePreset = async () => {
590
+ const preset = await createPreset({ types: defaultTypes.map((t) => ({
591
+ ...t,
603
592
  hidden: false
604
593
  })) });
605
594
  preset.writer ??= {};
@@ -650,6 +639,11 @@ const createGenerator = async ({ getPkgDir, tagPrefix }) => {
650
639
  {{> commit root=@root}}
651
640
  {{/each}}
652
641
  {{/each}}`.trim() + eol(2);
642
+ return preset;
643
+ };
644
+ const createGenerator = async ({ getPkgDir, tagPrefix }) => {
645
+ const pkgDir = getPkgDir();
646
+ const preset = await parsePreset();
653
647
  return new ConventionalChangelog().readPackage(`${pkgDir}/package.json`).config(preset).options({ releaseCount: 1 }).commits({ path: pkgDir }).tags({ prefix: tagPrefix });
654
648
  };
655
649
  const getChangelog = async ({ getPkgDir, tagPrefix }) => {
@@ -675,7 +669,6 @@ const generateChangelog = async ({ getPkgDir, tagPrefix }) => {
675
669
  writeStream.end();
676
670
  await finished(writeStream);
677
671
  };
678
-
679
672
  //#endregion
680
673
  //#region src/git/prompts.ts
681
674
  const runGitPrompts = async (ctx, config) => {
@@ -711,7 +704,6 @@ const runGitPrompts = async (ctx, config) => {
711
704
  } });
712
705
  Object.assign(config.git, reset);
713
706
  };
714
-
715
707
  //#endregion
716
708
  //#region src/github/prompts.ts
717
709
  const runGithubPrompts = async (ctx, config) => {
@@ -734,7 +726,6 @@ const runGithubPrompts = async (ctx, config) => {
734
726
  Object.assign(config.github, { release: res.release });
735
727
  return res;
736
728
  };
737
-
738
729
  //#endregion
739
730
  //#region src/github/release.ts
740
731
  const truncateBody = (body) => {
@@ -900,7 +891,6 @@ const createRelease = async (ctx, config) => {
900
891
  }
901
892
  }
902
893
  };
903
-
904
894
  //#endregion
905
895
  //#region src/npm/prompts.ts
906
896
  const runNpmPublishPrompts = async (ctx, config) => {
@@ -931,17 +921,8 @@ const runNpmOptPrompts = async (ctx, config) => {
931
921
  Object.assign(ctx.npm, { otp: res.otp });
932
922
  return res;
933
923
  };
934
-
935
924
  //#endregion
936
925
  //#region src/npm/publish.ts
937
- const resolvePublishTag = async (pkgName, version) => {
938
- const { isPrerelease: isPrerelease$1, preId } = parseVersion(version);
939
- if (isPrerelease$1) return preId || "next";
940
- const active = await getPublishedVersion(pkgName);
941
- if (!active) return "latest";
942
- return lt(version, active) ? "previous" : "latest";
943
- };
944
- const isOtpError = (err) => err instanceof Error && /one-time password|otp/i.test(err.message);
945
926
  const npmCheck = async (ctx, config) => {
946
927
  const { pkg: { name, current, publishConfig: { registry } } } = ctx;
947
928
  const { npm: { skipChecks } } = config;
@@ -974,7 +955,6 @@ const publishNpm = async (ctx, config) => {
974
955
  cwd: getPkgDir(selectedPkg)
975
956
  });
976
957
  };
977
-
978
958
  //#endregion
979
959
  //#region src/action.ts
980
960
  var Action = class {
@@ -1016,19 +996,19 @@ var Action = class {
1016
996
  } else if (packages.length < 1) abortTask(MSG.ABORT.MONOREPO_NO_PACKAGES);
1017
997
  }
1018
998
  const selectPackage = async () => {
1019
- const pkg$2 = await select({
999
+ const pkg = await select({
1020
1000
  message: question(MSG.PROMPT.SELECT_PACKAGE, "package"),
1021
- options: packages.map((pkg$3) => ({
1022
- label: pkg$3,
1023
- value: pkg$3
1001
+ options: packages.map((pkg) => ({
1002
+ label: pkg,
1003
+ value: pkg
1024
1004
  }))
1025
1005
  });
1026
- abortSinglePrompt(pkg$2);
1027
- return pkg$2;
1006
+ abortSinglePrompt(pkg);
1007
+ return pkg;
1028
1008
  };
1029
1009
  const selectedPkg = !isMonorepo ? "" : ci ? defPkg : packages.length === 1 ? packages[0] : await selectPackage();
1030
- const { pkg: pkg$1, pkgDir } = getPackageInfo(selectedPkg, getPkgDir);
1031
- const { version: pkgVersion, private: pkgPrivate = false, name: pkgName, publishConfig = {} } = pkg$1;
1010
+ const { pkg, pkgDir } = getPackageInfo(selectedPkg, getPkgDir);
1011
+ const { version: pkgVersion, private: pkgPrivate = false, name: pkgName, publishConfig = {} } = pkg;
1032
1012
  const nextVersion = inc(pkgVersion, cmdArgs) ?? "";
1033
1013
  const ctx = mergeConfig(createDefaultContext(), {
1034
1014
  selectedPkg,
@@ -1059,7 +1039,7 @@ var Action = class {
1059
1039
  });
1060
1040
  const { messages } = await publint({ pkgDir });
1061
1041
  for (const message of messages) {
1062
- const formated = formatMessage(message, pkg$1);
1042
+ const formated = formatMessage(message, pkg);
1063
1043
  formated && msg("PKG", formated);
1064
1044
  }
1065
1045
  return {
@@ -1081,19 +1061,19 @@ var Action = class {
1081
1061
  {
1082
1062
  title: MSG.CHECK.NPM.CHECKING,
1083
1063
  task: async () => {
1084
- const msg$1 = await npmCheck(ctx, config);
1064
+ const msg = await npmCheck(ctx, config);
1085
1065
  const { pkg: { publishConfig: { registry } } } = ctx;
1086
- return success(MSG.CHECK.NPM.CHECKED(registry, msg$1), dryRun);
1066
+ return success(MSG.CHECK.NPM.CHECKED(registry, msg), dryRun);
1087
1067
  },
1088
1068
  enabled: !ctx.noNpm
1089
1069
  },
1090
1070
  {
1091
1071
  title: MSG.CHECK.GITHUB.CHECKING,
1092
1072
  task: async () => {
1093
- const msg$1 = await githubCheck(ctx, config);
1073
+ const msg = await githubCheck(ctx, config);
1094
1074
  const { github: { owner, repo } } = ctx;
1095
1075
  const repository = getGithubUrl(owner, repo);
1096
- return success(MSG.CHECK.GITHUB.CHECKED(repository, msg$1), dryRun);
1076
+ return success(MSG.CHECK.GITHUB.CHECKED(repository, msg), dryRun);
1097
1077
  },
1098
1078
  enabled: !ctx.noGitHub
1099
1079
  }
@@ -1102,16 +1082,16 @@ var Action = class {
1102
1082
  async bumpTask(ctx, config) {
1103
1083
  const { pkg: { current }, dryRun, isCI, showRelease, showChangelog, selectedPkg } = ctx;
1104
1084
  const { isMonorepo, hooks, getPkgDir, tagPrefix } = config;
1105
- const need = (ctx$1) => {
1106
- const { pkg: { next: next$1 }, isIncrement: isIncrement$1 } = ctx$1;
1107
- return !next$1 && isIncrement$1;
1085
+ const need = (ctx) => {
1086
+ const { pkg: { next }, isIncrement } = ctx;
1087
+ return !next && isIncrement;
1108
1088
  };
1109
1089
  if (need(ctx)) {
1110
1090
  const nextVersion = (isCI ? inc(current, "patch") : void 0) || await runVersionPrompts(ctx, config);
1111
1091
  ctx.isIncrement = neq(current, nextVersion);
1112
- const { version: next$1, isPrerelease: toPreRelease, preId, preBase } = parseVersion(nextVersion);
1092
+ const { version: next, isPrerelease: toPreRelease, preId, preBase } = parseVersion(nextVersion);
1113
1093
  Object.assign(ctx.pkg, {
1114
- next: next$1,
1094
+ next,
1115
1095
  toPreRelease,
1116
1096
  preId,
1117
1097
  preBase
@@ -1125,8 +1105,8 @@ var Action = class {
1125
1105
  task: async () => {
1126
1106
  await bumpPackageVersion(next, [], getPkgDir(selectedPkg));
1127
1107
  await formatTemplate(ctx, config);
1128
- const to$1 = `(${current}...${diff(current, next)})`;
1129
- return success(MSG.TASK.VERSION.END(to$1), dryRun);
1108
+ const to = `(${current}...${diff(current, next)})`;
1109
+ return success(MSG.TASK.VERSION.END(to), dryRun);
1130
1110
  }
1131
1111
  }]).catch((err) => abortOnError(err, ctx));
1132
1112
  await runLifeCycleHook(hooks, "after:bump", dryRun);
@@ -1216,7 +1196,6 @@ var Action = class {
1216
1196
  await runLifeCycleHook(hooks, "after:release", dryRun);
1217
1197
  }
1218
1198
  };
1219
-
1220
1199
  //#endregion
1221
1200
  //#region src/cli.ts
1222
1201
  const pkg = readJsonFile(join(__dirname, "..", "package.json"));
@@ -1253,6 +1232,5 @@ program.on("command:*", () => {
1253
1232
  console.log(`See ${red`--help`} for a list of available commands.\n`);
1254
1233
  process.exit(1);
1255
1234
  });
1256
-
1257
1235
  //#endregion
1258
- export { };
1236
+ export {};
package/dist/index.d.mts CHANGED
@@ -3,7 +3,6 @@ import { ConventionalChangelog } from "conventional-changelog";
3
3
  import { log } from "@clack/prompts";
4
4
 
5
5
  //#region src/types.d.ts
6
-
7
6
  type Logger = typeof log;
8
7
  type HookTiming = 'before' | 'after';
9
8
  type HookAction = 'bump' | 'publish' | 'push' | 'release';
@@ -172,7 +171,7 @@ declare const generateChangelog: ({
172
171
  tagPrefix
173
172
  }: Options) => Promise<void>;
174
173
  //#endregion
175
- //#region src/index.d.ts
174
+ //#region src/npm/publish.d.ts
176
175
  interface PublishTagOptions {
177
176
  /**
178
177
  * 支持通过命令行参数提供
package/dist/index.mjs CHANGED
@@ -1,109 +1,12 @@
1
- import { eol, getPackageInfo, getPublishedVersion, parseVersion, publishPackage } from "@peiyanlu/cli-utils";
2
- import { blue, cyan, dim, green, magenta, red, underline, yellow } from "ansis";
3
- import { lt } from "semver";
4
1
  import { isFunction, isPlainObject } from "@peiyanlu/ts-utils";
5
2
  import { createWriteStream, existsSync, readFileSync } from "node:fs";
6
3
  import { join } from "node:path";
4
+ import { eol, getPackageInfo, publishPackage, resolvePublishTag } from "@peiyanlu/cli-utils";
7
5
  import { ConventionalChangelog } from "conventional-changelog";
8
6
  import createPreset from "conventional-changelog-conventionalcommits";
9
7
  import { writeFile } from "node:fs/promises";
10
8
  import { finished } from "node:stream/promises";
11
-
12
- //#region src/messages.ts
13
- const n = (b) => b ? "(dry run)" : "";
14
- const t = () => green(`${Math.floor(process.uptime())}s`);
15
- const MSG = {
16
- INTRO: (dryRun) => `🚀 Starting release ${n(dryRun)}`,
17
- INTRO_PREPARE: (dryRun) => `🚀 Starting prepare release ${n(dryRun)}`,
18
- OUTRO: (dryRun) => `🎉 Release finished successfully in ${t()} ${n(dryRun)}`,
19
- OUTRO_PREPARE: (dryRun) => `🎉 Prepare release finished successfully in ${t()} ${n(dryRun)}`,
20
- LOG: {
21
- SHOW_VERSION: (version) => `🎉 Released ${green(version)}`,
22
- SHOW_CHANGELOG: "🎉 Changelog collected",
23
- CHANGELOG_EMPTY: "No commits found since last release",
24
- CHANGES_EMPTY: "Working tree clean. No files changed"
25
- },
26
- CHECK: {
27
- GIT: {
28
- CHECKING: "Checking Git repository",
29
- CHECKED: (name, url) => `Git remote resolved: ${url ? `${dim(name)} → ${underline(dim(url))}` : "not found"}`
30
- },
31
- NPM: {
32
- CHECKING: "Checking npm registry",
33
- CHECKED: (registry, msg) => `NPM registry: ${underline(dim(registry))} ${underline(dim(msg))}`
34
- },
35
- GITHUB: {
36
- CHECKING: "Checking github repository",
37
- CHECKED: (repository, msg) => `GitHub repository: ${underline(dim(repository))} ${underline(dim(msg))}`
38
- }
39
- },
40
- TASK: {
41
- VERSION: {
42
- START: "Bumping version",
43
- END: (to) => `Version bumped: ${underline(dim(to))}`
44
- },
45
- CHANGELOG: {
46
- START: "Generating changelog",
47
- END: `Changelog generated`
48
- },
49
- NPM: {
50
- START: "Publishing npm package",
51
- END: (url) => `NPM package published: ${underline(dim(url))}`
52
- },
53
- GIT: {
54
- START: "Creating git commit, tag & push",
55
- END: "Git commit, tag & push completed"
56
- },
57
- GITHUB: {
58
- START: "Creating GitHub release",
59
- END: (url) => `GitHub release created: ${underline(dim(url))}`
60
- }
61
- },
62
- PROMPT: {
63
- SELECT_PACKAGE: "Select package release:",
64
- SELECT_VERSION: "Select version bump:",
65
- INPUT_VERSION: "Enter custom version:",
66
- NPM_PUBLISH: (pkg) => `Publish to npm ${underline(dim`(${pkg})`)}?`,
67
- NPM_OTP: "Enter npm one-time password (OTP):",
68
- GITHUB_RELEASE: (title) => `Create a new GitHub release ${underline(dim`(${title})`)}?`,
69
- GIT_COMMIT: (msg) => `Create git commit ${underline(dim`(${msg})`)}?`,
70
- GIT_TAG: (msg) => `Create git tag ${underline(dim`(${msg})`)}?`,
71
- GIT_PUSH: "Push commits and tags to remote?"
72
- },
73
- ERROR: {
74
- GIT_WORKDIR: `[git] Working dir must be clean`,
75
- GIT_REGISTRY: (name) => `[git] Repository not found for ${dim(name)}`,
76
- GIT_REMOTE: (name) => `[git] Remote "${dim(name)}" not found`,
77
- GITHUB_TAG_EXIT: (tag) => `[github] Release or tag "${tag}" already exists`,
78
- GITHUB_TOKEN: (tokenRef) => `[github] Missing GitHub token. Please set ${yellow(tokenRef ?? "GITHUB_TOKEN")}`,
79
- GITHUB_AUTH: "[github] Invalid GitHub token or insufficient permissions",
80
- GITHUB_USER: "[github] User does not have permission to create releases",
81
- NPM_REGISTRY: (registry) => `[npm] Unable to reach npm registry ${underline(dim(registry))}`,
82
- NPM_AUTH: `[npm] Not authenticated with npm. Please run ${yellow("npm login")} and try again.`,
83
- NPM_USER: (user, name) => `[npm] User ${dim(user)} is not a collaborator of ${dim(name)}.`
84
- },
85
- ABORT: {
86
- CANCEL: "Operation cancelled",
87
- MONOREPO_CI_NO_PACKAGE: "CI mode requires a target package in monorepo. Please specify it via \"--package <pkg>\"",
88
- MONOREPO_NO_PACKAGES: "Monorepo detected, but no packages found. Please configure \"config.packages\""
89
- },
90
- INFO: {
91
- TOOL: (name, version) => `${name} ${dim(`v${version}`)}`,
92
- CONFIG: (path) => `config file: ${underline(dim(path || "not found"))}`
93
- }
94
- };
95
-
96
- //#endregion
97
- //#region src/npm/publish.ts
98
- const resolvePublishTag = async (pkgName, version) => {
99
- const { isPrerelease, preId } = parseVersion(version);
100
- if (isPrerelease) return preId || "next";
101
- const active = await getPublishedVersion(pkgName);
102
- if (!active) return "latest";
103
- return lt(version, active) ? "previous" : "latest";
104
- };
105
-
106
- //#endregion
9
+ import { blue, cyan, green, magenta, red, underline, yellow } from "ansis";
107
10
  //#region src/config.ts
108
11
  function defineConfig(config) {
109
12
  return config;
@@ -123,7 +26,6 @@ const mergeConfig = (defaults, overrides) => {
123
26
  }
124
27
  return result;
125
28
  };
126
-
127
29
  //#endregion
128
30
  //#region src/git/changetype.ts
129
31
  const defaultTypes = [
@@ -218,13 +120,11 @@ const defaultTypes = [
218
120
  description: "紧急修复"
219
121
  }
220
122
  ];
221
-
222
123
  //#endregion
223
124
  //#region src/git/changelog.ts
224
- const createGenerator = async ({ getPkgDir, tagPrefix }) => {
225
- const pkgDir = getPkgDir();
226
- const preset = await createPreset({ types: defaultTypes.map((t$1) => ({
227
- ...t$1,
125
+ const parsePreset = async () => {
126
+ const preset = await createPreset({ types: defaultTypes.map((t) => ({
127
+ ...t,
228
128
  hidden: false
229
129
  })) });
230
130
  preset.writer ??= {};
@@ -275,6 +175,11 @@ const createGenerator = async ({ getPkgDir, tagPrefix }) => {
275
175
  {{> commit root=@root}}
276
176
  {{/each}}
277
177
  {{/each}}`.trim() + eol(2);
178
+ return preset;
179
+ };
180
+ const createGenerator = async ({ getPkgDir, tagPrefix }) => {
181
+ const pkgDir = getPkgDir();
182
+ const preset = await parsePreset();
278
183
  return new ConventionalChangelog().readPackage(`${pkgDir}/package.json`).config(preset).options({ releaseCount: 1 }).commits({ path: pkgDir }).tags({ prefix: tagPrefix });
279
184
  };
280
185
  const getChangelog = async ({ getPkgDir, tagPrefix }) => {
@@ -300,9 +205,9 @@ const generateChangelog = async ({ getPkgDir, tagPrefix }) => {
300
205
  writeStream.end();
301
206
  await finished(writeStream);
302
207
  };
303
-
208
+ `${yellow("npm login")}`;
304
209
  //#endregion
305
- //#region src/index.ts
210
+ //#region src/npm/publish.ts
306
211
  const publishTagToNpm = async (options) => {
307
212
  const { gitTag, defaultPackage, tagSeparator = "@", getPkgDir = () => ".", provenance } = options;
308
213
  const tag = process.argv.slice(2)[0] || gitTag;
@@ -314,6 +219,7 @@ const publishTagToNpm = async (options) => {
314
219
  [pkgName, version] = tag.split(tagSeparator);
315
220
  console.log(`🔍 Parsed tag → package: "${yellow(pkgName)}", version: "${green(version)}"`);
316
221
  } else {
222
+ pkgName = ".";
317
223
  version = tag;
318
224
  console.log(`🔍 Parsed tag → version only: "${green(version)}"`);
319
225
  }
@@ -337,6 +243,5 @@ const publishTagToNpm = async (options) => {
337
243
  });
338
244
  console.log(`🎉 Successfully published ${red`${pkg.name}@${version}`} with dist-tag "${blue(publishTag)}"\n`);
339
245
  };
340
-
341
246
  //#endregion
342
- export { createGenerator, defineConfig, generateChangelog, getChangelog, mergeConfig, publishTagToNpm };
247
+ export { createGenerator, defineConfig, generateChangelog, getChangelog, mergeConfig, publishTagToNpm };
@@ -0,0 +1,28 @@
1
+ import { getInput, setFailed } from "@actions/core";
2
+ import { context, getOctokit } from "@actions/github";
3
+ //#region src/release.ts
4
+ async function run() {
5
+ try {
6
+ const github = getOctokit(process.env.GITHUB_TOKEN);
7
+ const { owner, repo } = context.repo;
8
+ const tag = getInput("tag_name", { required: true }).replace("refs/tags/", "");
9
+ const releaseName = getInput("release_name", { required: false }) || tag;
10
+ const body = getInput("body", { required: false }) || "";
11
+ const draft = getInput("draft", { required: false }) === "true";
12
+ const prerelease = /\d-[a-z]/.test(tag);
13
+ await github.rest.repos.createRelease({
14
+ owner,
15
+ repo,
16
+ tag_name: tag,
17
+ name: releaseName,
18
+ body,
19
+ draft,
20
+ prerelease
21
+ });
22
+ } catch (error) {
23
+ setFailed(error.message);
24
+ }
25
+ }
26
+ await run();
27
+ //#endregion
28
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peiyanlu/release",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "Release project tool.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -26,28 +26,30 @@
26
26
  "test:cov": "vitest run --coverage"
27
27
  },
28
28
  "dependencies": {
29
- "@clack/prompts": "^0.11.0",
29
+ "@actions/core": "^3.0.0",
30
+ "@actions/github": "^9.0.0",
31
+ "@clack/prompts": "^1.2.0",
30
32
  "@octokit/rest": "^22.0.1",
31
- "@peiyanlu/cli-utils": "^0.0.7",
33
+ "@peiyanlu/cli-utils": "^0.0.8",
32
34
  "@peiyanlu/ts-utils": "^0.0.5",
33
35
  "ansis": "^4.2.0",
34
- "commander": "^14.0.2",
35
- "conventional-changelog": "^7.1.1",
36
- "conventional-changelog-conventionalcommits": "^9.1.0",
36
+ "commander": "^14.0.3",
37
+ "conventional-changelog": "^7.2.0",
38
+ "conventional-changelog-conventionalcommits": "^9.3.1",
37
39
  "mime-types": "^3.0.2",
38
40
  "open": "^11.0.0",
39
- "publint": "^0.3.17",
40
- "semver": "^7.7.3",
41
+ "publint": "^0.3.18",
42
+ "semver": "^7.7.4",
41
43
  "tinyglobby": "^0.2.15"
42
44
  },
43
45
  "devDependencies": {
44
46
  "@types/mime-types": "^3.0.1",
45
- "@types/node": "^24.10.3",
47
+ "@types/node": "^25.5.2",
46
48
  "@types/semver": "^7.7.1",
47
- "@vitest/coverage-v8": "^4.0.15",
48
- "tsdown": "^0.18.4",
49
- "typescript": "^5.9.3",
50
- "vitest": "^4.0.18"
49
+ "@vitest/coverage-v8": "^4.1.3",
50
+ "tsdown": "^0.21.7",
51
+ "typescript": "^6.0.2",
52
+ "vitest": "^4.1.3"
51
53
  },
52
54
  "author": {
53
55
  "name": "YanluPei",