@modulify/conventional-release 0.1.0 → 0.1.2
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 +44 -1
- package/bin/cli.cjs +29 -305
- package/bin/cli.mjs +27 -288
- package/dist/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/cli/args.cjs +67 -0
- package/dist/cli/args.mjs +65 -0
- package/dist/cli/output.cjs +51 -0
- package/dist/cli/output.mjs +46 -0
- package/dist/cli/reporter.cjs +127 -0
- package/dist/cli/reporter.mjs +127 -0
- package/dist/config.cjs +54 -0
- package/dist/config.mjs +51 -0
- package/dist/constants.cjs +16 -0
- package/dist/constants.mjs +12 -0
- package/dist/execute.cjs +192 -0
- package/dist/execute.mjs +190 -0
- package/dist/index.cjs +51 -707
- package/dist/index.mjs +51 -710
- package/dist/plan.cjs +260 -0
- package/dist/plan.mjs +253 -0
- package/dist/reporter.cjs +33 -0
- package/dist/reporter.mjs +27 -0
- package/dist/runtime.cjs +68 -0
- package/dist/runtime.mjs +67 -0
- package/package.json +16 -11
- package/types/release.d.ts +2 -0
package/bin/cli.mjs
CHANGED
|
@@ -1,291 +1,30 @@
|
|
|
1
|
+
import { run } from "../dist/index.mjs";
|
|
2
|
+
import { parseArgv } from "../dist/cli/args.mjs";
|
|
3
|
+
import { createReporter } from "../dist/cli/reporter.mjs";
|
|
4
|
+
import { ConsoleOutput, Output } from "../dist/cli/output.mjs";
|
|
1
5
|
import { GitCommander } from "@modulify/git-toolkit";
|
|
2
6
|
import { Runner } from "@modulify/git-toolkit/shell";
|
|
3
|
-
|
|
4
|
-
import yargs from "yargs";
|
|
5
|
-
import { hideBin } from "yargs/helpers";
|
|
6
|
-
import chalk from "chalk";
|
|
7
|
-
import figures from "figures";
|
|
8
|
-
import * as util from "node:util";
|
|
9
|
-
const DEFAULTS = {
|
|
10
|
-
dry: false,
|
|
11
|
-
verbose: false,
|
|
12
|
-
tags: false
|
|
13
|
-
};
|
|
14
|
-
class CliParseError extends Error {
|
|
15
|
-
help;
|
|
16
|
-
}
|
|
17
|
-
async function parseArgv(argv = process.argv) {
|
|
18
|
-
const parser = yargs(hideBin(argv)).locale("en").scriptName("conventional-release").usage("Usage: $0 [options]").option("release-as", {
|
|
19
|
-
alias: "r",
|
|
20
|
-
describe: "Specify the release type (major|minor|patch)",
|
|
21
|
-
requiresArg: true,
|
|
22
|
-
string: true
|
|
23
|
-
}).option("prerelease", {
|
|
24
|
-
alias: "p",
|
|
25
|
-
describe: "Specify the prerelease type (alpha|beta|rc)",
|
|
26
|
-
requiresArg: true,
|
|
27
|
-
string: true
|
|
28
|
-
}).option("dry", {
|
|
29
|
-
type: "boolean",
|
|
30
|
-
default: DEFAULTS.dry,
|
|
31
|
-
describe: "See the commands that running release would run"
|
|
32
|
-
}).option("verbose", {
|
|
33
|
-
type: "boolean",
|
|
34
|
-
default: DEFAULTS.verbose,
|
|
35
|
-
describe: "Show detailed per-slice progress output"
|
|
36
|
-
}).option("tags", {
|
|
37
|
-
type: "boolean",
|
|
38
|
-
default: DEFAULTS.tags,
|
|
39
|
-
describe: "Show generated tags in the final output"
|
|
40
|
-
}).exitProcess(false).check((options) => {
|
|
41
|
-
if (!["alpha", "beta", "rc", void 0].includes(options.prerelease)) {
|
|
42
|
-
throw new Error("prerelease should be one of alpha, beta, rc or undefined");
|
|
43
|
-
}
|
|
44
|
-
return true;
|
|
45
|
-
}).showHelpOnFail(false).fail((message) => {
|
|
46
|
-
throw new Error(message);
|
|
47
|
-
}).alias("version", "v").alias("help", "h").example("$0", "Update changelog and tag release").example("$0 --dry --verbose", "Show a detailed dry-run release preview").pkgConf("release").wrap(97);
|
|
48
|
-
let parsed;
|
|
49
|
-
try {
|
|
50
|
-
parsed = await parser.parseAsync();
|
|
51
|
-
} catch (error) {
|
|
52
|
-
const failure = new CliParseError(error.message);
|
|
53
|
-
const help = await parser.getHelp();
|
|
54
|
-
failure.help = [help].flat().join("\n");
|
|
55
|
-
throw failure;
|
|
56
|
-
}
|
|
57
|
-
return {
|
|
58
|
-
releaseAs: parsed.releaseAs,
|
|
59
|
-
prerelease: parsed.prerelease,
|
|
60
|
-
dry: parsed.dry,
|
|
61
|
-
verbose: parsed.verbose,
|
|
62
|
-
tags: parsed.tags
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
function createReporter({
|
|
66
|
-
output,
|
|
67
|
-
git,
|
|
68
|
-
showTags = false,
|
|
69
|
-
verbosity = "summary"
|
|
70
|
-
}) {
|
|
71
|
-
if (verbosity === "detailed") {
|
|
72
|
-
return new DetailedReporter({
|
|
73
|
-
output,
|
|
74
|
-
git,
|
|
75
|
-
showTags
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
return new SummaryReporter({
|
|
79
|
-
output,
|
|
80
|
-
git,
|
|
81
|
-
showTags
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
class SummaryReporter {
|
|
85
|
-
output;
|
|
86
|
-
git;
|
|
87
|
-
showTags;
|
|
88
|
-
scope = null;
|
|
89
|
-
position = /* @__PURE__ */ new Map();
|
|
90
|
-
constructor({
|
|
91
|
-
output,
|
|
92
|
-
git,
|
|
93
|
-
showTags
|
|
94
|
-
}) {
|
|
95
|
-
this.output = output;
|
|
96
|
-
this.git = git;
|
|
97
|
-
this.showTags = showTags;
|
|
98
|
-
}
|
|
99
|
-
async onStart(context) {
|
|
100
|
-
this.output.info(
|
|
101
|
-
context.dry ? "Starting dry release" : "Starting release"
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
async onScope(scope, context) {
|
|
105
|
-
this.scope = scope;
|
|
106
|
-
this.position = new Map(
|
|
107
|
-
scope.slices.map((slice, index) => [slice.id, index + 1])
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
async onSliceStart(slice) {
|
|
111
|
-
this.output.info("Running slice %s", [this.describeProgress(slice)]);
|
|
112
|
-
}
|
|
113
|
-
async onSuccess(result) {
|
|
114
|
-
if (!result.changed) {
|
|
115
|
-
this.output.success("No changes since last release");
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const changed = result.slices.filter((slice) => slice.changed);
|
|
119
|
-
const primary = changed[0];
|
|
120
|
-
const packages = collectPackages(changed);
|
|
121
|
-
this.output.success("Release slices: %s", [String(changed.length)]);
|
|
122
|
-
this.output.success("Updated packages: %s", [String(packages.length)]);
|
|
123
|
-
if (primary) {
|
|
124
|
-
this.output.success("Next version: %s", [primary.nextVersion]);
|
|
125
|
-
}
|
|
126
|
-
if (result.dry) {
|
|
127
|
-
this.output.info("No committing or tagging since this was a dry run");
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
this.output.success("Committed %s staged files", [String(result.files.length)]);
|
|
131
|
-
if (this.showTags) {
|
|
132
|
-
const tags = collectTags(changed);
|
|
133
|
-
if (tags.length) {
|
|
134
|
-
this.output.success("Tags: %s", [tags.join(", ")]);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
this.output.info("Run `%s` to publish", [
|
|
138
|
-
`git push --follow-tags origin ${await this.resolveBranch()}`
|
|
139
|
-
]);
|
|
140
|
-
}
|
|
141
|
-
async onError(error) {
|
|
142
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
143
|
-
this.output.error(message);
|
|
144
|
-
}
|
|
145
|
-
describeProgress(slice) {
|
|
146
|
-
const position = this.position.get(slice.id);
|
|
147
|
-
const total = this.scope?.slices.length;
|
|
148
|
-
const label = describeSlice(slice);
|
|
149
|
-
return position && total ? `${position}/${total}: ${label}` : label;
|
|
150
|
-
}
|
|
151
|
-
async resolveBranch() {
|
|
152
|
-
try {
|
|
153
|
-
return await this.git.revParse("HEAD", { abbrevRef: true });
|
|
154
|
-
} catch {
|
|
155
|
-
return "%branch%";
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
class DetailedReporter extends SummaryReporter {
|
|
160
|
-
async onScope(scope, context) {
|
|
161
|
-
await super.onScope(scope, context);
|
|
162
|
-
this.output.info("%s scope: %s packages, %s affected, %s slices", [
|
|
163
|
-
scope.mode,
|
|
164
|
-
String(scope.packages.length),
|
|
165
|
-
String(scope.affected.length),
|
|
166
|
-
String(scope.slices.length)
|
|
167
|
-
]);
|
|
168
|
-
}
|
|
169
|
-
async onSliceSuccess(slice) {
|
|
170
|
-
if (!slice.changed) {
|
|
171
|
-
this.output.warn("Completed slice %s without version changes (%s)", [
|
|
172
|
-
describeSlice(slice),
|
|
173
|
-
slice.currentVersion
|
|
174
|
-
]);
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
this.output.success("Completed slice %s: %s -> %s (%s)", [
|
|
178
|
-
describeSlice(slice),
|
|
179
|
-
slice.currentVersion,
|
|
180
|
-
slice.nextVersion,
|
|
181
|
-
slice.releaseType
|
|
182
|
-
]);
|
|
183
|
-
if (this.showTags && slice.tag) {
|
|
184
|
-
this.output.info("Tag: %s", [slice.tag]);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
async onSuccess(result) {
|
|
188
|
-
await super.onSuccess(result);
|
|
189
|
-
if (!result.changed) {
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
const packages = collectPackages(result.slices.filter((slice) => slice.changed));
|
|
193
|
-
this.output.info("Updated packages: %s", [describePackages(packages)]);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
function describeSlice(slice) {
|
|
197
|
-
if (slice.partition) {
|
|
198
|
-
return `${slice.partition} [${describePackages(slice.packages)}]`;
|
|
199
|
-
}
|
|
200
|
-
return describePackages(slice.packages);
|
|
201
|
-
}
|
|
202
|
-
function describePackages(packages) {
|
|
203
|
-
return packages.map((pkg) => pkg.name ?? pkg.path).join(", ");
|
|
204
|
-
}
|
|
205
|
-
function collectTags(slices) {
|
|
206
|
-
return slices.map((slice) => slice.tag).filter((tag) => !!tag);
|
|
207
|
-
}
|
|
208
|
-
function collectPackages(slices) {
|
|
209
|
-
const packages = [];
|
|
210
|
-
const seen = /* @__PURE__ */ new Set();
|
|
211
|
-
for (const slice of slices) {
|
|
212
|
-
for (const pkg of slice.packages) {
|
|
213
|
-
const identity = pkg.name ?? pkg.path;
|
|
214
|
-
if (seen.has(identity)) {
|
|
215
|
-
continue;
|
|
216
|
-
}
|
|
217
|
-
seen.add(identity);
|
|
218
|
-
packages.push(pkg);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return packages;
|
|
222
|
-
}
|
|
223
|
-
class ConsoleOutput {
|
|
224
|
-
write(message) {
|
|
225
|
-
console.info(message);
|
|
226
|
-
}
|
|
227
|
-
writeError(message) {
|
|
228
|
-
console.error(message);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
class Output {
|
|
232
|
-
output;
|
|
233
|
-
theme;
|
|
234
|
-
constructor({
|
|
235
|
-
dry,
|
|
236
|
-
output = new ConsoleOutput(),
|
|
237
|
-
theme = createDefaultTheme(dry)
|
|
238
|
-
}) {
|
|
239
|
-
this.output = output;
|
|
240
|
-
this.theme = theme;
|
|
241
|
-
}
|
|
242
|
-
info(template, context = [], figure = this.theme.info) {
|
|
243
|
-
this.output.write(format(template, context, figure));
|
|
244
|
-
}
|
|
245
|
-
success(template, context = [], figure = this.theme.success) {
|
|
246
|
-
this.output.write(format(template, context, figure));
|
|
247
|
-
}
|
|
248
|
-
warn(template, context = [], figure = this.theme.warning) {
|
|
249
|
-
this.output.write(format(template, context, figure));
|
|
250
|
-
}
|
|
251
|
-
error(template, context = [], figure = this.theme.error) {
|
|
252
|
-
this.output.writeError(format(template, context, figure));
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
function createDefaultTheme(dry) {
|
|
256
|
-
return {
|
|
257
|
-
success: dry ? chalk.yellow(figures.tick) : chalk.green(figures.tick),
|
|
258
|
-
warning: chalk.yellow(figures.warning),
|
|
259
|
-
error: chalk.red(figures.cross),
|
|
260
|
-
info: chalk.blue(figures.info)
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
function format(template, context, figure) {
|
|
264
|
-
const bold = (arg) => chalk.bold(arg);
|
|
265
|
-
const message = util.format(template, ...context.map(bold));
|
|
266
|
-
return `${figure} ${message}`;
|
|
267
|
-
}
|
|
7
|
+
//#region src/cli.ts
|
|
268
8
|
async function main(argv = process.argv) {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
};
|
|
9
|
+
const cwd = process.cwd();
|
|
10
|
+
const options = await parseArgv(argv);
|
|
11
|
+
const output = new Output({
|
|
12
|
+
dry: options.dry,
|
|
13
|
+
output: new ConsoleOutput()
|
|
14
|
+
});
|
|
15
|
+
const git = new GitCommander({ sh: new Runner(cwd) });
|
|
16
|
+
await run({
|
|
17
|
+
cwd,
|
|
18
|
+
dry: options.dry,
|
|
19
|
+
releaseAs: options.releaseAs,
|
|
20
|
+
prerelease: options.prerelease,
|
|
21
|
+
reporter: createReporter({
|
|
22
|
+
output,
|
|
23
|
+
git,
|
|
24
|
+
showTags: options.tags,
|
|
25
|
+
verbosity: options.verbose ? "detailed" : "summary"
|
|
26
|
+
})
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { main };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.__toESM = __toESM;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let yargs = require("yargs");
|
|
3
|
+
yargs = require_runtime.__toESM(yargs, 1);
|
|
4
|
+
let yargs_helpers = require("yargs/helpers");
|
|
5
|
+
//#region src/cli/args.ts
|
|
6
|
+
var DEFAULTS = {
|
|
7
|
+
releaseAs: void 0,
|
|
8
|
+
prerelease: void 0,
|
|
9
|
+
dry: false,
|
|
10
|
+
verbose: false,
|
|
11
|
+
tags: false
|
|
12
|
+
};
|
|
13
|
+
var CliParseError = class extends Error {
|
|
14
|
+
help;
|
|
15
|
+
};
|
|
16
|
+
async function parseArgv(argv = process.argv) {
|
|
17
|
+
const parser = (0, yargs.default)((0, yargs_helpers.hideBin)(argv)).locale("en").scriptName("conventional-release").usage("Usage: $0 [options]").option("release-as", {
|
|
18
|
+
alias: "r",
|
|
19
|
+
describe: "Specify the release type (major|minor|patch)",
|
|
20
|
+
requiresArg: true,
|
|
21
|
+
string: true
|
|
22
|
+
}).option("prerelease", {
|
|
23
|
+
alias: "p",
|
|
24
|
+
describe: "Specify the prerelease type (alpha|beta|rc)",
|
|
25
|
+
requiresArg: true,
|
|
26
|
+
string: true
|
|
27
|
+
}).option("dry", {
|
|
28
|
+
type: "boolean",
|
|
29
|
+
default: DEFAULTS.dry,
|
|
30
|
+
describe: "See the commands that running release would run"
|
|
31
|
+
}).option("verbose", {
|
|
32
|
+
type: "boolean",
|
|
33
|
+
default: DEFAULTS.verbose,
|
|
34
|
+
describe: "Show detailed per-slice progress output"
|
|
35
|
+
}).option("tags", {
|
|
36
|
+
type: "boolean",
|
|
37
|
+
default: DEFAULTS.tags,
|
|
38
|
+
describe: "Show generated tags in the final output"
|
|
39
|
+
}).exitProcess(false).check((options) => {
|
|
40
|
+
if (![
|
|
41
|
+
"alpha",
|
|
42
|
+
"beta",
|
|
43
|
+
"rc",
|
|
44
|
+
void 0
|
|
45
|
+
].includes(options.prerelease)) throw new Error("prerelease should be one of alpha, beta, rc or undefined");
|
|
46
|
+
return true;
|
|
47
|
+
}).showHelpOnFail(false).fail((message) => {
|
|
48
|
+
throw new Error(message);
|
|
49
|
+
}).alias("version", "v").alias("help", "h").example("$0", "Update changelog and tag release").example("$0 --dry --verbose", "Show a detailed dry-run release preview").pkgConf("release").wrap(97);
|
|
50
|
+
let parsed;
|
|
51
|
+
try {
|
|
52
|
+
parsed = await parser.parseAsync();
|
|
53
|
+
} catch (error) {
|
|
54
|
+
const failure = new CliParseError(error.message);
|
|
55
|
+
failure.help = [await parser.getHelp()].flat().join("\n");
|
|
56
|
+
throw failure;
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
releaseAs: parsed.releaseAs,
|
|
60
|
+
prerelease: parsed.prerelease,
|
|
61
|
+
dry: parsed.dry,
|
|
62
|
+
verbose: parsed.verbose,
|
|
63
|
+
tags: parsed.tags
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
exports.parseArgv = parseArgv;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import yargs from "yargs";
|
|
2
|
+
import { hideBin } from "yargs/helpers";
|
|
3
|
+
//#region src/cli/args.ts
|
|
4
|
+
var DEFAULTS = {
|
|
5
|
+
releaseAs: void 0,
|
|
6
|
+
prerelease: void 0,
|
|
7
|
+
dry: false,
|
|
8
|
+
verbose: false,
|
|
9
|
+
tags: false
|
|
10
|
+
};
|
|
11
|
+
var CliParseError = class extends Error {
|
|
12
|
+
help;
|
|
13
|
+
};
|
|
14
|
+
async function parseArgv(argv = process.argv) {
|
|
15
|
+
const parser = yargs(hideBin(argv)).locale("en").scriptName("conventional-release").usage("Usage: $0 [options]").option("release-as", {
|
|
16
|
+
alias: "r",
|
|
17
|
+
describe: "Specify the release type (major|minor|patch)",
|
|
18
|
+
requiresArg: true,
|
|
19
|
+
string: true
|
|
20
|
+
}).option("prerelease", {
|
|
21
|
+
alias: "p",
|
|
22
|
+
describe: "Specify the prerelease type (alpha|beta|rc)",
|
|
23
|
+
requiresArg: true,
|
|
24
|
+
string: true
|
|
25
|
+
}).option("dry", {
|
|
26
|
+
type: "boolean",
|
|
27
|
+
default: DEFAULTS.dry,
|
|
28
|
+
describe: "See the commands that running release would run"
|
|
29
|
+
}).option("verbose", {
|
|
30
|
+
type: "boolean",
|
|
31
|
+
default: DEFAULTS.verbose,
|
|
32
|
+
describe: "Show detailed per-slice progress output"
|
|
33
|
+
}).option("tags", {
|
|
34
|
+
type: "boolean",
|
|
35
|
+
default: DEFAULTS.tags,
|
|
36
|
+
describe: "Show generated tags in the final output"
|
|
37
|
+
}).exitProcess(false).check((options) => {
|
|
38
|
+
if (![
|
|
39
|
+
"alpha",
|
|
40
|
+
"beta",
|
|
41
|
+
"rc",
|
|
42
|
+
void 0
|
|
43
|
+
].includes(options.prerelease)) throw new Error("prerelease should be one of alpha, beta, rc or undefined");
|
|
44
|
+
return true;
|
|
45
|
+
}).showHelpOnFail(false).fail((message) => {
|
|
46
|
+
throw new Error(message);
|
|
47
|
+
}).alias("version", "v").alias("help", "h").example("$0", "Update changelog and tag release").example("$0 --dry --verbose", "Show a detailed dry-run release preview").pkgConf("release").wrap(97);
|
|
48
|
+
let parsed;
|
|
49
|
+
try {
|
|
50
|
+
parsed = await parser.parseAsync();
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const failure = new CliParseError(error.message);
|
|
53
|
+
failure.help = [await parser.getHelp()].flat().join("\n");
|
|
54
|
+
throw failure;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
releaseAs: parsed.releaseAs,
|
|
58
|
+
prerelease: parsed.prerelease,
|
|
59
|
+
dry: parsed.dry,
|
|
60
|
+
verbose: parsed.verbose,
|
|
61
|
+
tags: parsed.tags
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
export { parseArgv };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let chalk = require("chalk");
|
|
3
|
+
chalk = require_runtime.__toESM(chalk, 1);
|
|
4
|
+
let figures = require("figures");
|
|
5
|
+
figures = require_runtime.__toESM(figures, 1);
|
|
6
|
+
let node_util = require("node:util");
|
|
7
|
+
node_util = require_runtime.__toESM(node_util, 1);
|
|
8
|
+
//#region src/cli/output.ts
|
|
9
|
+
var ConsoleOutput = class {
|
|
10
|
+
write(message) {
|
|
11
|
+
console.info(message);
|
|
12
|
+
}
|
|
13
|
+
writeError(message) {
|
|
14
|
+
console.error(message);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var Output = class {
|
|
18
|
+
output;
|
|
19
|
+
theme;
|
|
20
|
+
constructor({ dry, output = new ConsoleOutput(), theme = createDefaultTheme(dry) }) {
|
|
21
|
+
this.output = output;
|
|
22
|
+
this.theme = theme;
|
|
23
|
+
}
|
|
24
|
+
info(template, context = [], figure = this.theme.info) {
|
|
25
|
+
this.output.write(format(template, context, figure));
|
|
26
|
+
}
|
|
27
|
+
success(template, context = [], figure = this.theme.success) {
|
|
28
|
+
this.output.write(format(template, context, figure));
|
|
29
|
+
}
|
|
30
|
+
warn(template, context = [], figure = this.theme.warning) {
|
|
31
|
+
this.output.write(format(template, context, figure));
|
|
32
|
+
}
|
|
33
|
+
error(template, context = [], figure = this.theme.error) {
|
|
34
|
+
this.output.writeError(format(template, context, figure));
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
function createDefaultTheme(dry) {
|
|
38
|
+
return {
|
|
39
|
+
success: dry ? chalk.default.yellow(figures.default.tick) : chalk.default.green(figures.default.tick),
|
|
40
|
+
warning: chalk.default.yellow(figures.default.warning),
|
|
41
|
+
error: chalk.default.red(figures.default.cross),
|
|
42
|
+
info: chalk.default.blue(figures.default.info)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function format(template, context, figure) {
|
|
46
|
+
const bold = (arg) => chalk.default.bold(arg);
|
|
47
|
+
return `${figure} ${node_util.format(template, ...context.map(bold))}`;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
exports.ConsoleOutput = ConsoleOutput;
|
|
51
|
+
exports.Output = Output;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import figures from "figures";
|
|
3
|
+
import * as util from "node:util";
|
|
4
|
+
//#region src/cli/output.ts
|
|
5
|
+
var ConsoleOutput = class {
|
|
6
|
+
write(message) {
|
|
7
|
+
console.info(message);
|
|
8
|
+
}
|
|
9
|
+
writeError(message) {
|
|
10
|
+
console.error(message);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
var Output = class {
|
|
14
|
+
output;
|
|
15
|
+
theme;
|
|
16
|
+
constructor({ dry, output = new ConsoleOutput(), theme = createDefaultTheme(dry) }) {
|
|
17
|
+
this.output = output;
|
|
18
|
+
this.theme = theme;
|
|
19
|
+
}
|
|
20
|
+
info(template, context = [], figure = this.theme.info) {
|
|
21
|
+
this.output.write(format(template, context, figure));
|
|
22
|
+
}
|
|
23
|
+
success(template, context = [], figure = this.theme.success) {
|
|
24
|
+
this.output.write(format(template, context, figure));
|
|
25
|
+
}
|
|
26
|
+
warn(template, context = [], figure = this.theme.warning) {
|
|
27
|
+
this.output.write(format(template, context, figure));
|
|
28
|
+
}
|
|
29
|
+
error(template, context = [], figure = this.theme.error) {
|
|
30
|
+
this.output.writeError(format(template, context, figure));
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
function createDefaultTheme(dry) {
|
|
34
|
+
return {
|
|
35
|
+
success: dry ? chalk.yellow(figures.tick) : chalk.green(figures.tick),
|
|
36
|
+
warning: chalk.yellow(figures.warning),
|
|
37
|
+
error: chalk.red(figures.cross),
|
|
38
|
+
info: chalk.blue(figures.info)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function format(template, context, figure) {
|
|
42
|
+
const bold = (arg) => chalk.bold(arg);
|
|
43
|
+
return `${figure} ${util.format(template, ...context.map(bold))}`;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { ConsoleOutput, Output };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
//#region src/cli/reporter.ts
|
|
2
|
+
function createReporter({ output, git, showTags = false, verbosity = "summary" }) {
|
|
3
|
+
if (verbosity === "detailed") return new DetailedReporter({
|
|
4
|
+
output,
|
|
5
|
+
git,
|
|
6
|
+
showTags
|
|
7
|
+
});
|
|
8
|
+
return new SummaryReporter({
|
|
9
|
+
output,
|
|
10
|
+
git,
|
|
11
|
+
showTags
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
var SummaryReporter = class {
|
|
15
|
+
output;
|
|
16
|
+
git;
|
|
17
|
+
showTags;
|
|
18
|
+
scope = null;
|
|
19
|
+
position = /* @__PURE__ */ new Map();
|
|
20
|
+
constructor({ output, git, showTags }) {
|
|
21
|
+
this.output = output;
|
|
22
|
+
this.git = git;
|
|
23
|
+
this.showTags = showTags;
|
|
24
|
+
}
|
|
25
|
+
async onStart(context) {
|
|
26
|
+
this.output.info(context.dry ? "Starting dry release" : "Starting release");
|
|
27
|
+
}
|
|
28
|
+
async onScope(scope, context) {
|
|
29
|
+
this.scope = scope;
|
|
30
|
+
this.position = new Map(scope.slices.map((slice, index) => [slice.id, index + 1]));
|
|
31
|
+
}
|
|
32
|
+
async onSliceStart(slice) {
|
|
33
|
+
this.output.info("Running slice %s", [this.describeProgress(slice)]);
|
|
34
|
+
}
|
|
35
|
+
async onSuccess(result) {
|
|
36
|
+
if (!result.changed) {
|
|
37
|
+
this.output.success("No changes since last release");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const changed = result.slices.filter((slice) => slice.changed);
|
|
41
|
+
const primary = changed[0];
|
|
42
|
+
const packages = collectPackages(changed);
|
|
43
|
+
this.output.success("Release slices: %s", [String(changed.length)]);
|
|
44
|
+
this.output.success("Updated packages: %s", [String(packages.length)]);
|
|
45
|
+
if (primary) this.output.success("Next version: %s", [primary.nextVersion]);
|
|
46
|
+
if (result.dry) {
|
|
47
|
+
this.output.info("No committing or tagging since this was a dry run");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.output.success("Committed %s staged files", [String(result.files.length)]);
|
|
51
|
+
if (this.showTags) {
|
|
52
|
+
const tags = collectTags(changed);
|
|
53
|
+
if (tags.length) this.output.success("Tags: %s", [tags.join(", ")]);
|
|
54
|
+
}
|
|
55
|
+
this.output.info("Run `%s` to publish", [`git push --follow-tags origin ${await this.resolveBranch()}`]);
|
|
56
|
+
}
|
|
57
|
+
async onError(error) {
|
|
58
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
59
|
+
this.output.error(message);
|
|
60
|
+
}
|
|
61
|
+
describeProgress(slice) {
|
|
62
|
+
const position = this.position.get(slice.id);
|
|
63
|
+
const total = this.scope?.slices.length;
|
|
64
|
+
const label = describeSlice(slice);
|
|
65
|
+
return position && total ? `${position}/${total}: ${label}` : label;
|
|
66
|
+
}
|
|
67
|
+
async resolveBranch() {
|
|
68
|
+
try {
|
|
69
|
+
return await this.git.revParse("HEAD", { abbrevRef: true });
|
|
70
|
+
} catch {
|
|
71
|
+
return "%branch%";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
var DetailedReporter = class extends SummaryReporter {
|
|
76
|
+
async onScope(scope, context) {
|
|
77
|
+
await super.onScope(scope, context);
|
|
78
|
+
this.output.info("%s scope: %s packages, %s affected, %s slices", [
|
|
79
|
+
scope.mode,
|
|
80
|
+
String(scope.packages.length),
|
|
81
|
+
String(scope.affected.length),
|
|
82
|
+
String(scope.slices.length)
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
85
|
+
async onSliceSuccess(slice) {
|
|
86
|
+
if (!slice.changed) {
|
|
87
|
+
this.output.warn("Completed slice %s without version changes (%s)", [describeSlice(slice), slice.currentVersion]);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.output.success("Completed slice %s: %s -> %s (%s)", [
|
|
91
|
+
describeSlice(slice),
|
|
92
|
+
slice.currentVersion,
|
|
93
|
+
slice.nextVersion,
|
|
94
|
+
slice.releaseType
|
|
95
|
+
]);
|
|
96
|
+
if (this.showTags && slice.tag) this.output.info("Tag: %s", [slice.tag]);
|
|
97
|
+
}
|
|
98
|
+
async onSuccess(result) {
|
|
99
|
+
await super.onSuccess(result);
|
|
100
|
+
if (!result.changed) return;
|
|
101
|
+
const packages = collectPackages(result.slices.filter((slice) => slice.changed));
|
|
102
|
+
this.output.info("Updated packages: %s", [describePackages(packages)]);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
function describeSlice(slice) {
|
|
106
|
+
if (slice.partition) return `${slice.partition} [${describePackages(slice.packages)}]`;
|
|
107
|
+
return describePackages(slice.packages);
|
|
108
|
+
}
|
|
109
|
+
function describePackages(packages) {
|
|
110
|
+
return packages.map((pkg) => pkg.name ?? pkg.path).join(", ");
|
|
111
|
+
}
|
|
112
|
+
function collectTags(slices) {
|
|
113
|
+
return slices.map((slice) => slice.tag).filter((tag) => !!tag);
|
|
114
|
+
}
|
|
115
|
+
function collectPackages(slices) {
|
|
116
|
+
const packages = [];
|
|
117
|
+
const seen = /* @__PURE__ */ new Set();
|
|
118
|
+
for (const slice of slices) for (const pkg of slice.packages) {
|
|
119
|
+
const identity = pkg.name ?? pkg.path;
|
|
120
|
+
if (seen.has(identity)) continue;
|
|
121
|
+
seen.add(identity);
|
|
122
|
+
packages.push(pkg);
|
|
123
|
+
}
|
|
124
|
+
return packages;
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
exports.createReporter = createReporter;
|