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