@peiyanlu/release 0.0.14 → 0.0.15
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 +6 -2
- package/dist/cli.mjs +76 -38
- package/dist/index.d.mts +24 -13
- package/dist/index.mjs +33 -24
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -122,7 +122,9 @@ export default defineConfig({
|
|
|
122
122
|
packages: [],
|
|
123
123
|
getPkgDir: (pkg) => `.`,
|
|
124
124
|
toTag: (pkg: string, version: string) => `v${ version }`,
|
|
125
|
-
|
|
125
|
+
changelog: {
|
|
126
|
+
tagPrefix: undefined,
|
|
127
|
+
},
|
|
126
128
|
|
|
127
129
|
git: {
|
|
128
130
|
commit: true,
|
|
@@ -157,7 +159,9 @@ export default defineConfig({
|
|
|
157
159
|
packages: [ 'demo-a', 'demo-b' ],
|
|
158
160
|
getPkgDir: (pkg) => `packages/${ pkg }`,
|
|
159
161
|
toTag: (pkg: string, version: string) => `${ pkg }@${ version }`,
|
|
160
|
-
|
|
162
|
+
changelog: {
|
|
163
|
+
tagPrefix: (pkg: string) => `${ pkg }@`,
|
|
164
|
+
},
|
|
161
165
|
|
|
162
166
|
git: {
|
|
163
167
|
commit: true,
|
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, isOtpError, isPrerelease, isValid, isWorkingDirClean, parseGitHubRepo, parseVersion, pingRegistry, publishPackage, pushBranch, pushTag, readJsonFile, resolveChangelogRange, resolvePublishTag } 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, registryArg, resolveChangelogRange, resolvePublishTag, runNpm } 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
|
+
import { castArray, isFunction, isPlainObject, isUndefined, isZero } from "@peiyanlu/ts-utils";
|
|
8
9
|
import { publint } from "publint";
|
|
9
10
|
import { formatMessage } from "publint/utils";
|
|
10
11
|
import { inc, 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";
|
|
@@ -54,13 +54,12 @@ const resolveConfig = async (cwd) => {
|
|
|
54
54
|
};
|
|
55
55
|
};
|
|
56
56
|
const mergeConfig = (defaults, overrides) => {
|
|
57
|
-
if (!overrides) return structuredClone(defaults);
|
|
58
|
-
if (Object.keys(defaults).length === 0) return structuredClone(overrides);
|
|
59
57
|
const result = {};
|
|
60
|
-
for (const key
|
|
58
|
+
for (const key of Object.keys(defaults)) {
|
|
61
59
|
const defaultValue = defaults[key];
|
|
62
60
|
const overrideValue = overrides[key];
|
|
63
|
-
if (overrideValue
|
|
61
|
+
if (isUndefined(overrideValue)) if (isFunction(defaultValue)) result[key] = defaultValue;
|
|
62
|
+
else if (isPlainObject(defaultValue)) result[key] = mergeConfig(defaultValue, {});
|
|
64
63
|
else result[key] = structuredClone(defaultValue);
|
|
65
64
|
else if (isPlainObject(defaultValue) && isPlainObject(overrideValue)) result[key] = mergeConfig(defaultValue, overrideValue);
|
|
66
65
|
else if (isFunction(overrideValue)) result[key] = overrideValue;
|
|
@@ -134,13 +133,14 @@ const MSG = {
|
|
|
134
133
|
GIT_WORKDIR: `[git] Working dir must be clean`,
|
|
135
134
|
GIT_REGISTRY: (name) => `[git] Repository not found for ${dim(name)}`,
|
|
136
135
|
GIT_REMOTE: (name) => `[git] Remote "${dim(name)}" not found`,
|
|
137
|
-
GITHUB_TAG_EXIT: (tag) => `[github] Release
|
|
136
|
+
GITHUB_TAG_EXIT: (tag) => `[github] Release for tag "${tag}" already exists and is not a draft`,
|
|
138
137
|
GITHUB_TOKEN: (tokenRef) => `[github] Missing GitHub token. Please set ${yellow(tokenRef ?? "GITHUB_TOKEN")}`,
|
|
139
138
|
GITHUB_AUTH: "[github] Invalid GitHub token or insufficient permissions",
|
|
140
139
|
GITHUB_USER: "[github] User does not have permission to create releases",
|
|
141
140
|
NPM_REGISTRY: (registry) => `[npm] Unable to reach npm registry ${underline(dim(registry))}`,
|
|
142
|
-
NPM_AUTH: `[npm] Not authenticated with npm. Please run ${yellow("npm login")} and try again
|
|
143
|
-
|
|
141
|
+
NPM_AUTH: `[npm] Not authenticated with npm. Please run ${yellow("npm login")} and try again`,
|
|
142
|
+
NPM_PERMISSION: `[npm] Missing publish permission. Please use a token with publish access and try again`,
|
|
143
|
+
NPM_USER: (user, name) => `[npm] User ${dim(user)} is not a collaborator of ${dim(name)}`
|
|
144
144
|
},
|
|
145
145
|
ABORT: {
|
|
146
146
|
CANCEL: "Operation cancelled",
|
|
@@ -444,8 +444,11 @@ const createDefaultConfig = (isCI) => {
|
|
|
444
444
|
toTag(pkg, version) {
|
|
445
445
|
return `v${version}`;
|
|
446
446
|
},
|
|
447
|
-
|
|
448
|
-
|
|
447
|
+
changelog: {
|
|
448
|
+
tagPrefix(pkg) {
|
|
449
|
+
return "";
|
|
450
|
+
},
|
|
451
|
+
releaseCount: 1
|
|
449
452
|
},
|
|
450
453
|
ignoreGit: false,
|
|
451
454
|
ignoreNpm: false,
|
|
@@ -521,42 +524,42 @@ const defaultTypes = [
|
|
|
521
524
|
},
|
|
522
525
|
{
|
|
523
526
|
type: "chore",
|
|
524
|
-
section: "
|
|
527
|
+
section: "🧹 其他更新",
|
|
525
528
|
description: "非功能性更改"
|
|
526
529
|
},
|
|
527
530
|
{
|
|
528
531
|
type: "refactor",
|
|
529
|
-
section: "
|
|
532
|
+
section: "♻️ 代码重构",
|
|
530
533
|
description: "重构代码"
|
|
531
534
|
},
|
|
532
535
|
{
|
|
533
536
|
type: "test",
|
|
534
|
-
section: "
|
|
537
|
+
section: "🧪 测试",
|
|
535
538
|
description: "测试更新"
|
|
536
539
|
},
|
|
537
540
|
{
|
|
538
541
|
type: "build",
|
|
539
|
-
section: "
|
|
542
|
+
section: "🏗️ 构建系统",
|
|
540
543
|
description: "构建工具和系统修改"
|
|
541
544
|
},
|
|
542
545
|
{
|
|
543
546
|
type: "ci",
|
|
544
|
-
section: "
|
|
547
|
+
section: "🤖 CI",
|
|
545
548
|
description: "持续集成配置"
|
|
546
549
|
},
|
|
547
550
|
{
|
|
548
551
|
type: "config",
|
|
549
|
-
section: "
|
|
552
|
+
section: "⚙️ 配置",
|
|
550
553
|
description: "配置文件更新"
|
|
551
554
|
},
|
|
552
555
|
{
|
|
553
556
|
type: "deps",
|
|
554
|
-
section: "
|
|
557
|
+
section: "📦 依赖更新",
|
|
555
558
|
description: "依赖版本变更"
|
|
556
559
|
},
|
|
557
560
|
{
|
|
558
561
|
type: "security",
|
|
559
|
-
section: "
|
|
562
|
+
section: "🛡️ 安全修复",
|
|
560
563
|
description: "安全性更新"
|
|
561
564
|
},
|
|
562
565
|
{
|
|
@@ -566,13 +569,18 @@ const defaultTypes = [
|
|
|
566
569
|
},
|
|
567
570
|
{
|
|
568
571
|
type: "ux",
|
|
569
|
-
section: "
|
|
572
|
+
section: "🎨 用户体验",
|
|
570
573
|
description: "用户体验改进"
|
|
571
574
|
},
|
|
572
575
|
{
|
|
573
576
|
type: "hotfix",
|
|
574
|
-
section: "
|
|
577
|
+
section: "🚑 热修复",
|
|
575
578
|
description: "紧急修复"
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
type: "tool",
|
|
582
|
+
section: "🛠️ 工具链",
|
|
583
|
+
description: "工具链变更"
|
|
576
584
|
}
|
|
577
585
|
];
|
|
578
586
|
//#endregion
|
|
@@ -632,32 +640,37 @@ const parsePreset = async () => {
|
|
|
632
640
|
{{/each}}`.trim();
|
|
633
641
|
return preset;
|
|
634
642
|
};
|
|
635
|
-
const createGenerator = async ({ getPkgDir, tagPrefix }) => {
|
|
643
|
+
const createGenerator = async ({ getPkgDir, tagPrefix, releaseCount = 1 }) => {
|
|
636
644
|
const pkgDir = getPkgDir();
|
|
637
645
|
const preset = await parsePreset();
|
|
638
|
-
return new ConventionalChangelog().readPackage(`${pkgDir}/package.json`).config(preset).options({ releaseCount
|
|
646
|
+
return new ConventionalChangelog().readPackage(`${pkgDir}/package.json`).config(preset).options({ releaseCount }).commits({ path: pkgDir }).tags({ prefix: tagPrefix });
|
|
639
647
|
};
|
|
640
|
-
const getChangelog = async ({ getPkgDir, tagPrefix }) => {
|
|
648
|
+
const getChangelog = async ({ getPkgDir, tagPrefix, releaseCount = 1 }) => {
|
|
641
649
|
const generator = await createGenerator({
|
|
642
650
|
getPkgDir,
|
|
643
|
-
tagPrefix
|
|
651
|
+
tagPrefix,
|
|
652
|
+
releaseCount
|
|
644
653
|
});
|
|
645
654
|
let changelog = "";
|
|
646
655
|
for await (const chunk of generator.write()) changelog += chunk;
|
|
647
656
|
return changelog;
|
|
648
657
|
};
|
|
649
|
-
const generateChangelog = async ({ getPkgDir, tagPrefix }) => {
|
|
658
|
+
const generateChangelog = async ({ getPkgDir, tagPrefix, releaseCount = 1 }) => {
|
|
650
659
|
const infile = join(getPkgDir(), "CHANGELOG.md");
|
|
651
660
|
if (!existsSync(infile)) await writeFile(infile, "");
|
|
652
661
|
const exist = readFileSync(infile, "utf-8");
|
|
662
|
+
const writeStream = createWriteStream(infile);
|
|
653
663
|
const generator = await createGenerator({
|
|
654
664
|
getPkgDir,
|
|
655
|
-
tagPrefix
|
|
665
|
+
tagPrefix,
|
|
666
|
+
releaseCount
|
|
656
667
|
});
|
|
657
|
-
const writeStream = createWriteStream(infile);
|
|
658
668
|
for await (const chunk of generator.write()) writeStream.write(chunk);
|
|
659
|
-
|
|
660
|
-
|
|
669
|
+
const override = isZero(releaseCount);
|
|
670
|
+
if (!(isZero(exist.trim().length) || override)) {
|
|
671
|
+
writeStream.write(eol());
|
|
672
|
+
writeStream.write(exist);
|
|
673
|
+
}
|
|
661
674
|
writeStream.end();
|
|
662
675
|
await finished(writeStream);
|
|
663
676
|
};
|
|
@@ -776,7 +789,7 @@ const createCReleaseByTag = async (octokit, options) => {
|
|
|
776
789
|
const existing = await getReleaseByTagSafe(octokit, options);
|
|
777
790
|
if (!existing) return createCRelease(octokit, { ...options });
|
|
778
791
|
const { draft, id: releaseId } = existing;
|
|
779
|
-
if (!draft) throw new Error(
|
|
792
|
+
if (!draft) throw new Error(MSG.ERROR.GITHUB_TAG_EXIT(options.tag));
|
|
780
793
|
return updateCRelease(octokit, {
|
|
781
794
|
releaseId,
|
|
782
795
|
...options
|
|
@@ -919,15 +932,32 @@ const runNpmOptPrompts = async (ctx, config) => {
|
|
|
919
932
|
};
|
|
920
933
|
//#endregion
|
|
921
934
|
//#region src/npm/publish.ts
|
|
935
|
+
const canPublish = async (registry) => {
|
|
936
|
+
const res = await runNpm([
|
|
937
|
+
"publish",
|
|
938
|
+
"--dry-run",
|
|
939
|
+
"--no-git-checks",
|
|
940
|
+
"--access",
|
|
941
|
+
"public",
|
|
942
|
+
...registryArg(registry)
|
|
943
|
+
], { error: "throw" }).catch((err) => err);
|
|
944
|
+
if (!(res instanceof Error)) return true;
|
|
945
|
+
return [/previously published versions/i, /cannot publish over/i].some((reg) => reg.test(res.message));
|
|
946
|
+
};
|
|
922
947
|
const npmCheck = async (ctx, config) => {
|
|
923
948
|
const { pkg: { name, current, publishConfig: { registry } } } = ctx;
|
|
924
949
|
const { npm: { skipChecks } } = config;
|
|
925
950
|
const tag = await resolvePublishTag(name, current);
|
|
926
951
|
Object.assign(ctx.npm, { tag });
|
|
927
952
|
if (skipChecks) return "";
|
|
928
|
-
const [pinged, username] = await Promise.all([
|
|
953
|
+
const [pinged, username, canPublished] = await Promise.all([
|
|
954
|
+
pingRegistry(registry),
|
|
955
|
+
getAuthenticatedUser(registry),
|
|
956
|
+
canPublish(registry)
|
|
957
|
+
]);
|
|
929
958
|
if (!pinged) throw new Error(MSG.ERROR.NPM_REGISTRY(registry));
|
|
930
959
|
if (!username) throw new Error(MSG.ERROR.NPM_AUTH);
|
|
960
|
+
if (!canPublished) throw new Error(MSG.ERROR.NPM_PERMISSION);
|
|
931
961
|
Object.assign(ctx.npm, { username });
|
|
932
962
|
const latest = await getPublishedVersion(`${name}@${tag}`);
|
|
933
963
|
if (latest) {
|
|
@@ -1077,7 +1107,7 @@ var Action = class {
|
|
|
1077
1107
|
}
|
|
1078
1108
|
async bumpTask(ctx, config) {
|
|
1079
1109
|
const { pkg: { current }, dryRun, isCI, showRelease, showChangelog, selectedPkg, noGit } = ctx;
|
|
1080
|
-
const { isMonorepo, hooks, getPkgDir, tagPrefix } = config;
|
|
1110
|
+
const { isMonorepo, hooks, getPkgDir, changelog: { tagPrefix, releaseCount } } = config;
|
|
1081
1111
|
const need = (ctx) => {
|
|
1082
1112
|
const { pkg: { next }, isIncrement } = ctx;
|
|
1083
1113
|
return !next && isIncrement;
|
|
@@ -1107,11 +1137,16 @@ var Action = class {
|
|
|
1107
1137
|
}]).catch((err) => abortOnError(err, ctx));
|
|
1108
1138
|
await runLifeCycleHook(hooks, "after:bump", dryRun);
|
|
1109
1139
|
if (noGit) return;
|
|
1110
|
-
const
|
|
1140
|
+
const match = isMonorepo ? `${tagPrefix?.(selectedPkg)}*` : "*";
|
|
1141
|
+
const { from, to } = isZero(releaseCount) ? {
|
|
1142
|
+
from: "",
|
|
1143
|
+
to: "HEAD"
|
|
1144
|
+
} : await resolveChangelogRange(isIncrement, match);
|
|
1111
1145
|
const commits = await getLog(from, to, getPkgDir(selectedPkg));
|
|
1112
1146
|
const changelog = await getChangelog({
|
|
1113
1147
|
getPkgDir: () => getPkgDir(selectedPkg),
|
|
1114
|
-
tagPrefix: tagPrefix?.(selectedPkg)
|
|
1148
|
+
tagPrefix: tagPrefix?.(selectedPkg),
|
|
1149
|
+
releaseCount
|
|
1115
1150
|
});
|
|
1116
1151
|
Object.assign(ctx.github, { changelog });
|
|
1117
1152
|
if (commits) {
|
|
@@ -1122,14 +1157,15 @@ var Action = class {
|
|
|
1122
1157
|
}
|
|
1123
1158
|
async changelogTask(ctx, config) {
|
|
1124
1159
|
const { isIncrement, dryRun, selectedPkg, noGit } = ctx;
|
|
1125
|
-
const { getPkgDir, tagPrefix } = config;
|
|
1160
|
+
const { getPkgDir, changelog: { tagPrefix, releaseCount } } = config;
|
|
1126
1161
|
if (noGit) return;
|
|
1127
1162
|
await tasks([{
|
|
1128
1163
|
title: MSG.TASK.CHANGELOG.START,
|
|
1129
1164
|
task: async () => {
|
|
1130
1165
|
await generateChangelog({
|
|
1131
1166
|
getPkgDir: () => getPkgDir(selectedPkg),
|
|
1132
|
-
tagPrefix: tagPrefix?.(selectedPkg)
|
|
1167
|
+
tagPrefix: tagPrefix?.(selectedPkg),
|
|
1168
|
+
releaseCount
|
|
1133
1169
|
});
|
|
1134
1170
|
await gitAddAll();
|
|
1135
1171
|
return success(MSG.TASK.CHANGELOG.END, dryRun);
|
|
@@ -1222,7 +1258,9 @@ program.command("init").description("Create a release configuration file").optio
|
|
|
1222
1258
|
packages: [ 'demo-a', 'demo-b' ],
|
|
1223
1259
|
getPkgDir: (pkg) => \`packages/\${ pkg }\`,
|
|
1224
1260
|
toTag: (pkg, version) => \`\${ pkg }@\${ version }\`,
|
|
1225
|
-
|
|
1261
|
+
changelog: {
|
|
1262
|
+
tagPrefix: (pkg) => \`\${ pkg }@\`,
|
|
1263
|
+
},
|
|
1226
1264
|
}`;
|
|
1227
1265
|
writeFileSync(configPath, [`import { defineConfig } from '@peiyanlu/release'`, `export default defineConfig(${monorepo ? monoConfigToString() : "{}"})`].join(eol(2)), "utf-8");
|
|
1228
1266
|
console.log(`${green`✔`} ${infile} created successfully`);
|
package/dist/index.d.mts
CHANGED
|
@@ -23,14 +23,20 @@ interface ReleaseConfig {
|
|
|
23
23
|
getPkgDir: (pkg: string) => string;
|
|
24
24
|
/** 使用 monorepo 时使用 toTag,例如 `${pkg}@${version}`,默认为 `v${version}` 作为单仓库 */
|
|
25
25
|
toTag: (pkg: string, version: string) => string;
|
|
26
|
-
/**
|
|
27
|
-
|
|
26
|
+
/**
|
|
27
|
+
* CHANGELOG 相关配置
|
|
28
|
+
* 影响生成的日志数量、日志标题(monorepo)。
|
|
29
|
+
*/
|
|
30
|
+
changelog: {
|
|
31
|
+
/** 作为 CHANGELOG 标题的 Tag 前缀,多包场景下需要 `${pkg}@` */tagPrefix: ((pkg: string) => string); /** 生成多少个版本的变更日志,详见 {@link Options} */
|
|
32
|
+
releaseCount: number;
|
|
33
|
+
};
|
|
28
34
|
/** 忽略 git、github 环境检查以及后续操作 */
|
|
29
|
-
ignoreGit: boolean
|
|
35
|
+
ignoreGit: boolean;
|
|
30
36
|
/** 忽略 npm 环境检查以及后续操作 */
|
|
31
|
-
ignoreNpm: boolean
|
|
37
|
+
ignoreNpm: boolean;
|
|
32
38
|
/** 忽略 github 环境检查以及后续操作 */
|
|
33
|
-
ignoreGithub: boolean
|
|
39
|
+
ignoreGithub: boolean;
|
|
34
40
|
/**
|
|
35
41
|
* Git 相关配置
|
|
36
42
|
* 影响提交、打 tag、推送等本地/远程 Git 行为。
|
|
@@ -156,27 +162,32 @@ declare function defineConfig(config: UserConfigFnObject): UserConfigFnObject;
|
|
|
156
162
|
declare function defineConfig(config: UserConfigFnPromise): UserConfigFnPromise;
|
|
157
163
|
declare function defineConfig(config: UserConfigFn): UserConfigFn;
|
|
158
164
|
declare function defineConfig(config: UserConfigExport): UserConfigExport;
|
|
159
|
-
declare const mergeConfig: <T extends object>(defaults: DeepRequired<T>, overrides
|
|
165
|
+
declare const mergeConfig: <T extends object>(defaults: DeepRequired<T>, overrides: DeepPartial<T>) => DeepRequired<T>;
|
|
160
166
|
//#endregion
|
|
161
167
|
//#region src/git/changelog.d.ts
|
|
162
|
-
interface
|
|
168
|
+
interface GenerateOptions {
|
|
163
169
|
/** @example () => `packages/${pkg}` */
|
|
164
170
|
getPkgDir: () => string;
|
|
165
171
|
/** @example `${pkg}@` */
|
|
166
172
|
tagPrefix?: string;
|
|
173
|
+
/** 生成多少个变更日志,详见 {@link Options} */
|
|
174
|
+
releaseCount?: number;
|
|
167
175
|
}
|
|
168
176
|
declare const createGenerator: ({
|
|
169
177
|
getPkgDir,
|
|
170
|
-
tagPrefix
|
|
171
|
-
|
|
178
|
+
tagPrefix,
|
|
179
|
+
releaseCount
|
|
180
|
+
}: GenerateOptions) => Promise<ConventionalChangelog>;
|
|
172
181
|
declare const getChangelog: ({
|
|
173
182
|
getPkgDir,
|
|
174
|
-
tagPrefix
|
|
175
|
-
|
|
183
|
+
tagPrefix,
|
|
184
|
+
releaseCount
|
|
185
|
+
}: GenerateOptions) => Promise<string>;
|
|
176
186
|
declare const generateChangelog: ({
|
|
177
187
|
getPkgDir,
|
|
178
|
-
tagPrefix
|
|
179
|
-
|
|
188
|
+
tagPrefix,
|
|
189
|
+
releaseCount
|
|
190
|
+
}: GenerateOptions) => Promise<void>;
|
|
180
191
|
//#endregion
|
|
181
192
|
//#region src/npm/publish.d.ts
|
|
182
193
|
interface PublishTagOptions {
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isFunction, isPlainObject } from "@peiyanlu/ts-utils";
|
|
1
|
+
import { isFunction, isPlainObject, isUndefined, isZero } from "@peiyanlu/ts-utils";
|
|
2
2
|
import { createWriteStream, existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { eol, getPackageInfo, publishPackage, resolvePublishTag } from "@peiyanlu/cli-utils";
|
|
@@ -12,13 +12,12 @@ function defineConfig(config) {
|
|
|
12
12
|
return config;
|
|
13
13
|
}
|
|
14
14
|
const mergeConfig = (defaults, overrides) => {
|
|
15
|
-
if (!overrides) return structuredClone(defaults);
|
|
16
|
-
if (Object.keys(defaults).length === 0) return structuredClone(overrides);
|
|
17
15
|
const result = {};
|
|
18
|
-
for (const key
|
|
16
|
+
for (const key of Object.keys(defaults)) {
|
|
19
17
|
const defaultValue = defaults[key];
|
|
20
18
|
const overrideValue = overrides[key];
|
|
21
|
-
if (overrideValue
|
|
19
|
+
if (isUndefined(overrideValue)) if (isFunction(defaultValue)) result[key] = defaultValue;
|
|
20
|
+
else if (isPlainObject(defaultValue)) result[key] = mergeConfig(defaultValue, {});
|
|
22
21
|
else result[key] = structuredClone(defaultValue);
|
|
23
22
|
else if (isPlainObject(defaultValue) && isPlainObject(overrideValue)) result[key] = mergeConfig(defaultValue, overrideValue);
|
|
24
23
|
else if (isFunction(overrideValue)) result[key] = overrideValue;
|
|
@@ -66,42 +65,42 @@ const defaultTypes = [
|
|
|
66
65
|
},
|
|
67
66
|
{
|
|
68
67
|
type: "chore",
|
|
69
|
-
section: "
|
|
68
|
+
section: "🧹 其他更新",
|
|
70
69
|
description: "非功能性更改"
|
|
71
70
|
},
|
|
72
71
|
{
|
|
73
72
|
type: "refactor",
|
|
74
|
-
section: "
|
|
73
|
+
section: "♻️ 代码重构",
|
|
75
74
|
description: "重构代码"
|
|
76
75
|
},
|
|
77
76
|
{
|
|
78
77
|
type: "test",
|
|
79
|
-
section: "
|
|
78
|
+
section: "🧪 测试",
|
|
80
79
|
description: "测试更新"
|
|
81
80
|
},
|
|
82
81
|
{
|
|
83
82
|
type: "build",
|
|
84
|
-
section: "
|
|
83
|
+
section: "🏗️ 构建系统",
|
|
85
84
|
description: "构建工具和系统修改"
|
|
86
85
|
},
|
|
87
86
|
{
|
|
88
87
|
type: "ci",
|
|
89
|
-
section: "
|
|
88
|
+
section: "🤖 CI",
|
|
90
89
|
description: "持续集成配置"
|
|
91
90
|
},
|
|
92
91
|
{
|
|
93
92
|
type: "config",
|
|
94
|
-
section: "
|
|
93
|
+
section: "⚙️ 配置",
|
|
95
94
|
description: "配置文件更新"
|
|
96
95
|
},
|
|
97
96
|
{
|
|
98
97
|
type: "deps",
|
|
99
|
-
section: "
|
|
98
|
+
section: "📦 依赖更新",
|
|
100
99
|
description: "依赖版本变更"
|
|
101
100
|
},
|
|
102
101
|
{
|
|
103
102
|
type: "security",
|
|
104
|
-
section: "
|
|
103
|
+
section: "🛡️ 安全修复",
|
|
105
104
|
description: "安全性更新"
|
|
106
105
|
},
|
|
107
106
|
{
|
|
@@ -111,13 +110,18 @@ const defaultTypes = [
|
|
|
111
110
|
},
|
|
112
111
|
{
|
|
113
112
|
type: "ux",
|
|
114
|
-
section: "
|
|
113
|
+
section: "🎨 用户体验",
|
|
115
114
|
description: "用户体验改进"
|
|
116
115
|
},
|
|
117
116
|
{
|
|
118
117
|
type: "hotfix",
|
|
119
|
-
section: "
|
|
118
|
+
section: "🚑 热修复",
|
|
120
119
|
description: "紧急修复"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
type: "tool",
|
|
123
|
+
section: "🛠️ 工具链",
|
|
124
|
+
description: "工具链变更"
|
|
121
125
|
}
|
|
122
126
|
];
|
|
123
127
|
//#endregion
|
|
@@ -177,32 +181,37 @@ const parsePreset = async () => {
|
|
|
177
181
|
{{/each}}`.trim();
|
|
178
182
|
return preset;
|
|
179
183
|
};
|
|
180
|
-
const createGenerator = async ({ getPkgDir, tagPrefix }) => {
|
|
184
|
+
const createGenerator = async ({ getPkgDir, tagPrefix, releaseCount = 1 }) => {
|
|
181
185
|
const pkgDir = getPkgDir();
|
|
182
186
|
const preset = await parsePreset();
|
|
183
|
-
return new ConventionalChangelog().readPackage(`${pkgDir}/package.json`).config(preset).options({ releaseCount
|
|
187
|
+
return new ConventionalChangelog().readPackage(`${pkgDir}/package.json`).config(preset).options({ releaseCount }).commits({ path: pkgDir }).tags({ prefix: tagPrefix });
|
|
184
188
|
};
|
|
185
|
-
const getChangelog = async ({ getPkgDir, tagPrefix }) => {
|
|
189
|
+
const getChangelog = async ({ getPkgDir, tagPrefix, releaseCount = 1 }) => {
|
|
186
190
|
const generator = await createGenerator({
|
|
187
191
|
getPkgDir,
|
|
188
|
-
tagPrefix
|
|
192
|
+
tagPrefix,
|
|
193
|
+
releaseCount
|
|
189
194
|
});
|
|
190
195
|
let changelog = "";
|
|
191
196
|
for await (const chunk of generator.write()) changelog += chunk;
|
|
192
197
|
return changelog;
|
|
193
198
|
};
|
|
194
|
-
const generateChangelog = async ({ getPkgDir, tagPrefix }) => {
|
|
199
|
+
const generateChangelog = async ({ getPkgDir, tagPrefix, releaseCount = 1 }) => {
|
|
195
200
|
const infile = join(getPkgDir(), "CHANGELOG.md");
|
|
196
201
|
if (!existsSync(infile)) await writeFile(infile, "");
|
|
197
202
|
const exist = readFileSync(infile, "utf-8");
|
|
203
|
+
const writeStream = createWriteStream(infile);
|
|
198
204
|
const generator = await createGenerator({
|
|
199
205
|
getPkgDir,
|
|
200
|
-
tagPrefix
|
|
206
|
+
tagPrefix,
|
|
207
|
+
releaseCount
|
|
201
208
|
});
|
|
202
|
-
const writeStream = createWriteStream(infile);
|
|
203
209
|
for await (const chunk of generator.write()) writeStream.write(chunk);
|
|
204
|
-
|
|
205
|
-
|
|
210
|
+
const override = isZero(releaseCount);
|
|
211
|
+
if (!(isZero(exist.trim().length) || override)) {
|
|
212
|
+
writeStream.write(eol());
|
|
213
|
+
writeStream.write(exist);
|
|
214
|
+
}
|
|
206
215
|
writeStream.end();
|
|
207
216
|
await finished(writeStream);
|
|
208
217
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peiyanlu/release",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"description": "Release project tool.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"dev": "tsdown -w",
|
|
22
22
|
"build": "tsdown",
|
|
23
|
-
"
|
|
23
|
+
"prepublishOnly": "tsdown",
|
|
24
24
|
"release": "node index.js",
|
|
25
25
|
"test": "vitest run",
|
|
26
26
|
"test:cov": "vitest run --coverage"
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"@actions/github": "^9.1.1",
|
|
31
31
|
"@clack/prompts": "^1.5.0",
|
|
32
32
|
"@octokit/rest": "^22.0.1",
|
|
33
|
-
"@peiyanlu/cli-utils": "^0.0.
|
|
34
|
-
"@peiyanlu/ts-utils": "^0.0.
|
|
33
|
+
"@peiyanlu/cli-utils": "^0.0.9",
|
|
34
|
+
"@peiyanlu/ts-utils": "^0.0.7",
|
|
35
35
|
"ansis": "^4.3.1",
|
|
36
36
|
"commander": "^15.0.0",
|
|
37
37
|
"conventional-changelog": "^7.2.0",
|