@varlet/release 0.4.3 → 1.0.0
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 +163 -161
- package/README.zh-CN.md +163 -161
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +19 -0
- package/dist/index.d.ts +39 -26
- package/dist/index.js +278 -303
- package/package.json +37 -35
- package/bin/index.js +0 -47
- package/dist/index.cjs +0 -413
- package/dist/index.d.cts +0 -41
package/dist/index.js
CHANGED
|
@@ -1,305 +1,293 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { confirm, select } from "@
|
|
4
|
-
import
|
|
5
|
-
import { glob } from "glob";
|
|
6
|
-
import { createSpinner as createSpinner2 } from "nanospinner";
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { styleText } from "node:util";
|
|
3
|
+
import { cancel, confirm, isCancel, select, spinner } from "@clack/prompts";
|
|
4
|
+
import fse from "fs-extra";
|
|
7
5
|
import { logger } from "rslog";
|
|
8
6
|
import semver from "semver";
|
|
9
|
-
import { x
|
|
10
|
-
|
|
11
|
-
// src/changelog.ts
|
|
12
|
-
import { resolve as resolvePath } from "path";
|
|
7
|
+
import { x } from "tinyexec";
|
|
13
8
|
import conventionalChangelog from "conventional-changelog";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
function changelog({
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
commit.subject = commit.subject.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => {
|
|
69
|
-
if (username.includes("/")) {
|
|
70
|
-
return `@${username}`;
|
|
71
|
-
}
|
|
72
|
-
return `[@${username}](${context.host}/${username})`;
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
commit.references = commit.references.filter((reference) => {
|
|
77
|
-
if (issues.indexOf(reference.issue) === -1) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
return false;
|
|
81
|
-
});
|
|
82
|
-
return commit;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
} = {}) {
|
|
86
|
-
const s = createSpinner("Generating changelog").start();
|
|
87
|
-
return new Promise((resolve2) => {
|
|
88
|
-
conventionalChangelog(
|
|
89
|
-
{
|
|
90
|
-
preset,
|
|
91
|
-
releaseCount
|
|
92
|
-
},
|
|
93
|
-
void 0,
|
|
94
|
-
void 0,
|
|
95
|
-
void 0,
|
|
96
|
-
writerOpts
|
|
97
|
-
).pipe(createWriteStream(resolvePath(process.cwd(), file))).on("close", () => {
|
|
98
|
-
s.success({ text: "Changelog generated success!" });
|
|
99
|
-
resolve2();
|
|
100
|
-
});
|
|
101
|
-
});
|
|
9
|
+
|
|
10
|
+
//#region src/changelog.ts
|
|
11
|
+
const { createWriteStream } = fse;
|
|
12
|
+
function changelog({ releaseCount = 0, file = "CHANGELOG.md", preset = "angular", writerOpts = { transform(commit, context) {
|
|
13
|
+
let discard = true;
|
|
14
|
+
const issues = [];
|
|
15
|
+
commit.notes.forEach((note) => {
|
|
16
|
+
note.title = "BREAKING CHANGES";
|
|
17
|
+
discard = false;
|
|
18
|
+
});
|
|
19
|
+
if (commit.type === "feat") commit.type = "Features";
|
|
20
|
+
else if (commit.type === "fix") commit.type = "Bug Fixes";
|
|
21
|
+
else if (commit.type === "perf") commit.type = "Performance Improvements";
|
|
22
|
+
else if (commit.type === "revert" || commit.revert) commit.type = "Reverts";
|
|
23
|
+
else if (commit.type === "refactor") commit.type = "Code Refactoring";
|
|
24
|
+
else if (discard) return false;
|
|
25
|
+
else if (commit.type === "docs") commit.type = "Documentation";
|
|
26
|
+
else if (commit.type === "style") commit.type = "Styles";
|
|
27
|
+
else if (commit.type === "test") commit.type = "Tests";
|
|
28
|
+
else if (commit.type === "build") commit.type = "Build System";
|
|
29
|
+
else if (commit.type === "ci") commit.type = "Continuous Integration";
|
|
30
|
+
if (commit.scope === "*") commit.scope = "";
|
|
31
|
+
if (typeof commit.hash === "string") commit.shortHash = commit.hash.substring(0, 7);
|
|
32
|
+
if (typeof commit.subject === "string") {
|
|
33
|
+
let url = context.repository ? `${context.host}/${context.owner}/${context.repository}` : context.repoUrl;
|
|
34
|
+
if (url) {
|
|
35
|
+
url = `${url}/issues/`;
|
|
36
|
+
commit.subject = commit.subject.replace(/#([0-9]+)/g, (_, issue) => {
|
|
37
|
+
issues.push(issue);
|
|
38
|
+
return `[#${issue}](${url}${issue})`;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (context.host) commit.subject = commit.subject.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => {
|
|
42
|
+
if (username.includes("/")) return `@${username}`;
|
|
43
|
+
return `[@${username}](${context.host}/${username})`;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
commit.references = commit.references.filter((reference) => {
|
|
47
|
+
if (issues.indexOf(reference.issue) === -1) return true;
|
|
48
|
+
return false;
|
|
49
|
+
});
|
|
50
|
+
return commit;
|
|
51
|
+
} } } = {}) {
|
|
52
|
+
const s = spinner();
|
|
53
|
+
s.start("Generating changelog");
|
|
54
|
+
return new Promise((resolve$1) => {
|
|
55
|
+
conventionalChangelog({
|
|
56
|
+
preset,
|
|
57
|
+
releaseCount
|
|
58
|
+
}, void 0, void 0, void 0, writerOpts).pipe(createWriteStream(resolve(process.cwd(), file))).on("close", () => {
|
|
59
|
+
s.stop("Changelog generated successfully!");
|
|
60
|
+
resolve$1();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
102
63
|
}
|
|
103
64
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/release.ts
|
|
67
|
+
const cwd = process.cwd();
|
|
68
|
+
const { writeFileSync, readJSONSync, existsSync, readdirSync } = fse;
|
|
69
|
+
const releaseTypes = [
|
|
70
|
+
"patch",
|
|
71
|
+
"minor",
|
|
72
|
+
"major",
|
|
73
|
+
"prepatch",
|
|
74
|
+
"preminor",
|
|
75
|
+
"premajor"
|
|
76
|
+
];
|
|
77
|
+
const BACK_HINT = "Back to previous step";
|
|
109
78
|
async function isWorktreeEmpty() {
|
|
110
|
-
|
|
111
|
-
return !ret.stdout;
|
|
79
|
+
return !(await x("git", ["status", "--porcelain"])).stdout;
|
|
112
80
|
}
|
|
113
81
|
async function isSameVersion(version) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
82
|
+
const s = spinner();
|
|
83
|
+
s.start("Check remote version...");
|
|
84
|
+
const packageJsones = getPackageJsons();
|
|
85
|
+
const packageJson = packageJsones.find((packageJson) => !packageJson.config.private) || packageJsones[0];
|
|
86
|
+
if (packageJson) {
|
|
87
|
+
const { config } = packageJson;
|
|
88
|
+
try {
|
|
89
|
+
await x("npm", [
|
|
90
|
+
"view",
|
|
91
|
+
`${config.name}@${version ?? config.version}`,
|
|
92
|
+
"version"
|
|
93
|
+
], { throwOnError: true });
|
|
94
|
+
s.cancel();
|
|
95
|
+
logger.warn(`The npm package has a same remote version ${version ?? config.version}.`);
|
|
96
|
+
return true;
|
|
97
|
+
} catch {
|
|
98
|
+
s.stop();
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
132
102
|
}
|
|
133
103
|
async function publish({ preRelease, checkRemoteVersion, npmTag }) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
104
|
+
const s = spinner();
|
|
105
|
+
s.start("Publishing all packages");
|
|
106
|
+
const args = [
|
|
107
|
+
"-r",
|
|
108
|
+
"publish",
|
|
109
|
+
"--no-git-checks",
|
|
110
|
+
"--access",
|
|
111
|
+
"public"
|
|
112
|
+
];
|
|
113
|
+
if (checkRemoteVersion && await isSameVersion()) {
|
|
114
|
+
logger.error("publishing automatically skipped.");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (preRelease) args.push("--tag", "alpha");
|
|
118
|
+
else if (npmTag) args.push("--tag", npmTag);
|
|
119
|
+
try {
|
|
120
|
+
const ret = await x("pnpm", args, { throwOnError: true });
|
|
121
|
+
s.stop("Publish all packages successfully");
|
|
122
|
+
ret.stdout && logger.log(ret.stdout);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
s.cancel("Publish all packages failed");
|
|
125
|
+
throw error?.output?.stderr ?? error;
|
|
126
|
+
}
|
|
152
127
|
}
|
|
153
128
|
async function pushGit(version, remote = "origin", skipGitTag = false) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
129
|
+
const s = spinner();
|
|
130
|
+
s.start("Pushing to remote git repository");
|
|
131
|
+
await x("git", ["add", "."], { throwOnError: true });
|
|
132
|
+
await x("git", [
|
|
133
|
+
"commit",
|
|
134
|
+
"-m",
|
|
135
|
+
`v${version}`
|
|
136
|
+
], { throwOnError: true });
|
|
137
|
+
if (!skipGitTag) {
|
|
138
|
+
await x("git", ["tag", `v${version}`], { throwOnError: true });
|
|
139
|
+
await x("git", [
|
|
140
|
+
"push",
|
|
141
|
+
remote,
|
|
142
|
+
`v${version}`
|
|
143
|
+
], { throwOnError: true });
|
|
144
|
+
}
|
|
145
|
+
const ret = await x("git", ["push"], { throwOnError: true });
|
|
146
|
+
s.stop("Push remote repository successfully");
|
|
147
|
+
ret.stdout && logger.log(ret.stdout);
|
|
148
|
+
}
|
|
149
|
+
function getAllPackageJsons() {
|
|
150
|
+
const result = [resolve(cwd, "package.json")];
|
|
151
|
+
const packagesDir = resolve(cwd, "packages");
|
|
152
|
+
if (existsSync(packagesDir)) for (const name of readdirSync(packagesDir)) {
|
|
153
|
+
const pkgPath = resolve(packagesDir, name, "package.json");
|
|
154
|
+
if (existsSync(pkgPath)) result.push(pkgPath);
|
|
155
|
+
}
|
|
156
|
+
return result;
|
|
174
157
|
}
|
|
175
158
|
function getPackageJsons() {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
};
|
|
183
|
-
});
|
|
159
|
+
return getAllPackageJsons().map((path) => {
|
|
160
|
+
return {
|
|
161
|
+
config: readJSONSync(path),
|
|
162
|
+
filePath: path
|
|
163
|
+
};
|
|
164
|
+
});
|
|
184
165
|
}
|
|
185
166
|
function updateVersion(version) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
});
|
|
167
|
+
getPackageJsons().forEach(({ config, filePath }) => {
|
|
168
|
+
config.version = version;
|
|
169
|
+
writeFileSync(filePath, JSON.stringify(config, null, 2));
|
|
170
|
+
});
|
|
191
171
|
}
|
|
192
172
|
async function confirmRegistry() {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
173
|
+
const registry = (await x("npm", [
|
|
174
|
+
"config",
|
|
175
|
+
"get",
|
|
176
|
+
"registry"
|
|
177
|
+
])).stdout;
|
|
178
|
+
const ret = await confirm({ message: `Current registry is: ${registry}` });
|
|
179
|
+
if (isCancel(ret)) {
|
|
180
|
+
cancel("Operation cancelled.");
|
|
181
|
+
process.exit(0);
|
|
182
|
+
}
|
|
183
|
+
return ret;
|
|
198
184
|
}
|
|
199
185
|
async function confirmVersion(currentVersion, expectVersion) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
186
|
+
const ret = await select({
|
|
187
|
+
message: "Version confirm",
|
|
188
|
+
options: [`All packages version ${currentVersion} -> ${expectVersion}`, BACK_HINT].map((value) => ({
|
|
189
|
+
label: value,
|
|
190
|
+
value
|
|
191
|
+
}))
|
|
192
|
+
});
|
|
193
|
+
if (isCancel(ret)) {
|
|
194
|
+
cancel("Operation cancelled.");
|
|
195
|
+
process.exit(0);
|
|
196
|
+
}
|
|
197
|
+
return ret;
|
|
208
198
|
}
|
|
209
199
|
async function confirmRefs(remote = "origin") {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
200
|
+
const { stdout } = await x("git", ["remote", "-v"]);
|
|
201
|
+
const reg = new RegExp(`${remote}\t(.*) \\(push`);
|
|
202
|
+
const repo = stdout.match(reg)?.[1];
|
|
203
|
+
const { stdout: branch } = await x("git", ["branch", "--show-current"]);
|
|
204
|
+
const ret = await confirm({ message: `Current refs ${repo}:refs/for/${styleText("blue", branch)}` });
|
|
205
|
+
if (isCancel(ret)) {
|
|
206
|
+
cancel("Operation cancelled.");
|
|
207
|
+
process.exit(0);
|
|
208
|
+
}
|
|
209
|
+
return ret;
|
|
218
210
|
}
|
|
219
211
|
async function getReleaseType() {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
212
|
+
const releaseType = await select({
|
|
213
|
+
message: "Please select release type",
|
|
214
|
+
options: releaseTypes.map((type) => ({
|
|
215
|
+
label: type,
|
|
216
|
+
value: type
|
|
217
|
+
}))
|
|
218
|
+
});
|
|
219
|
+
if (isCancel(releaseType)) {
|
|
220
|
+
cancel("Operation cancelled.");
|
|
221
|
+
process.exit(0);
|
|
222
|
+
}
|
|
223
|
+
return releaseType;
|
|
225
224
|
}
|
|
226
225
|
async function getReleaseVersion(currentVersion) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
226
|
+
let isPreRelease = false;
|
|
227
|
+
let expectVersion = "";
|
|
228
|
+
let confirmVersionRet = "";
|
|
229
|
+
do {
|
|
230
|
+
const type = await getReleaseType();
|
|
231
|
+
isPreRelease = type.startsWith("pre");
|
|
232
|
+
expectVersion = semver.inc(currentVersion, type, `alpha.${Date.now()}`);
|
|
233
|
+
expectVersion = isPreRelease ? expectVersion.slice(0, -2) : expectVersion;
|
|
234
|
+
confirmVersionRet = await confirmVersion(currentVersion, expectVersion);
|
|
235
|
+
} while (confirmVersionRet === BACK_HINT);
|
|
236
|
+
return {
|
|
237
|
+
isPreRelease,
|
|
238
|
+
expectVersion
|
|
239
|
+
};
|
|
238
240
|
}
|
|
239
241
|
async function release(options) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
} catch {
|
|
281
|
-
}
|
|
282
|
-
try {
|
|
283
|
-
await exec("git", ["restore", "package.json"], {
|
|
284
|
-
throwOnError: true
|
|
285
|
-
});
|
|
286
|
-
} catch {
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
} catch (error) {
|
|
290
|
-
logger.error(error.toString());
|
|
291
|
-
process.exit(1);
|
|
292
|
-
}
|
|
242
|
+
try {
|
|
243
|
+
const currentVersion = readJSONSync(resolve(cwd, "package.json")).version;
|
|
244
|
+
if (!currentVersion) {
|
|
245
|
+
logger.error("Your package is missing the version field");
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (!await isWorktreeEmpty()) {
|
|
249
|
+
logger.error("Git worktree is not empty, please commit changed");
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (!await confirmRefs(options.remote)) return;
|
|
253
|
+
if (!options.skipNpmPublish && !await confirmRegistry()) return;
|
|
254
|
+
const { isPreRelease, expectVersion } = await getReleaseVersion(currentVersion);
|
|
255
|
+
if (options.checkRemoteVersion && await isSameVersion(expectVersion)) {
|
|
256
|
+
logger.error("Please check remote version.");
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
updateVersion(expectVersion);
|
|
260
|
+
if (options.task) await options.task(expectVersion, currentVersion);
|
|
261
|
+
if (!options.skipNpmPublish) await publish({
|
|
262
|
+
preRelease: isPreRelease,
|
|
263
|
+
npmTag: options.npmTag
|
|
264
|
+
});
|
|
265
|
+
if (!isPreRelease) {
|
|
266
|
+
if (!options.skipChangelog) await changelog();
|
|
267
|
+
await pushGit(expectVersion, options.remote, options.skipGitTag);
|
|
268
|
+
}
|
|
269
|
+
logger.success(`Release version ${expectVersion} successfully!`);
|
|
270
|
+
if (isPreRelease) {
|
|
271
|
+
try {
|
|
272
|
+
await x("git", ["restore", "**/package.json"], { throwOnError: true });
|
|
273
|
+
} catch {}
|
|
274
|
+
try {
|
|
275
|
+
await x("git", ["restore", "package.json"], { throwOnError: true });
|
|
276
|
+
} catch {}
|
|
277
|
+
}
|
|
278
|
+
} catch (error) {
|
|
279
|
+
logger.error(error);
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}
|
|
293
282
|
}
|
|
294
283
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
var WARNING_MESSAGE = `The rules for commit messages are as follows
|
|
284
|
+
//#endregion
|
|
285
|
+
//#region src/commitLint.ts
|
|
286
|
+
const { readFileSync } = fse;
|
|
287
|
+
const COMMIT_MESSAGE_RE = /^(revert|fix|feat|docs|perf|test|types|style|build|chore|release|refactor|merge|wip)(\(.+\))?!?: (.|\n)+/;
|
|
288
|
+
const ERROR_MESSAGE = "Commit message invalid.";
|
|
289
|
+
const WARNING_MESSAGE = `\
|
|
290
|
+
The rules for commit messages are as follows
|
|
303
291
|
|
|
304
292
|
Example:
|
|
305
293
|
|
|
@@ -329,40 +317,27 @@ Allowed types:
|
|
|
329
317
|
- wip
|
|
330
318
|
|
|
331
319
|
Commit message reference: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y
|
|
332
|
-
|
|
320
|
+
参考阮一峰Commit message编写指南: https://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html`;
|
|
333
321
|
function isVersionCommitMessage(message) {
|
|
334
|
-
|
|
322
|
+
return Boolean(message.startsWith("v") && semver.valid(message.slice(1)));
|
|
335
323
|
}
|
|
336
324
|
function getCommitMessage(commitMessagePath) {
|
|
337
|
-
|
|
325
|
+
return readFileSync(commitMessagePath, "utf-8").trim();
|
|
338
326
|
}
|
|
339
327
|
function commitLint(options) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
if (!isVersionCommitMessage(commitMessage) && !isValidCommitMessage) {
|
|
353
|
-
logger2.error(errorMessage);
|
|
354
|
-
logger2.warn(warningMessage);
|
|
355
|
-
process.exit(1);
|
|
356
|
-
}
|
|
328
|
+
const { commitMessagePath, commitMessageRe = COMMIT_MESSAGE_RE, errorMessage = ERROR_MESSAGE, warningMessage = WARNING_MESSAGE } = options;
|
|
329
|
+
if (!commitMessagePath) {
|
|
330
|
+
logger.error("commitMessagePath is required");
|
|
331
|
+
process.exit(1);
|
|
332
|
+
}
|
|
333
|
+
const commitMessage = getCommitMessage(commitMessagePath);
|
|
334
|
+
const isValidCommitMessage = new RegExp(commitMessageRe).test(commitMessage);
|
|
335
|
+
if (!isVersionCommitMessage(commitMessage) && !isValidCommitMessage) {
|
|
336
|
+
logger.error(errorMessage);
|
|
337
|
+
logger.warn(warningMessage);
|
|
338
|
+
process.exit(1);
|
|
339
|
+
}
|
|
357
340
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
commitLint,
|
|
362
|
-
getCommitMessage,
|
|
363
|
-
isSameVersion,
|
|
364
|
-
isVersionCommitMessage,
|
|
365
|
-
publish,
|
|
366
|
-
release,
|
|
367
|
-
updateVersion
|
|
368
|
-
};
|
|
341
|
+
|
|
342
|
+
//#endregion
|
|
343
|
+
export { COMMIT_MESSAGE_RE, changelog, commitLint, getAllPackageJsons, getCommitMessage, isSameVersion, isVersionCommitMessage, publish, release, updateVersion };
|