@peiyanlu/release 0.0.6 → 0.0.7
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 +43 -1
- package/dist/cli.mjs +38 -66
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +17 -37
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -65,6 +65,18 @@ pnpm release minor --ci
|
|
|
65
65
|
| `--show-changelog` | 打印生成的 Changelog 并退出 |
|
|
66
66
|
| `--ci` | 启用 CI 模式:禁用交互提示,缺少必要参数时直接失败;GitHub Actions 等 CI/CD 环境中默认启用 |
|
|
67
67
|
|
|
68
|
+
### Prepare 相关参数
|
|
69
|
+
|
|
70
|
+
| 参数 | 说明 |
|
|
71
|
+
|-------------|--------------------------|
|
|
72
|
+
| `--prepare` | 仅仅变更版本、提交代码、创建 Tag、推送到远程 |
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pnpm release minor --prepare --ci --package pkg-a
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
> 后续可以通过 tag 进行 npm 发布和创建 GitHub release
|
|
79
|
+
|
|
68
80
|
### Monorepo / CI 相关参数
|
|
69
81
|
|
|
70
82
|
| 参数 | 说明 |
|
|
@@ -72,7 +84,7 @@ pnpm release minor --ci
|
|
|
72
84
|
| `-p, --package <pkg>` | 指定要发布的子包名称(仅用于 Monorepo 的 CI 场景) |
|
|
73
85
|
|
|
74
86
|
```bash
|
|
75
|
-
pnpm release minor --ci --package
|
|
87
|
+
pnpm release minor --ci --package pkg-a
|
|
76
88
|
```
|
|
77
89
|
|
|
78
90
|
### npm 发布相关参数
|
|
@@ -268,6 +280,36 @@ GitHub Release 可基于 Git Tag 自动创建,并支持附带:
|
|
|
268
280
|
|
|
269
281
|
工具默认配置偏向于 **单仓库(Single Repo)** 项目,但是可以通过配置使其支持 **Monorepo**
|
|
270
282
|
|
|
283
|
+
## 流程拆分
|
|
284
|
+
|
|
285
|
+
### 本地准备 Release(仅创建 Tag)
|
|
286
|
+
|
|
287
|
+
在本地完成版本确认与变更准备:
|
|
288
|
+
|
|
289
|
+
- 确定下一个版本
|
|
290
|
+
- 更新 `package.json` / `CHANGELOG`
|
|
291
|
+
- 创建发布提交
|
|
292
|
+
- 创建并推送 git 标签
|
|
293
|
+
|
|
294
|
+
### CI/CD 自动发布(由 Tag 触发)
|
|
295
|
+
|
|
296
|
+
当 Tag 推送到远端后,CI/CD 自动执行:
|
|
297
|
+
|
|
298
|
+
- 发布到 npm
|
|
299
|
+
- 创建 GItHub release
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
// publishCI.ts
|
|
303
|
+
import { publishTagToNpm } from '@peiyanlu/release'
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
await publishTagToNpm({
|
|
307
|
+
gitTag: '1.0.16',
|
|
308
|
+
getPkgDir: () => '.',
|
|
309
|
+
defaultPackage: '.',
|
|
310
|
+
})
|
|
311
|
+
```
|
|
312
|
+
|
|
271
313
|
## Dry Run
|
|
272
314
|
|
|
273
315
|
```bash
|
package/dist/cli.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
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, isWorkingDirClean, parseGitHubRepo, 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, isPrerelease, isValid, isWorkingDirClean, parseGitHubRepo, parseVersion, pingRegistry, publishPackage, pushBranch, pushTag, readJsonFile, resolveChangelogRange } 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 {
|
|
11
|
-
import { castArray, isPlainObject, isUndefined } from "@peiyanlu/ts-utils";
|
|
10
|
+
import { inc, lt, neq } from "semver";
|
|
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";
|
|
14
14
|
import { ConventionalChangelog } from "conventional-changelog";
|
|
@@ -55,7 +55,6 @@ const resolveConfig = async (cwd) => {
|
|
|
55
55
|
config: await loadConfig(configFile)
|
|
56
56
|
};
|
|
57
57
|
};
|
|
58
|
-
const isFunction = (v) => typeof v === "function";
|
|
59
58
|
const mergeConfig = (defaults, overrides) => {
|
|
60
59
|
if (!overrides) return structuredClone(defaults);
|
|
61
60
|
if (Object.keys(defaults).length === 0) return structuredClone(overrides);
|
|
@@ -78,8 +77,9 @@ const n = (b) => b ? "(dry run)" : "";
|
|
|
78
77
|
const t = () => green(`${Math.floor(process.uptime())}s`);
|
|
79
78
|
const MSG = {
|
|
80
79
|
INTRO: (dryRun) => `🚀 Starting release ${n(dryRun)}`,
|
|
80
|
+
INTRO_PREPARE: (dryRun) => `🚀 Starting prepare release ${n(dryRun)}`,
|
|
81
81
|
OUTRO: (dryRun) => `🎉 Release finished successfully in ${t()} ${n(dryRun)}`,
|
|
82
|
-
OUTRO_PREPARE: (dryRun) => `🎉
|
|
82
|
+
OUTRO_PREPARE: (dryRun) => `🎉 Prepare release finished successfully in ${t()} ${n(dryRun)}`,
|
|
83
83
|
LOG: {
|
|
84
84
|
SHOW_VERSION: (version) => `🎉 Released ${green(version)}`,
|
|
85
85
|
SHOW_CHANGELOG: "🎉 Changelog collected",
|
|
@@ -298,34 +298,6 @@ const formatTemplate = async (ctx, config) => {
|
|
|
298
298
|
Object.assign(ctx.github, { releaseName });
|
|
299
299
|
};
|
|
300
300
|
|
|
301
|
-
//#endregion
|
|
302
|
-
//#region src/version/bump.ts
|
|
303
|
-
const isPreRelease = (version) => {
|
|
304
|
-
return Boolean(prerelease(version));
|
|
305
|
-
};
|
|
306
|
-
const isValid = (version) => {
|
|
307
|
-
return Boolean(valid(version));
|
|
308
|
-
};
|
|
309
|
-
const parseVersion = (raw) => {
|
|
310
|
-
const next = isValid(raw) ? raw : coerce(raw)?.toString();
|
|
311
|
-
if (!next) return {};
|
|
312
|
-
const { prerelease: prerelease$1 } = parse(next);
|
|
313
|
-
const toPreRelease = Boolean(prerelease$1.length);
|
|
314
|
-
const [preId, preBase] = prerelease$1.map(String);
|
|
315
|
-
return {
|
|
316
|
-
next,
|
|
317
|
-
toPreRelease,
|
|
318
|
-
preId,
|
|
319
|
-
preBase
|
|
320
|
-
};
|
|
321
|
-
};
|
|
322
|
-
const getCIVersion = (current) => {
|
|
323
|
-
return inc(current, Release.PATCH);
|
|
324
|
-
};
|
|
325
|
-
const isNeq = (current, next) => {
|
|
326
|
-
return neq(current, next);
|
|
327
|
-
};
|
|
328
|
-
|
|
329
301
|
//#endregion
|
|
330
302
|
//#region src/version/prompts.ts
|
|
331
303
|
let Release = /* @__PURE__ */ function(Release$1) {
|
|
@@ -779,7 +751,7 @@ const getReleaseByTagSafe = async (octokit, options) => {
|
|
|
779
751
|
}
|
|
780
752
|
};
|
|
781
753
|
const createCRelease = async (octokit, options) => {
|
|
782
|
-
const { owner, repo, tag, name, body, draft, prerelease
|
|
754
|
+
const { owner, repo, tag, name, body, draft, prerelease, generateReleaseNotes, makeLatest, targetCommitish, discussionCategoryName } = options;
|
|
783
755
|
const { data } = await octokit.repos.createRelease({
|
|
784
756
|
owner,
|
|
785
757
|
repo,
|
|
@@ -787,7 +759,7 @@ const createCRelease = async (octokit, options) => {
|
|
|
787
759
|
name,
|
|
788
760
|
body,
|
|
789
761
|
draft,
|
|
790
|
-
prerelease
|
|
762
|
+
prerelease,
|
|
791
763
|
generate_release_notes: generateReleaseNotes,
|
|
792
764
|
make_latest: makeLatest,
|
|
793
765
|
target_commitish: targetCommitish,
|
|
@@ -796,7 +768,7 @@ const createCRelease = async (octokit, options) => {
|
|
|
796
768
|
return data;
|
|
797
769
|
};
|
|
798
770
|
const updateCRelease = async (octokit, options) => {
|
|
799
|
-
const { owner, repo, tag, name, body, draft, prerelease
|
|
771
|
+
const { owner, repo, tag, name, body, draft, prerelease, generateReleaseNotes, makeLatest, targetCommitish, discussionCategoryName, releaseId } = options;
|
|
800
772
|
const { data } = await octokit.repos.updateRelease({
|
|
801
773
|
owner,
|
|
802
774
|
repo,
|
|
@@ -805,7 +777,7 @@ const updateCRelease = async (octokit, options) => {
|
|
|
805
777
|
name,
|
|
806
778
|
body,
|
|
807
779
|
draft,
|
|
808
|
-
prerelease
|
|
780
|
+
prerelease,
|
|
809
781
|
generate_release_notes: generateReleaseNotes,
|
|
810
782
|
make_latest: makeLatest,
|
|
811
783
|
target_commitish: targetCommitish,
|
|
@@ -842,13 +814,13 @@ const uploadAssets = async (octokit, options) => {
|
|
|
842
814
|
}));
|
|
843
815
|
};
|
|
844
816
|
const createWebRelease = async (options) => {
|
|
845
|
-
const { owner, repo, tag, title, body, prerelease
|
|
817
|
+
const { owner, repo, tag, title, body, prerelease } = options;
|
|
846
818
|
const url = new URL(`${getGithubUrl(owner, repo)}/releases/new`);
|
|
847
819
|
Object.entries({
|
|
848
820
|
tag,
|
|
849
821
|
title,
|
|
850
822
|
body,
|
|
851
|
-
prerelease
|
|
823
|
+
prerelease
|
|
852
824
|
}).forEach(([key, value]) => {
|
|
853
825
|
url.searchParams.set(key, value);
|
|
854
826
|
});
|
|
@@ -891,7 +863,7 @@ const githubCheck = async (ctx, config) => {
|
|
|
891
863
|
const createRelease = async (ctx, config) => {
|
|
892
864
|
const { pkg: { name, toPreRelease }, git: { currentTag }, isCI, dryRun } = ctx;
|
|
893
865
|
const { github: { isWeb, token, owner, repo, changelog, releaseName } } = ctx;
|
|
894
|
-
const { github: { release, assets, prerelease
|
|
866
|
+
const { github: { release, assets, prerelease, autoGenerate, draft } } = config;
|
|
895
867
|
if (!release || dryRun) return;
|
|
896
868
|
const octokit = new Octokit({ auth: token });
|
|
897
869
|
if (isWeb) await createWebRelease({
|
|
@@ -900,7 +872,7 @@ const createRelease = async (ctx, config) => {
|
|
|
900
872
|
tag: currentTag,
|
|
901
873
|
title: releaseName,
|
|
902
874
|
body: truncateBody(changelog),
|
|
903
|
-
prerelease: String(toPreRelease || prerelease
|
|
875
|
+
prerelease: String(toPreRelease || prerelease)
|
|
904
876
|
});
|
|
905
877
|
else if (isCI) {
|
|
906
878
|
const res = await createCReleaseByTag(octokit, {
|
|
@@ -910,7 +882,7 @@ const createRelease = async (ctx, config) => {
|
|
|
910
882
|
name: releaseName,
|
|
911
883
|
body: autoGenerate ? "" : truncateBody(changelog),
|
|
912
884
|
draft,
|
|
913
|
-
prerelease: toPreRelease || prerelease
|
|
885
|
+
prerelease: toPreRelease || prerelease,
|
|
914
886
|
generateReleaseNotes: autoGenerate,
|
|
915
887
|
makeLatest: "true"
|
|
916
888
|
});
|
|
@@ -963,8 +935,8 @@ const runNpmOptPrompts = async (ctx, config) => {
|
|
|
963
935
|
//#endregion
|
|
964
936
|
//#region src/npm/publish.ts
|
|
965
937
|
const resolvePublishTag = async (pkgName, version) => {
|
|
966
|
-
const {
|
|
967
|
-
if (
|
|
938
|
+
const { isPrerelease: isPrerelease$1, preId } = parseVersion(version);
|
|
939
|
+
if (isPrerelease$1) return preId || "next";
|
|
968
940
|
const active = await getPublishedVersion(pkgName);
|
|
969
941
|
if (!active) return "latest";
|
|
970
942
|
return lt(version, active) ? "previous" : "latest";
|
|
@@ -1018,7 +990,7 @@ var Action = class {
|
|
|
1018
990
|
taskEnd(MSG.OUTRO(ctx.dryRun));
|
|
1019
991
|
}
|
|
1020
992
|
async handlePrepareRelease(cmdArgs, options) {
|
|
1021
|
-
const { ctx, config } = await this.createContext(cmdArgs, options);
|
|
993
|
+
const { ctx, config } = await this.createContext(cmdArgs, options, true);
|
|
1022
994
|
await this.checkTask(ctx, config);
|
|
1023
995
|
await this.bumpTask(ctx, config);
|
|
1024
996
|
await this.changelogTask(ctx, config);
|
|
@@ -1026,7 +998,7 @@ var Action = class {
|
|
|
1026
998
|
if (ctx.dryRun) gitRollback(ctx);
|
|
1027
999
|
taskEnd(MSG.OUTRO_PREPARE(ctx.dryRun));
|
|
1028
1000
|
}
|
|
1029
|
-
async createContext(cmdArgs, options) {
|
|
1001
|
+
async createContext(cmdArgs, options, prepare = false) {
|
|
1030
1002
|
const { version: cVersion, name: cName } = readJsonFile(join(__dirname, "../package.json"));
|
|
1031
1003
|
const { otp, package: defPkg, ...others } = options;
|
|
1032
1004
|
const { showChangelog, showRelease, ci, dryRun } = Object.fromEntries(Object.entries(others).map(([k, v]) => [k, Boolean(v)]));
|
|
@@ -1036,7 +1008,7 @@ var Action = class {
|
|
|
1036
1008
|
info(MSG.INFO.TOOL(cName, cVersion));
|
|
1037
1009
|
info(MSG.INFO.CONFIG(configPath));
|
|
1038
1010
|
console.log();
|
|
1039
|
-
intro(MSG.INTRO(dryRun));
|
|
1011
|
+
intro(prepare ? MSG.INTRO_PREPARE(dryRun) : MSG.INTRO(dryRun));
|
|
1040
1012
|
const { isMonorepo, packages, getPkgDir } = config;
|
|
1041
1013
|
if (isMonorepo) {
|
|
1042
1014
|
if (ci) {
|
|
@@ -1077,7 +1049,7 @@ var Action = class {
|
|
|
1077
1049
|
pkg: {
|
|
1078
1050
|
name: pkgName,
|
|
1079
1051
|
isPrivate: pkgPrivate,
|
|
1080
|
-
fromPreRelease:
|
|
1052
|
+
fromPreRelease: isPrerelease(pkgVersion),
|
|
1081
1053
|
current: pkgVersion,
|
|
1082
1054
|
next: nextVersion,
|
|
1083
1055
|
toPreRelease: false,
|
|
@@ -1135,10 +1107,15 @@ var Action = class {
|
|
|
1135
1107
|
return !next$1 && isIncrement$1;
|
|
1136
1108
|
};
|
|
1137
1109
|
if (need(ctx)) {
|
|
1138
|
-
const
|
|
1139
|
-
ctx.isIncrement =
|
|
1140
|
-
const
|
|
1141
|
-
Object.assign(ctx.pkg, {
|
|
1110
|
+
const nextVersion = (isCI ? inc(current, "patch") : void 0) || await runVersionPrompts(ctx, config);
|
|
1111
|
+
ctx.isIncrement = neq(current, nextVersion);
|
|
1112
|
+
const { version: next$1, isPrerelease: toPreRelease, preId, preBase } = parseVersion(nextVersion);
|
|
1113
|
+
Object.assign(ctx.pkg, {
|
|
1114
|
+
next: next$1,
|
|
1115
|
+
toPreRelease,
|
|
1116
|
+
preId,
|
|
1117
|
+
preBase
|
|
1118
|
+
});
|
|
1142
1119
|
}
|
|
1143
1120
|
const { pkg: { next }, isIncrement } = ctx;
|
|
1144
1121
|
if (showRelease) taskEnd(MSG.LOG.SHOW_VERSION(next));
|
|
@@ -1243,14 +1220,10 @@ var Action = class {
|
|
|
1243
1220
|
//#endregion
|
|
1244
1221
|
//#region src/cli.ts
|
|
1245
1222
|
const pkg = readJsonFile(join(__dirname, "..", "package.json"));
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
await new Action().handleRelease(releaseType, options);
|
|
1251
|
-
});
|
|
1252
|
-
withCommonOptions(program.command("prepare").description("Prepare a release (bump version, commit, tag)")).action(async (releaseType, options) => {
|
|
1253
|
-
await new Action().handlePrepareRelease(releaseType, options);
|
|
1223
|
+
program.name("release").description(pkg.description).version(pkg.version, "-v, --version", "Print the tool version and exit.").usage("[release-type] [options]").argument("[release-type]", "Version bump type: patch | minor | major").option("-n, --dry-run", "Run in dry mode", false).option("-p, --package <pkg>", "Specify package name (CI only).", "").option("--otp <code>", "One-time password for npm publish.", "").option("--prepare", "Prepare a release.", false).option("--ci", "Enable CI mode.", false).option("--show-changelog", "Print changelog and exit.", false).option("--show-release", "Print release version and exit.", false).helpOption("-h, --help", "Display help information.").action(async (releaseType, options) => {
|
|
1224
|
+
const { prepare } = options;
|
|
1225
|
+
const action = new Action();
|
|
1226
|
+
prepare ? await action.handlePrepareRelease(releaseType, options) : await action.handleRelease(releaseType, options);
|
|
1254
1227
|
});
|
|
1255
1228
|
program.command("init").description("Create a release configuration file").option("-f, --force", "Overwrite existing config file", false).option("-m, --monorepo", "Mono-repo project", false).action((options) => {
|
|
1256
1229
|
const { force = false, monorepo = false } = options;
|
|
@@ -1258,9 +1231,10 @@ program.command("init").description("Create a release configuration file").optio
|
|
|
1258
1231
|
const { type } = readJsonFile(join(cwd, "package.json"));
|
|
1259
1232
|
const isESM = type === "module";
|
|
1260
1233
|
const isTS = existsSync(join(cwd, "tsconfig.json"));
|
|
1261
|
-
const
|
|
1234
|
+
const infile = `release.config.${isESM ? "" : "m"}${isTS ? "ts" : "js"}`;
|
|
1235
|
+
const configPath = join(cwd, infile);
|
|
1262
1236
|
if (existsSync(configPath) && !force) {
|
|
1263
|
-
console.error(`${red`Error:`} ${yellow
|
|
1237
|
+
console.error(`${red`Error:`} ${yellow(infile)} already exists.\nUse ${green`--force`} to overwrite.`);
|
|
1264
1238
|
process.exit(1);
|
|
1265
1239
|
}
|
|
1266
1240
|
const monoConfigToString = () => `{
|
|
@@ -1270,10 +1244,8 @@ program.command("init").description("Create a release configuration file").optio
|
|
|
1270
1244
|
toTag: (pkg, version) => \`\${ pkg }@\${ version }\`,
|
|
1271
1245
|
tagPrefix: (pkg) => \`\${ pkg }@\`,
|
|
1272
1246
|
}`;
|
|
1273
|
-
writeFileSync(configPath, `import { defineConfig } from '@peiyanlu/release'
|
|
1274
|
-
|
|
1275
|
-
export default defineConfig(${monorepo ? monoConfigToString() : "{}"})`, "utf-8");
|
|
1276
|
-
console.log(`${green`✔ release.config.ts`} created successfully`);
|
|
1247
|
+
writeFileSync(configPath, [`import { defineConfig } from '@peiyanlu/release'`, `export default defineConfig(${monorepo ? monoConfigToString() : "{}"})`].join(eol(2)), "utf-8");
|
|
1248
|
+
console.log(`${green`✔`} ${infile} created successfully`);
|
|
1277
1249
|
});
|
|
1278
1250
|
program.parse(process.argv);
|
|
1279
1251
|
program.on("command:*", () => {
|
package/dist/index.d.mts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { eol, getPackageInfo, getPublishedVersion, publishPackage } from "@peiyanlu/cli-utils";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { isPlainObject } from "@peiyanlu/ts-utils";
|
|
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
|
+
import { isFunction, isPlainObject } from "@peiyanlu/ts-utils";
|
|
6
5
|
import { createWriteStream, existsSync, readFileSync } from "node:fs";
|
|
7
6
|
import { join } from "node:path";
|
|
8
7
|
import { ConventionalChangelog } from "conventional-changelog";
|
|
@@ -15,8 +14,9 @@ const n = (b) => b ? "(dry run)" : "";
|
|
|
15
14
|
const t = () => green(`${Math.floor(process.uptime())}s`);
|
|
16
15
|
const MSG = {
|
|
17
16
|
INTRO: (dryRun) => `🚀 Starting release ${n(dryRun)}`,
|
|
17
|
+
INTRO_PREPARE: (dryRun) => `🚀 Starting prepare release ${n(dryRun)}`,
|
|
18
18
|
OUTRO: (dryRun) => `🎉 Release finished successfully in ${t()} ${n(dryRun)}`,
|
|
19
|
-
OUTRO_PREPARE: (dryRun) => `🎉
|
|
19
|
+
OUTRO_PREPARE: (dryRun) => `🎉 Prepare release finished successfully in ${t()} ${n(dryRun)}`,
|
|
20
20
|
LOG: {
|
|
21
21
|
SHOW_VERSION: (version) => `🎉 Released ${green(version)}`,
|
|
22
22
|
SHOW_CHANGELOG: "🎉 Changelog collected",
|
|
@@ -93,30 +93,11 @@ const MSG = {
|
|
|
93
93
|
}
|
|
94
94
|
};
|
|
95
95
|
|
|
96
|
-
//#endregion
|
|
97
|
-
//#region src/version/bump.ts
|
|
98
|
-
const isValid = (version) => {
|
|
99
|
-
return Boolean(valid(version));
|
|
100
|
-
};
|
|
101
|
-
const parseVersion = (raw) => {
|
|
102
|
-
const next = isValid(raw) ? raw : coerce(raw)?.toString();
|
|
103
|
-
if (!next) return {};
|
|
104
|
-
const { prerelease } = parse(next);
|
|
105
|
-
const toPreRelease = Boolean(prerelease.length);
|
|
106
|
-
const [preId, preBase] = prerelease.map(String);
|
|
107
|
-
return {
|
|
108
|
-
next,
|
|
109
|
-
toPreRelease,
|
|
110
|
-
preId,
|
|
111
|
-
preBase
|
|
112
|
-
};
|
|
113
|
-
};
|
|
114
|
-
|
|
115
96
|
//#endregion
|
|
116
97
|
//#region src/npm/publish.ts
|
|
117
98
|
const resolvePublishTag = async (pkgName, version) => {
|
|
118
|
-
const {
|
|
119
|
-
if (
|
|
99
|
+
const { isPrerelease, preId } = parseVersion(version);
|
|
100
|
+
if (isPrerelease) return preId || "next";
|
|
120
101
|
const active = await getPublishedVersion(pkgName);
|
|
121
102
|
if (!active) return "latest";
|
|
122
103
|
return lt(version, active) ? "previous" : "latest";
|
|
@@ -127,7 +108,6 @@ const resolvePublishTag = async (pkgName, version) => {
|
|
|
127
108
|
function defineConfig(config) {
|
|
128
109
|
return config;
|
|
129
110
|
}
|
|
130
|
-
const isFunction = (v) => typeof v === "function";
|
|
131
111
|
const mergeConfig = (defaults, overrides) => {
|
|
132
112
|
if (!overrides) return structuredClone(defaults);
|
|
133
113
|
if (Object.keys(defaults).length === 0) return structuredClone(overrides);
|
|
@@ -327,35 +307,35 @@ const publishTagToNpm = async (options) => {
|
|
|
327
307
|
const { gitTag, defaultPackage, tagSeparator = "@", getPkgDir = () => ".", provenance } = options;
|
|
328
308
|
const tag = process.argv.slice(2)[0] || gitTag;
|
|
329
309
|
if (!tag) throw new Error(`❌ No git tag specified.`);
|
|
330
|
-
console.log(`\n📦 Start publishing from git tag: ${tag}`);
|
|
310
|
+
console.log(`\n📦 Start publishing from git tag: ${cyan(tag)}`);
|
|
331
311
|
let pkgName = defaultPackage;
|
|
332
312
|
let version;
|
|
333
313
|
if (tag.includes(tagSeparator)) {
|
|
334
314
|
[pkgName, version] = tag.split(tagSeparator);
|
|
335
|
-
console.log(`🔍 Parsed tag → package: "${pkgName}", version: "${version}"`);
|
|
315
|
+
console.log(`🔍 Parsed tag → package: "${yellow(pkgName)}", version: "${green(version)}"`);
|
|
336
316
|
} else {
|
|
337
317
|
version = tag;
|
|
338
|
-
console.log(`🔍 Parsed tag → version only: "${version}"`);
|
|
318
|
+
console.log(`🔍 Parsed tag → version only: "${green(version)}"`);
|
|
339
319
|
}
|
|
340
320
|
if (version.startsWith("v")) {
|
|
341
321
|
version = version.slice(1);
|
|
342
322
|
console.log(`✂️ Normalized version (strip v): ${version}`);
|
|
343
323
|
}
|
|
344
324
|
if (!pkgName) throw new Error(`❌ Package name should be specified in tag "${tag}" when defaultPackage is not set`);
|
|
345
|
-
console.log(`📁 Resolving package info for "${pkgName}"...`);
|
|
325
|
+
console.log(`📁 Resolving package info for "${magenta(pkgName)}"...`);
|
|
346
326
|
const { pkg, pkgDir } = getPackageInfo(pkgName, getPkgDir);
|
|
347
|
-
console.log(`📄 package.json → name: ${pkg.name}, version: ${pkg.version}`);
|
|
348
|
-
console.log(`📂 Package directory: ${pkgDir}`);
|
|
327
|
+
console.log(`📄 package.json → name: ${yellow(pkg.name)}, version: ${green(pkg.version)}`);
|
|
328
|
+
console.log(`📂 Package directory: ${underline(pkgDir)}`);
|
|
349
329
|
if (pkg.version !== version) throw new Error(`❌ Package version from tag "${version}" mismatches with current version "${pkg.version}"`);
|
|
350
330
|
const publishTag = await resolvePublishTag(pkg.name, version);
|
|
351
|
-
console.log(`🏷 Resolved npm dist-tag: "${publishTag}" (version ${version})`);
|
|
352
|
-
console.log(`🚀 Publishing "${pkg.name}@${version}" to npm...`);
|
|
331
|
+
console.log(`🏷 Resolved npm dist-tag: "${blue(publishTag)}" (version ${green(version)})`);
|
|
332
|
+
console.log(`🚀 Publishing "${red`${pkg.name}@${version}`}" to npm...`);
|
|
353
333
|
await publishPackage({
|
|
354
334
|
tag: publishTag,
|
|
355
335
|
args: provenance ? ["--provenance"] : [],
|
|
356
336
|
cwd: pkgDir
|
|
357
337
|
});
|
|
358
|
-
console.log(
|
|
338
|
+
console.log(`🎉 Successfully published ${red`${pkg.name}@${version}`} with dist-tag "${blue(publishTag)}"\n`);
|
|
359
339
|
};
|
|
360
340
|
|
|
361
341
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peiyanlu/release",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Release project tool.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,11 +17,19 @@
|
|
|
17
17
|
},
|
|
18
18
|
"./package.json": "./package.json"
|
|
19
19
|
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"dev": "tsdown -w",
|
|
22
|
+
"build": "tsdown",
|
|
23
|
+
"prepublish": "tsdown",
|
|
24
|
+
"release": "node index.js",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:cov": "vitest run --coverage"
|
|
27
|
+
},
|
|
20
28
|
"dependencies": {
|
|
21
29
|
"@clack/prompts": "^0.11.0",
|
|
22
30
|
"@octokit/rest": "^22.0.1",
|
|
23
|
-
"@peiyanlu/cli-utils": "^0.0.
|
|
24
|
-
"@peiyanlu/ts-utils": "^0.0.
|
|
31
|
+
"@peiyanlu/cli-utils": "^0.0.7",
|
|
32
|
+
"@peiyanlu/ts-utils": "^0.0.5",
|
|
25
33
|
"ansis": "^4.2.0",
|
|
26
34
|
"commander": "^14.0.2",
|
|
27
35
|
"conventional-changelog": "^7.1.1",
|
|
@@ -66,13 +74,5 @@
|
|
|
66
74
|
"bugs": {
|
|
67
75
|
"url": "https://github.com/peiyanlu/release/issues"
|
|
68
76
|
},
|
|
69
|
-
"homepage": "https://github.com/peiyanlu/release#readme"
|
|
70
|
-
|
|
71
|
-
"dev": "tsdown -w",
|
|
72
|
-
"build": "tsdown",
|
|
73
|
-
"prepublish": "tsdown",
|
|
74
|
-
"release": "node index.js",
|
|
75
|
-
"test": "vitest run",
|
|
76
|
-
"test:cov": "vitest run --coverage"
|
|
77
|
-
}
|
|
78
|
-
}
|
|
77
|
+
"homepage": "https://github.com/peiyanlu/release#readme"
|
|
78
|
+
}
|