cross-release-cli 0.0.1-alpha.1 → 0.0.1-alpha.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/dist/index.cjs +46 -57
- package/dist/index.mjs +402 -0
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -10,6 +10,7 @@ var fs = require('node:fs');
|
|
|
10
10
|
var cac = require('cac');
|
|
11
11
|
var defu = require('defu');
|
|
12
12
|
var execa = require('execa');
|
|
13
|
+
var debug$1 = require('debug');
|
|
13
14
|
|
|
14
15
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
15
16
|
|
|
@@ -36,8 +37,9 @@ var isUnicodeSupported__default = /*#__PURE__*/_interopDefaultLegacy(isUnicodeSu
|
|
|
36
37
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
37
38
|
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
38
39
|
var cac__default = /*#__PURE__*/_interopDefaultLegacy(cac);
|
|
40
|
+
var debug__default = /*#__PURE__*/_interopDefaultLegacy(debug$1);
|
|
39
41
|
|
|
40
|
-
var version = "0.0.
|
|
42
|
+
var version = "0.0.1-alpha.1";
|
|
41
43
|
|
|
42
44
|
const configDefaults = {
|
|
43
45
|
showHelp: false,
|
|
@@ -54,11 +56,11 @@ const configDefaults = {
|
|
|
54
56
|
dir: process.cwd(),
|
|
55
57
|
commit: {
|
|
56
58
|
shouldVerify: true,
|
|
57
|
-
shouldStageAll:
|
|
59
|
+
shouldStageAll: true,
|
|
58
60
|
template: "chore: release v%s"
|
|
59
61
|
},
|
|
60
62
|
push: {
|
|
61
|
-
|
|
63
|
+
shouldFollowTags: false
|
|
62
64
|
}
|
|
63
65
|
};
|
|
64
66
|
function loadUserConfig(overrides) {
|
|
@@ -67,7 +69,7 @@ function loadUserConfig(overrides) {
|
|
|
67
69
|
return defu.defu(overrides, userConfig, configDefaults);
|
|
68
70
|
}
|
|
69
71
|
function parseOptions() {
|
|
70
|
-
const cli = cac__default["default"]("cross-release").version(version).usage("[flags] version").option("-r, --recursive", "Run the command for each project in the workspace (default: false)").option("-d, --dry", "Dry run (default: false)").option("-D, --dir
|
|
72
|
+
const cli = cac__default["default"]("cross-release").version(version).usage("[flags] version").option("-r, --recursive", "Run the command for each project in the workspace (default: false)").option("-d, --dry", "Dry run (default: false)").option("-D, --dir [dir]", "Set working directory (default: project root)").option("-p, --publish", "Publish the project (default: false)").option("-c, --commit", "Commit current changes (default: false)").option("-p, --push", "Push the project to remote (default: false)").option("-t, --tag", "Create a tag for current version (default: false)").option("-e, --exclude [dir]", "Folders to exclude from search (default: [node_modules, .git])").option("-y, --yes", "Answer yes to all prompts (default: false)").help().parse();
|
|
71
73
|
const { args, options } = cli;
|
|
72
74
|
const parsedArgs = loadUserConfig({
|
|
73
75
|
dir: options.dir,
|
|
@@ -86,6 +88,11 @@ function parseOptions() {
|
|
|
86
88
|
return parsedArgs;
|
|
87
89
|
}
|
|
88
90
|
|
|
91
|
+
function createDebug(ns) {
|
|
92
|
+
return debug__default["default"](`cross-release-cli:${ns}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const debug = createDebug("git");
|
|
89
96
|
async function gitTag(tagName, options) {
|
|
90
97
|
const s = prompts.spinner();
|
|
91
98
|
s.start("creating tag");
|
|
@@ -94,7 +101,7 @@ async function gitTag(tagName, options) {
|
|
|
94
101
|
if (isDel) {
|
|
95
102
|
args.push("--delete");
|
|
96
103
|
} else {
|
|
97
|
-
if (!message ||
|
|
104
|
+
if (!message || message?.length === 0) {
|
|
98
105
|
prompts.log.warn("no message provided, is recommended to provide a message for create an annotated tag");
|
|
99
106
|
} else {
|
|
100
107
|
args.push(
|
|
@@ -114,7 +121,7 @@ async function gitTag(tagName, options) {
|
|
|
114
121
|
if (!process.env.DRY) {
|
|
115
122
|
try {
|
|
116
123
|
const { command } = await execa.execa("git", ["tag", ...args]);
|
|
117
|
-
|
|
124
|
+
debug(`command: ${command}`);
|
|
118
125
|
} catch (e) {
|
|
119
126
|
s.stop(colorette.red(e.shortMessage));
|
|
120
127
|
return false;
|
|
@@ -126,23 +133,23 @@ async function gitTag(tagName, options) {
|
|
|
126
133
|
async function gitCommit(message, options) {
|
|
127
134
|
const s = prompts.spinner();
|
|
128
135
|
s.start("committing");
|
|
129
|
-
const { modifiedFiles = [], shouldStageAll
|
|
136
|
+
const { modifiedFiles = [], shouldStageAll, shouldVerify } = options || {};
|
|
130
137
|
const args = [];
|
|
131
138
|
if (process.env.DRY) {
|
|
132
139
|
args.push("--dry-run");
|
|
133
140
|
}
|
|
134
|
-
args.push("--message",
|
|
135
|
-
if (modifiedFiles.length) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
} else if (shouldStageAll) {
|
|
141
|
+
args.push("--message", message);
|
|
142
|
+
if (!shouldStageAll && modifiedFiles.length) {
|
|
143
|
+
args.push("--", ...modifiedFiles);
|
|
144
|
+
} else {
|
|
139
145
|
args.push("--all");
|
|
140
146
|
}
|
|
141
147
|
if (!shouldVerify) {
|
|
142
148
|
args.push("--no-verify");
|
|
143
149
|
}
|
|
144
150
|
try {
|
|
145
|
-
await execa.execa("git", ["commit", ...args]);
|
|
151
|
+
const { command } = await execa.execa("git", ["commit", ...args]);
|
|
152
|
+
debug(`command: ${command}`);
|
|
146
153
|
s.stop(`commit message: ${colorette.green(message)}`);
|
|
147
154
|
} catch (e) {
|
|
148
155
|
s.stop(colorette.red(e.shortMessage));
|
|
@@ -169,7 +176,8 @@ async function gitPush(options) {
|
|
|
169
176
|
args.push("--dry-run");
|
|
170
177
|
}
|
|
171
178
|
try {
|
|
172
|
-
await execa.execa("git", ["push", ...args]);
|
|
179
|
+
const { command } = await execa.execa("git", ["push", ...args]);
|
|
180
|
+
debug(`command: ${command}`);
|
|
173
181
|
s.stop(`pushed to repo: ${colorette.gray(originUrl)}`);
|
|
174
182
|
} catch (e) {
|
|
175
183
|
s.stop(colorette.red(e.shortMessage));
|
|
@@ -180,19 +188,6 @@ async function gitPush(options) {
|
|
|
180
188
|
async function gitOriginUrl() {
|
|
181
189
|
return (await execa.execa("git", ["remote", "get-url", "origin"])).stdout.trim();
|
|
182
190
|
}
|
|
183
|
-
async function gitAdd(files) {
|
|
184
|
-
const args = ["-A"];
|
|
185
|
-
if (process.env.DRY) {
|
|
186
|
-
args.push("--dry-run");
|
|
187
|
-
}
|
|
188
|
-
args.push("--", ...files);
|
|
189
|
-
try {
|
|
190
|
-
await execa.execa("git", ["add", ...args]);
|
|
191
|
-
} catch (e) {
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
191
|
|
|
197
192
|
var ExitCode = /* @__PURE__ */ ((ExitCode2) => {
|
|
198
193
|
ExitCode2[ExitCode2["Success"] = 0] = "Success";
|
|
@@ -223,9 +218,8 @@ function handleUserCancel() {
|
|
|
223
218
|
prompts.cancel("User cancel");
|
|
224
219
|
process.exit(ExitCode.InvalidArgument);
|
|
225
220
|
}
|
|
226
|
-
async function chooseVersion(
|
|
227
|
-
|
|
228
|
-
const versionObj = crossBump.parseVersion(projectVersion);
|
|
221
|
+
async function chooseVersion(currentVersion) {
|
|
222
|
+
const versionObj = crossBump.parseVersion(currentVersion);
|
|
229
223
|
const {
|
|
230
224
|
nextMajor,
|
|
231
225
|
nextMinor,
|
|
@@ -234,11 +228,12 @@ async function chooseVersion(projectVersion) {
|
|
|
234
228
|
nextPreMajor,
|
|
235
229
|
nextPreMinor,
|
|
236
230
|
nextPrePatch
|
|
237
|
-
} = crossBump.getNextVersions(versionObj
|
|
231
|
+
} = crossBump.getNextVersions(versionObj ?? void 0);
|
|
238
232
|
const C_CUSTOM = "custom";
|
|
239
233
|
const versions = [
|
|
240
234
|
{ label: "custom...", value: C_CUSTOM },
|
|
241
235
|
{ label: `next (${nextRelease})`, value: nextRelease },
|
|
236
|
+
{ label: `keep (${currentVersion})`, value: currentVersion || "" },
|
|
242
237
|
{ label: `patch (${nextPatch})`, value: nextPatch },
|
|
243
238
|
{ label: `minor (${nextMinor})`, value: nextMinor },
|
|
244
239
|
{ label: `major (${nextMajor})`, value: nextMajor },
|
|
@@ -247,9 +242,9 @@ async function chooseVersion(projectVersion) {
|
|
|
247
242
|
{ label: `pre-major (${nextPreMajor})`, value: nextPreMajor }
|
|
248
243
|
];
|
|
249
244
|
const selectedValue = await prompts.select({
|
|
250
|
-
message: `Pick a project version. (current: ${
|
|
245
|
+
message: `Pick a project version. (current: ${currentVersion})`,
|
|
251
246
|
options: versions,
|
|
252
|
-
initialValue:
|
|
247
|
+
initialValue: versions[1].value ?? C_CUSTOM
|
|
253
248
|
});
|
|
254
249
|
if (!selectedValue || selectedValue === C_CUSTOM) {
|
|
255
250
|
return await prompts.text({
|
|
@@ -278,7 +273,6 @@ class App {
|
|
|
278
273
|
this.currentVersion = "";
|
|
279
274
|
this.nextVersion = "";
|
|
280
275
|
this.modifiedFiles = [];
|
|
281
|
-
// TODO: record the task execution status to rollback when execution fails
|
|
282
276
|
this.taskQueue = [];
|
|
283
277
|
this.taskStatus = "pending";
|
|
284
278
|
this.options = parseOptions();
|
|
@@ -329,7 +323,7 @@ getNextVersion_fn = async function() {
|
|
|
329
323
|
if (crossBump.isVersionValid(version)) {
|
|
330
324
|
this.nextVersion = version;
|
|
331
325
|
} else {
|
|
332
|
-
const nextVersion = await chooseVersion(
|
|
326
|
+
const nextVersion = await chooseVersion(this.currentVersion);
|
|
333
327
|
if (prompts.isCancel(nextVersion)) {
|
|
334
328
|
handleUserCancel();
|
|
335
329
|
} else {
|
|
@@ -339,19 +333,20 @@ getNextVersion_fn = async function() {
|
|
|
339
333
|
};
|
|
340
334
|
_getProjects = new WeakSet();
|
|
341
335
|
getProjects_fn = async function() {
|
|
342
|
-
const { options: { dir, excludes, isRecursive }, nextVersion
|
|
336
|
+
const { options: { dir, excludes, isRecursive }, nextVersion } = this;
|
|
343
337
|
const projectFiles = await crossBump.findProjectFiles(dir, excludes, isRecursive);
|
|
344
338
|
__privateMethod(this, _addTask, addTask_fn).call(this, {
|
|
345
339
|
name: "upgradeVersion",
|
|
346
340
|
exec: () => {
|
|
347
341
|
return Promise.all(projectFiles.map(async (projectFile) => {
|
|
348
|
-
|
|
342
|
+
try {
|
|
343
|
+
await crossBump.upgradeProjectVersion(nextVersion, projectFile);
|
|
349
344
|
this.modifiedFiles.push(projectFile.path);
|
|
350
|
-
message(`upgrade
|
|
351
|
-
}
|
|
345
|
+
message(`upgrade to ${colorette.blue(nextVersion)} for ${colorette.gray(path__default["default"].relative(dir, projectFile.path))}`);
|
|
346
|
+
} catch (e) {
|
|
352
347
|
this.taskStatus = "failed";
|
|
353
348
|
prompts.log.error(String(e));
|
|
354
|
-
}
|
|
349
|
+
}
|
|
355
350
|
}));
|
|
356
351
|
}
|
|
357
352
|
});
|
|
@@ -374,46 +369,38 @@ confirmReleaseOptions_fn = async function() {
|
|
|
374
369
|
__privateMethod(this, _addTask, addTask_fn).call(this, {
|
|
375
370
|
name: taskName,
|
|
376
371
|
exec: execFn
|
|
377
|
-
// rollback: rollbackFn,
|
|
378
372
|
});
|
|
379
373
|
}
|
|
380
374
|
};
|
|
381
375
|
const message2 = this.formatMessageString(commit.template, this.nextVersion);
|
|
382
376
|
await confirmAndSet(
|
|
383
377
|
"shouldCommit",
|
|
384
|
-
"should commit
|
|
378
|
+
"should commit?",
|
|
385
379
|
"commit",
|
|
386
380
|
async () => {
|
|
387
|
-
__privateMethod(this, _check, check_fn).call(this, await gitCommit(message2, {
|
|
381
|
+
__privateMethod(this, _check, check_fn).call(this, await gitCommit(message2, {
|
|
382
|
+
modifiedFiles: this.modifiedFiles,
|
|
383
|
+
shouldStageAll: commit.shouldStageAll,
|
|
384
|
+
shouldVerify: commit.shouldVerify
|
|
385
|
+
}));
|
|
388
386
|
}
|
|
389
|
-
// async () => {
|
|
390
|
-
// if (!process.env.DRY) {
|
|
391
|
-
// await gitReset({ files: this.modifiedFiles })
|
|
392
|
-
// }
|
|
393
|
-
// log.info("rollback: git reset")
|
|
394
|
-
// },
|
|
395
387
|
);
|
|
396
388
|
const tagName = `v${this.nextVersion}`;
|
|
397
389
|
await confirmAndSet(
|
|
398
390
|
"shouldTag",
|
|
399
|
-
"should create
|
|
391
|
+
"should create tag?",
|
|
400
392
|
"tag",
|
|
401
393
|
async () => {
|
|
402
394
|
__privateMethod(this, _check, check_fn).call(this, await gitTag(tagName, { message: message2 }));
|
|
403
395
|
}
|
|
404
|
-
// async () => {
|
|
405
|
-
// await gitTag(tagName, { isDel: true })
|
|
406
|
-
// log.info("rollback: git tag")
|
|
407
|
-
// },
|
|
408
396
|
);
|
|
409
397
|
await confirmAndSet(
|
|
410
398
|
"shouldPush",
|
|
411
|
-
"should push to remote
|
|
399
|
+
"should push to remote?",
|
|
412
400
|
"push",
|
|
413
401
|
async () => {
|
|
414
|
-
__privateMethod(this, _check, check_fn).call(this, await gitPush({ shouldFollowTags: this.options.push.
|
|
402
|
+
__privateMethod(this, _check, check_fn).call(this, await gitPush({ shouldFollowTags: this.options.push.shouldFollowTags }));
|
|
415
403
|
}
|
|
416
|
-
// () => undefined,
|
|
417
404
|
);
|
|
418
405
|
};
|
|
419
406
|
_addTask = new WeakSet();
|
|
@@ -425,10 +412,12 @@ _start = new WeakSet();
|
|
|
425
412
|
start_fn = function() {
|
|
426
413
|
prompts.intro("Cross release");
|
|
427
414
|
__privateMethod(this, _checkDryRun, checkDryRun_fn).call(this);
|
|
415
|
+
this.taskStatus = "running";
|
|
428
416
|
};
|
|
429
417
|
_done = new WeakSet();
|
|
430
418
|
done_fn = function() {
|
|
431
419
|
prompts.outro("Done");
|
|
420
|
+
this.taskStatus = "finished";
|
|
432
421
|
};
|
|
433
422
|
_check = new WeakSet();
|
|
434
423
|
check_fn = function(status) {
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path$1 from 'path';
|
|
3
|
+
import { spinner, log, isCancel, intro, outro, cancel, select, text, confirm } from '@clack/prompts';
|
|
4
|
+
import { findProjectFiles, getProjectVersion, isVersionValid, upgradeProjectVersion, parseVersion, getNextVersions } from 'cross-bump';
|
|
5
|
+
import { red, blue, green, gray, bgBlue } from 'colorette';
|
|
6
|
+
import isUnicodeSupported from 'is-unicode-supported';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
import * as fs from 'node:fs';
|
|
9
|
+
import cac from 'cac';
|
|
10
|
+
import { defu } from 'defu';
|
|
11
|
+
import { execa } from 'execa';
|
|
12
|
+
import debug$1 from 'debug';
|
|
13
|
+
|
|
14
|
+
var version = "0.0.1-alpha.1";
|
|
15
|
+
|
|
16
|
+
const configDefaults = {
|
|
17
|
+
showHelp: false,
|
|
18
|
+
showVersion: false,
|
|
19
|
+
version: "",
|
|
20
|
+
isAllYes: false,
|
|
21
|
+
isDry: false,
|
|
22
|
+
isRecursive: false,
|
|
23
|
+
shouldCommit: false,
|
|
24
|
+
shouldPublish: false,
|
|
25
|
+
shouldPush: false,
|
|
26
|
+
shouldTag: false,
|
|
27
|
+
excludes: ["node_modules", ".git"],
|
|
28
|
+
dir: process.cwd(),
|
|
29
|
+
commit: {
|
|
30
|
+
shouldVerify: true,
|
|
31
|
+
shouldStageAll: true,
|
|
32
|
+
template: "chore: release v%s"
|
|
33
|
+
},
|
|
34
|
+
push: {
|
|
35
|
+
shouldFollowTags: false
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
function loadUserConfig(overrides) {
|
|
39
|
+
const file = fs.readFileSync(path.resolve(process.cwd(), "package.json"), "utf-8");
|
|
40
|
+
const userConfig = JSON.parse(file)["cross-release"];
|
|
41
|
+
return defu(overrides, userConfig, configDefaults);
|
|
42
|
+
}
|
|
43
|
+
function parseOptions() {
|
|
44
|
+
const cli = cac("cross-release").version(version).usage("[flags] version").option("-r, --recursive", "Run the command for each project in the workspace (default: false)").option("-d, --dry", "Dry run (default: false)").option("-D, --dir [dir]", "Set working directory (default: project root)").option("-p, --publish", "Publish the project (default: false)").option("-c, --commit", "Commit current changes (default: false)").option("-p, --push", "Push the project to remote (default: false)").option("-t, --tag", "Create a tag for current version (default: false)").option("-e, --exclude [dir]", "Folders to exclude from search (default: [node_modules, .git])").option("-y, --yes", "Answer yes to all prompts (default: false)").help().parse();
|
|
45
|
+
const { args, options } = cli;
|
|
46
|
+
const parsedArgs = loadUserConfig({
|
|
47
|
+
dir: options.dir,
|
|
48
|
+
excludes: options.exclude,
|
|
49
|
+
isRecursive: options.recursive,
|
|
50
|
+
isDry: options.dry,
|
|
51
|
+
isAllYes: options.yes,
|
|
52
|
+
showHelp: options.help,
|
|
53
|
+
showVersion: options.version,
|
|
54
|
+
shouldCommit: options.commit,
|
|
55
|
+
shouldPublish: options.publish,
|
|
56
|
+
shouldPush: options.push,
|
|
57
|
+
shouldTag: options.tag,
|
|
58
|
+
version: args[0]
|
|
59
|
+
});
|
|
60
|
+
return parsedArgs;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function createDebug(ns) {
|
|
64
|
+
return debug$1(`cross-release-cli:${ns}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const debug = createDebug("git");
|
|
68
|
+
async function gitTag(tagName, options) {
|
|
69
|
+
const s = spinner();
|
|
70
|
+
s.start("creating tag");
|
|
71
|
+
const { isForce = false, isDel = false, message } = options || {};
|
|
72
|
+
const args = [];
|
|
73
|
+
if (isDel) {
|
|
74
|
+
args.push("--delete");
|
|
75
|
+
} else {
|
|
76
|
+
if (!message || message?.length === 0) {
|
|
77
|
+
log.warn("no message provided, is recommended to provide a message for create an annotated tag");
|
|
78
|
+
} else {
|
|
79
|
+
args.push(
|
|
80
|
+
// Create an annotated tag, which is recommended for releases.
|
|
81
|
+
// See https://git-scm.com/docs/git-tag
|
|
82
|
+
"--annotate",
|
|
83
|
+
// Use the same commit message for the tag
|
|
84
|
+
"--message",
|
|
85
|
+
// formatMessageString(template, nextVersion),
|
|
86
|
+
message
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (isForce)
|
|
91
|
+
args.push("--force");
|
|
92
|
+
args.push(tagName);
|
|
93
|
+
if (!process.env.DRY) {
|
|
94
|
+
try {
|
|
95
|
+
const { command } = await execa("git", ["tag", ...args]);
|
|
96
|
+
debug(`command: ${command}`);
|
|
97
|
+
} catch (e) {
|
|
98
|
+
s.stop(red(e.shortMessage));
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
s.stop(`create git tag: ${blue(tagName)}`);
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
async function gitCommit(message, options) {
|
|
106
|
+
const s = spinner();
|
|
107
|
+
s.start("committing");
|
|
108
|
+
const { modifiedFiles = [], shouldStageAll, shouldVerify } = options || {};
|
|
109
|
+
const args = [];
|
|
110
|
+
if (process.env.DRY) {
|
|
111
|
+
args.push("--dry-run");
|
|
112
|
+
}
|
|
113
|
+
args.push("--message", message);
|
|
114
|
+
if (!shouldStageAll && modifiedFiles.length) {
|
|
115
|
+
args.push("--", ...modifiedFiles);
|
|
116
|
+
} else {
|
|
117
|
+
args.push("--all");
|
|
118
|
+
}
|
|
119
|
+
if (!shouldVerify) {
|
|
120
|
+
args.push("--no-verify");
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
const { command } = await execa("git", ["commit", ...args]);
|
|
124
|
+
debug(`command: ${command}`);
|
|
125
|
+
s.stop(`commit message: ${green(message)}`);
|
|
126
|
+
} catch (e) {
|
|
127
|
+
s.stop(red(e.shortMessage));
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
async function gitPush(options) {
|
|
133
|
+
const { shouldFollowTags = true, remote, branch } = options || {};
|
|
134
|
+
const s = spinner();
|
|
135
|
+
s.start("pushing");
|
|
136
|
+
const originUrl = await gitOriginUrl();
|
|
137
|
+
const args = [];
|
|
138
|
+
if (shouldFollowTags) {
|
|
139
|
+
args.push("--follow-tags");
|
|
140
|
+
}
|
|
141
|
+
if (remote) {
|
|
142
|
+
args.push(remote);
|
|
143
|
+
if (branch) {
|
|
144
|
+
args.push(branch);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (process.env.DRY) {
|
|
148
|
+
args.push("--dry-run");
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
const { command } = await execa("git", ["push", ...args]);
|
|
152
|
+
debug(`command: ${command}`);
|
|
153
|
+
s.stop(`pushed to repo: ${gray(originUrl)}`);
|
|
154
|
+
} catch (e) {
|
|
155
|
+
s.stop(red(e.shortMessage));
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
async function gitOriginUrl() {
|
|
161
|
+
return (await execa("git", ["remote", "get-url", "origin"])).stdout.trim();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
var ExitCode = /* @__PURE__ */ ((ExitCode2) => {
|
|
165
|
+
ExitCode2[ExitCode2["Success"] = 0] = "Success";
|
|
166
|
+
ExitCode2[ExitCode2["FatalError"] = 1] = "FatalError";
|
|
167
|
+
ExitCode2[ExitCode2["InvalidArgument"] = 9] = "InvalidArgument";
|
|
168
|
+
return ExitCode2;
|
|
169
|
+
})(ExitCode || {});
|
|
170
|
+
|
|
171
|
+
var __accessCheck = (obj, member, msg) => {
|
|
172
|
+
if (!member.has(obj))
|
|
173
|
+
throw TypeError("Cannot " + msg);
|
|
174
|
+
};
|
|
175
|
+
var __privateAdd = (obj, member, value) => {
|
|
176
|
+
if (member.has(obj))
|
|
177
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
178
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
179
|
+
};
|
|
180
|
+
var __privateMethod = (obj, member, method) => {
|
|
181
|
+
__accessCheck(obj, member, "access private method");
|
|
182
|
+
return method;
|
|
183
|
+
};
|
|
184
|
+
var _checkDryRun, checkDryRun_fn, _getNextVersion, getNextVersion_fn, _getProjects, getProjects_fn, _confirmReleaseOptions, confirmReleaseOptions_fn, _addTask, addTask_fn, _start, start_fn, _done, done_fn, _check, check_fn;
|
|
185
|
+
function message(msg) {
|
|
186
|
+
const bar = isUnicodeSupported() ? "\u2502" : "|";
|
|
187
|
+
console.log(`${gray(bar)} ${msg}`);
|
|
188
|
+
}
|
|
189
|
+
function handleUserCancel() {
|
|
190
|
+
cancel("User cancel");
|
|
191
|
+
process.exit(ExitCode.InvalidArgument);
|
|
192
|
+
}
|
|
193
|
+
async function chooseVersion(currentVersion) {
|
|
194
|
+
const versionObj = parseVersion(currentVersion);
|
|
195
|
+
const {
|
|
196
|
+
nextMajor,
|
|
197
|
+
nextMinor,
|
|
198
|
+
nextPatch,
|
|
199
|
+
nextRelease,
|
|
200
|
+
nextPreMajor,
|
|
201
|
+
nextPreMinor,
|
|
202
|
+
nextPrePatch
|
|
203
|
+
} = getNextVersions(versionObj ?? void 0);
|
|
204
|
+
const C_CUSTOM = "custom";
|
|
205
|
+
const versions = [
|
|
206
|
+
{ label: "custom...", value: C_CUSTOM },
|
|
207
|
+
{ label: `next (${nextRelease})`, value: nextRelease },
|
|
208
|
+
{ label: `keep (${currentVersion})`, value: currentVersion || "" },
|
|
209
|
+
{ label: `patch (${nextPatch})`, value: nextPatch },
|
|
210
|
+
{ label: `minor (${nextMinor})`, value: nextMinor },
|
|
211
|
+
{ label: `major (${nextMajor})`, value: nextMajor },
|
|
212
|
+
{ label: `pre-patch (${nextPrePatch})`, value: nextPrePatch },
|
|
213
|
+
{ label: `pre-minor (${nextPreMinor})`, value: nextPreMinor },
|
|
214
|
+
{ label: `pre-major (${nextPreMajor})`, value: nextPreMajor }
|
|
215
|
+
];
|
|
216
|
+
const selectedValue = await select({
|
|
217
|
+
message: `Pick a project version. (current: ${currentVersion})`,
|
|
218
|
+
options: versions,
|
|
219
|
+
initialValue: versions[1].value ?? C_CUSTOM
|
|
220
|
+
});
|
|
221
|
+
if (!selectedValue || selectedValue === C_CUSTOM) {
|
|
222
|
+
return await text({
|
|
223
|
+
message: "Input your custom version number",
|
|
224
|
+
placeholder: "version number",
|
|
225
|
+
validate: (value) => {
|
|
226
|
+
if (!isVersionValid(value)) {
|
|
227
|
+
return "Invalid";
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
} else {
|
|
232
|
+
return selectedValue;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
class App {
|
|
236
|
+
constructor() {
|
|
237
|
+
__privateAdd(this, _checkDryRun);
|
|
238
|
+
__privateAdd(this, _getNextVersion);
|
|
239
|
+
__privateAdd(this, _getProjects);
|
|
240
|
+
__privateAdd(this, _confirmReleaseOptions);
|
|
241
|
+
__privateAdd(this, _addTask);
|
|
242
|
+
__privateAdd(this, _start);
|
|
243
|
+
__privateAdd(this, _done);
|
|
244
|
+
__privateAdd(this, _check);
|
|
245
|
+
this.currentVersion = "";
|
|
246
|
+
this.nextVersion = "";
|
|
247
|
+
this.modifiedFiles = [];
|
|
248
|
+
this.taskQueue = [];
|
|
249
|
+
this.taskStatus = "pending";
|
|
250
|
+
this.options = parseOptions();
|
|
251
|
+
}
|
|
252
|
+
async run() {
|
|
253
|
+
__privateMethod(this, _start, start_fn).call(this);
|
|
254
|
+
await __privateMethod(this, _getNextVersion, getNextVersion_fn).call(this);
|
|
255
|
+
await __privateMethod(this, _getProjects, getProjects_fn).call(this);
|
|
256
|
+
await __privateMethod(this, _confirmReleaseOptions, confirmReleaseOptions_fn).call(this);
|
|
257
|
+
for await (const task of this.taskQueue) {
|
|
258
|
+
if (this.taskStatus === "failed") {
|
|
259
|
+
break;
|
|
260
|
+
} else {
|
|
261
|
+
await task.exec();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
__privateMethod(this, _done, done_fn).call(this);
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Accepts a message string template (e.g. "release %s" or "This is the %s release").
|
|
268
|
+
* If the template contains any "%s" placeholders, then they are replaced with the version number;
|
|
269
|
+
* otherwise, the version number is appended to the string.
|
|
270
|
+
*/
|
|
271
|
+
formatMessageString(template, nextVersion) {
|
|
272
|
+
if (template.includes("%s")) {
|
|
273
|
+
return template.replace(/%s/g, nextVersion);
|
|
274
|
+
} else {
|
|
275
|
+
return template + nextVersion;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
_checkDryRun = new WeakSet();
|
|
280
|
+
checkDryRun_fn = function() {
|
|
281
|
+
if (this.options.isDry) {
|
|
282
|
+
log.message(bgBlue(" DRY RUN "));
|
|
283
|
+
process.env.DRY = "true";
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
_getNextVersion = new WeakSet();
|
|
287
|
+
getNextVersion_fn = async function() {
|
|
288
|
+
const { dir, excludes, version } = this.options;
|
|
289
|
+
const projectFile = await findProjectFiles(dir, excludes);
|
|
290
|
+
if (!projectFile.length) {
|
|
291
|
+
throw new Error("can't found any project file in the project root");
|
|
292
|
+
}
|
|
293
|
+
const projectVersion = await getProjectVersion(projectFile[0]);
|
|
294
|
+
this.currentVersion = projectVersion || "";
|
|
295
|
+
if (isVersionValid(version)) {
|
|
296
|
+
this.nextVersion = version;
|
|
297
|
+
} else {
|
|
298
|
+
const nextVersion = await chooseVersion(this.currentVersion);
|
|
299
|
+
if (isCancel(nextVersion)) {
|
|
300
|
+
handleUserCancel();
|
|
301
|
+
} else {
|
|
302
|
+
this.nextVersion = nextVersion;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
_getProjects = new WeakSet();
|
|
307
|
+
getProjects_fn = async function() {
|
|
308
|
+
const { options: { dir, excludes, isRecursive }, nextVersion } = this;
|
|
309
|
+
const projectFiles = await findProjectFiles(dir, excludes, isRecursive);
|
|
310
|
+
__privateMethod(this, _addTask, addTask_fn).call(this, {
|
|
311
|
+
name: "upgradeVersion",
|
|
312
|
+
exec: () => {
|
|
313
|
+
return Promise.all(projectFiles.map(async (projectFile) => {
|
|
314
|
+
try {
|
|
315
|
+
await upgradeProjectVersion(nextVersion, projectFile);
|
|
316
|
+
this.modifiedFiles.push(projectFile.path);
|
|
317
|
+
message(`upgrade to ${blue(nextVersion)} for ${gray(path$1.relative(dir, projectFile.path))}`);
|
|
318
|
+
} catch (e) {
|
|
319
|
+
this.taskStatus = "failed";
|
|
320
|
+
log.error(String(e));
|
|
321
|
+
}
|
|
322
|
+
}));
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
};
|
|
326
|
+
_confirmReleaseOptions = new WeakSet();
|
|
327
|
+
confirmReleaseOptions_fn = async function() {
|
|
328
|
+
const { isAllYes, commit } = this.options;
|
|
329
|
+
const confirmAndSet = async (optionName, message3, taskName, execFn) => {
|
|
330
|
+
if (isAllYes) {
|
|
331
|
+
this.options[optionName] = true;
|
|
332
|
+
} else if (!this.options[optionName]) {
|
|
333
|
+
const confirmation = await confirm({ message: message3 });
|
|
334
|
+
if (!isCancel(confirmation)) {
|
|
335
|
+
this.options[optionName] = confirmation;
|
|
336
|
+
} else {
|
|
337
|
+
handleUserCancel();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (this.options[optionName]) {
|
|
341
|
+
__privateMethod(this, _addTask, addTask_fn).call(this, {
|
|
342
|
+
name: taskName,
|
|
343
|
+
exec: execFn
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
const message2 = this.formatMessageString(commit.template, this.nextVersion);
|
|
348
|
+
await confirmAndSet(
|
|
349
|
+
"shouldCommit",
|
|
350
|
+
"should commit?",
|
|
351
|
+
"commit",
|
|
352
|
+
async () => {
|
|
353
|
+
__privateMethod(this, _check, check_fn).call(this, await gitCommit(message2, {
|
|
354
|
+
modifiedFiles: this.modifiedFiles,
|
|
355
|
+
shouldStageAll: commit.shouldStageAll,
|
|
356
|
+
shouldVerify: commit.shouldVerify
|
|
357
|
+
}));
|
|
358
|
+
}
|
|
359
|
+
);
|
|
360
|
+
const tagName = `v${this.nextVersion}`;
|
|
361
|
+
await confirmAndSet(
|
|
362
|
+
"shouldTag",
|
|
363
|
+
"should create tag?",
|
|
364
|
+
"tag",
|
|
365
|
+
async () => {
|
|
366
|
+
__privateMethod(this, _check, check_fn).call(this, await gitTag(tagName, { message: message2 }));
|
|
367
|
+
}
|
|
368
|
+
);
|
|
369
|
+
await confirmAndSet(
|
|
370
|
+
"shouldPush",
|
|
371
|
+
"should push to remote?",
|
|
372
|
+
"push",
|
|
373
|
+
async () => {
|
|
374
|
+
__privateMethod(this, _check, check_fn).call(this, await gitPush({ shouldFollowTags: this.options.push.shouldFollowTags }));
|
|
375
|
+
}
|
|
376
|
+
);
|
|
377
|
+
};
|
|
378
|
+
_addTask = new WeakSet();
|
|
379
|
+
addTask_fn = function(task) {
|
|
380
|
+
const expect = this.taskQueue.length + 1;
|
|
381
|
+
return this.taskQueue.push(task) === expect;
|
|
382
|
+
};
|
|
383
|
+
_start = new WeakSet();
|
|
384
|
+
start_fn = function() {
|
|
385
|
+
intro("Cross release");
|
|
386
|
+
__privateMethod(this, _checkDryRun, checkDryRun_fn).call(this);
|
|
387
|
+
this.taskStatus = "running";
|
|
388
|
+
};
|
|
389
|
+
_done = new WeakSet();
|
|
390
|
+
done_fn = function() {
|
|
391
|
+
outro("Done");
|
|
392
|
+
this.taskStatus = "finished";
|
|
393
|
+
};
|
|
394
|
+
_check = new WeakSet();
|
|
395
|
+
check_fn = function(status) {
|
|
396
|
+
if (!status) {
|
|
397
|
+
this.taskStatus = "failed";
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
var app = new App();
|
|
401
|
+
|
|
402
|
+
void app.run();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cross-release-cli",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.2",
|
|
4
4
|
"description": "command line app for cross language bump utility",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "rainbowatcher",
|
|
@@ -32,9 +32,10 @@
|
|
|
32
32
|
"defu": "^6.1.2",
|
|
33
33
|
"execa": "^8.0.1",
|
|
34
34
|
"is-unicode-supported": "^1.3.0",
|
|
35
|
-
"cross-bump": "0.0.1-alpha.
|
|
35
|
+
"cross-bump": "0.0.1-alpha.2"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
|
+
"clean": "rimraf dist/*",
|
|
38
39
|
"build": "pkgroll"
|
|
39
40
|
}
|
|
40
41
|
}
|