@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 +51 -6
- package/dist/cli.mjs +83 -105
- package/dist/index.d.mts +1 -2
- package/dist/index.mjs +14 -109
- package/dist/release.mjs +28 -0
- package/package.json +15 -13
package/README.md
CHANGED
|
@@ -296,18 +296,63 @@ GitHub Release 可基于 Git Tag 自动创建,并支持附带:
|
|
|
296
296
|
当 Tag 推送到远端后,CI/CD 自动执行:
|
|
297
297
|
|
|
298
298
|
- 发布到 npm
|
|
299
|
-
- 创建
|
|
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
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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,
|
|
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
|
|
38
|
-
if (existsSync(path
|
|
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
|
|
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
|
|
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
|
|
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
|
|
133
|
-
GIT_TAG: (msg
|
|
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
|
|
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
|
|
201
|
-
await pushTag(remoteName
|
|
202
|
-
await pushBranch(remoteName
|
|
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
|
|
226
|
-
cancel(`${red("✕")} ${msg
|
|
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
|
|
239
|
-
log.message(`\n${msg
|
|
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
|
|
243
|
-
outro(msg
|
|
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
|
|
250
|
-
console.log(`${rgb(33, 91, 184)(`i`)} ${msg
|
|
243
|
+
const info = (msg) => {
|
|
244
|
+
console.log(`${rgb(33, 91, 184)(`i`)} ${msg}`);
|
|
251
245
|
};
|
|
252
|
-
const msg = (prefix, msg
|
|
253
|
-
log.message(`${rgb(33, 91, 184)(`[${prefix}]`)} ${dim(msg
|
|
246
|
+
const msg = (prefix, msg) => {
|
|
247
|
+
log.message(`${rgb(33, 91, 184)(`[${prefix}]`)} ${dim(msg)}`);
|
|
254
248
|
};
|
|
255
|
-
const question = (msg
|
|
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
|
|
256
|
+
}[type]`?`} ${msg}`;
|
|
263
257
|
};
|
|
264
|
-
const success = (msg
|
|
265
|
-
return `${(dryRun ? rgb(123, 115, 66) : green)("✔")} ${msg
|
|
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
|
|
304
|
-
Release
|
|
305
|
-
Release
|
|
306
|
-
Release
|
|
307
|
-
Release
|
|
308
|
-
return Release
|
|
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
|
|
311
|
-
PreRelease
|
|
312
|
-
PreRelease
|
|
313
|
-
PreRelease
|
|
314
|
-
PreRelease
|
|
315
|
-
return PreRelease
|
|
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
|
|
318
|
-
PreId
|
|
319
|
-
PreId
|
|
320
|
-
PreId
|
|
321
|
-
PreId
|
|
322
|
-
PreId
|
|
323
|
-
PreId
|
|
324
|
-
PreId
|
|
325
|
-
return PreId
|
|
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
|
|
379
|
-
if (type === "ignore") return current
|
|
371
|
+
const resolveNextVersion = async (type, current) => {
|
|
372
|
+
if (type === "ignore") return current;
|
|
380
373
|
if (type === "custom") return inputVersion();
|
|
381
|
-
return createVersionMap(current
|
|
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
|
|
455
|
+
getPkgDir(pkg) {
|
|
464
456
|
return ".";
|
|
465
457
|
},
|
|
466
|
-
toTag(pkg
|
|
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
|
|
600
|
-
const
|
|
601
|
-
|
|
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
|
|
999
|
+
const pkg = await select({
|
|
1020
1000
|
message: question(MSG.PROMPT.SELECT_PACKAGE, "package"),
|
|
1021
|
-
options: packages.map((pkg
|
|
1022
|
-
label: pkg
|
|
1023
|
-
value: pkg
|
|
1001
|
+
options: packages.map((pkg) => ({
|
|
1002
|
+
label: pkg,
|
|
1003
|
+
value: pkg
|
|
1024
1004
|
}))
|
|
1025
1005
|
});
|
|
1026
|
-
abortSinglePrompt(pkg
|
|
1027
|
-
return pkg
|
|
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
|
|
1031
|
-
const { version: pkgVersion, private: pkgPrivate = false, name: pkgName, publishConfig = {} } = pkg
|
|
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
|
|
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
|
|
1064
|
+
const msg = await npmCheck(ctx, config);
|
|
1085
1065
|
const { pkg: { publishConfig: { registry } } } = ctx;
|
|
1086
|
-
return success(MSG.CHECK.NPM.CHECKED(registry, msg
|
|
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
|
|
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
|
|
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
|
|
1106
|
-
const { pkg: { next
|
|
1107
|
-
return !next
|
|
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
|
|
1092
|
+
const { version: next, isPrerelease: toPreRelease, preId, preBase } = parseVersion(nextVersion);
|
|
1113
1093
|
Object.assign(ctx.pkg, {
|
|
1114
|
-
next
|
|
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
|
|
1129
|
-
return success(MSG.TASK.VERSION.END(to
|
|
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/
|
|
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
|
|
225
|
-
const
|
|
226
|
-
|
|
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/
|
|
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 };
|
package/dist/release.mjs
ADDED
|
@@ -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.
|
|
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
|
-
"@
|
|
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.
|
|
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.
|
|
35
|
-
"conventional-changelog": "^7.
|
|
36
|
-
"conventional-changelog-conventionalcommits": "^9.1
|
|
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.
|
|
40
|
-
"semver": "^7.7.
|
|
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": "^
|
|
47
|
+
"@types/node": "^25.5.2",
|
|
46
48
|
"@types/semver": "^7.7.1",
|
|
47
|
-
"@vitest/coverage-v8": "^4.
|
|
48
|
-
"tsdown": "^0.
|
|
49
|
-
"typescript": "^
|
|
50
|
-
"vitest": "^4.
|
|
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",
|