cross-release-cli 0.0.1-alpha.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/LICENSE +21 -0
- package/README.md +87 -0
- package/bin/cross-release.js +3 -0
- package/dist/index.cjs +441 -0
- package/package.json +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 rainbowatcher
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Cross Release CLI
|
|
2
|
+
|
|
3
|
+
## Usage
|
|
4
|
+
|
|
5
|
+
1. install through package manager
|
|
6
|
+
|
|
7
|
+
```shell
|
|
8
|
+
# pnpm
|
|
9
|
+
pnpm i cross-release -g
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
otherwise you can use you favorite package manager instead
|
|
13
|
+
|
|
14
|
+
```shell
|
|
15
|
+
# npm
|
|
16
|
+
npm i cross-release -g
|
|
17
|
+
# yarn
|
|
18
|
+
yarn add cross-release --global
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
2. add to your package.json
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"scripts": {
|
|
26
|
+
"release": "cross-release"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
3. run release script
|
|
32
|
+
|
|
33
|
+
```shell
|
|
34
|
+
pnpm run release
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Command line
|
|
38
|
+
|
|
39
|
+
| short | long | description | default |
|
|
40
|
+
| ----- | --------------- | ------------------------------------------------- | -------------------------- |
|
|
41
|
+
| -r | --recursive | Run the command for each project in the workspace | `false` |
|
|
42
|
+
| -d | --dry | Dry run | `false` |
|
|
43
|
+
| -D | --dir [dir] | Set working directory | `project root` |
|
|
44
|
+
| -p | --publish | Publish the project | `false` |
|
|
45
|
+
| -c | --commit | Commit current changes | `false` |
|
|
46
|
+
| -p | --push | Push the project to remote | `false` |
|
|
47
|
+
| -t | --tag | Create a tag for current version | `false` |
|
|
48
|
+
| -e | --exclude [dir] | Folders to exclude from search | `["node_modules", ".git"]` |
|
|
49
|
+
| -y | --yes | Answer yes to all prompts | `false` |
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
You can specify various runtime settings by using the "package.json" file. Here are some examples that cover all the parameters:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"...": "...",
|
|
58
|
+
"cross-release": {
|
|
59
|
+
// show the help message
|
|
60
|
+
"showHelp": false,
|
|
61
|
+
// show the version about cross-release
|
|
62
|
+
"showVersion": false,
|
|
63
|
+
"version": "",
|
|
64
|
+
"isAllYes": false,
|
|
65
|
+
"isDry": false,
|
|
66
|
+
"isRecursive": false,
|
|
67
|
+
"shouldCommit": false,
|
|
68
|
+
"shouldPublish": false,
|
|
69
|
+
"shouldPush": false,
|
|
70
|
+
"shouldTag": false,
|
|
71
|
+
// default exclude folders are `["node_modules", ".git"]`, your config will be append within it
|
|
72
|
+
"excludes": ["path/to/exclude"],
|
|
73
|
+
"dir": "/path/to/run",
|
|
74
|
+
"commit": {
|
|
75
|
+
// Whether to invoke git pre-commit and commit-msg hook
|
|
76
|
+
"shouldVerify": true,
|
|
77
|
+
// Whether to stage all un-staged files or stage only changed files
|
|
78
|
+
"shouldStageAll": false,
|
|
79
|
+
// the symbol '%s' will be replace to the version number that you specified
|
|
80
|
+
"template": "chore: release v%s"
|
|
81
|
+
},
|
|
82
|
+
"push": {
|
|
83
|
+
"shouldFollowTags": false
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path$1 = require('path');
|
|
4
|
+
var prompts = require('@clack/prompts');
|
|
5
|
+
var crossBump = require('cross-bump');
|
|
6
|
+
var colorette = require('colorette');
|
|
7
|
+
var isUnicodeSupported = require('is-unicode-supported');
|
|
8
|
+
var path = require('node:path');
|
|
9
|
+
var fs = require('node:fs');
|
|
10
|
+
var cac = require('cac');
|
|
11
|
+
var defu = require('defu');
|
|
12
|
+
var execa = require('execa');
|
|
13
|
+
|
|
14
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
15
|
+
|
|
16
|
+
function _interopNamespace(e) {
|
|
17
|
+
if (e && e.__esModule) return e;
|
|
18
|
+
var n = Object.create(null);
|
|
19
|
+
if (e) {
|
|
20
|
+
Object.keys(e).forEach(function (k) {
|
|
21
|
+
if (k !== 'default') {
|
|
22
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
23
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
get: function () { return e[k]; }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
n["default"] = e;
|
|
31
|
+
return Object.freeze(n);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var path__default = /*#__PURE__*/_interopDefaultLegacy(path$1);
|
|
35
|
+
var isUnicodeSupported__default = /*#__PURE__*/_interopDefaultLegacy(isUnicodeSupported);
|
|
36
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
37
|
+
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
38
|
+
var cac__default = /*#__PURE__*/_interopDefaultLegacy(cac);
|
|
39
|
+
|
|
40
|
+
var version = "0.0.0";
|
|
41
|
+
|
|
42
|
+
const configDefaults = {
|
|
43
|
+
showHelp: false,
|
|
44
|
+
showVersion: false,
|
|
45
|
+
version: "",
|
|
46
|
+
isAllYes: false,
|
|
47
|
+
isDry: false,
|
|
48
|
+
isRecursive: false,
|
|
49
|
+
shouldCommit: false,
|
|
50
|
+
shouldPublish: false,
|
|
51
|
+
shouldPush: false,
|
|
52
|
+
shouldTag: false,
|
|
53
|
+
excludes: ["node_modules", ".git"],
|
|
54
|
+
dir: process.cwd(),
|
|
55
|
+
commit: {
|
|
56
|
+
shouldVerify: true,
|
|
57
|
+
shouldStageAll: false,
|
|
58
|
+
template: "chore: release v%s"
|
|
59
|
+
},
|
|
60
|
+
push: {
|
|
61
|
+
isTagOnly: false
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
function loadUserConfig(overrides) {
|
|
65
|
+
const file = fs__namespace.readFileSync(path__namespace.resolve(process.cwd(), "package.json"), "utf-8");
|
|
66
|
+
const userConfig = JSON.parse(file)["cross-release"];
|
|
67
|
+
return defu.defu(overrides, userConfig, configDefaults);
|
|
68
|
+
}
|
|
69
|
+
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 <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
|
+
const { args, options } = cli;
|
|
72
|
+
const parsedArgs = loadUserConfig({
|
|
73
|
+
dir: options.dir,
|
|
74
|
+
excludes: options.exclude,
|
|
75
|
+
isRecursive: options.recursive,
|
|
76
|
+
isDry: options.dry,
|
|
77
|
+
isAllYes: options.yes,
|
|
78
|
+
showHelp: options.help,
|
|
79
|
+
showVersion: options.version,
|
|
80
|
+
shouldCommit: options.commit,
|
|
81
|
+
shouldPublish: options.publish,
|
|
82
|
+
shouldPush: options.push,
|
|
83
|
+
shouldTag: options.tag,
|
|
84
|
+
version: args[0]
|
|
85
|
+
});
|
|
86
|
+
return parsedArgs;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function gitTag(tagName, options) {
|
|
90
|
+
const s = prompts.spinner();
|
|
91
|
+
s.start("creating tag");
|
|
92
|
+
const { isForce = false, isDel = false, message } = options || {};
|
|
93
|
+
const args = [];
|
|
94
|
+
if (isDel) {
|
|
95
|
+
args.push("--delete");
|
|
96
|
+
} else {
|
|
97
|
+
if (!message || (message == null ? void 0 : message.length) === 0) {
|
|
98
|
+
prompts.log.warn("no message provided, is recommended to provide a message for create an annotated tag");
|
|
99
|
+
} else {
|
|
100
|
+
args.push(
|
|
101
|
+
// Create an annotated tag, which is recommended for releases.
|
|
102
|
+
// See https://git-scm.com/docs/git-tag
|
|
103
|
+
"--annotate",
|
|
104
|
+
// Use the same commit message for the tag
|
|
105
|
+
"--message",
|
|
106
|
+
// formatMessageString(template, nextVersion),
|
|
107
|
+
message
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (isForce)
|
|
112
|
+
args.push("--force");
|
|
113
|
+
args.push(tagName);
|
|
114
|
+
if (!process.env.DRY) {
|
|
115
|
+
try {
|
|
116
|
+
const { command } = await execa.execa("git", ["tag", ...args]);
|
|
117
|
+
console.log(command);
|
|
118
|
+
} catch (e) {
|
|
119
|
+
s.stop(colorette.red(e.shortMessage));
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
s.stop(`create git tag: ${colorette.blue(tagName)}`);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
async function gitCommit(message, options) {
|
|
127
|
+
const s = prompts.spinner();
|
|
128
|
+
s.start("committing");
|
|
129
|
+
const { modifiedFiles = [], shouldStageAll = true, shouldVerify = true } = options || {};
|
|
130
|
+
const args = [];
|
|
131
|
+
if (process.env.DRY) {
|
|
132
|
+
args.push("--dry-run");
|
|
133
|
+
}
|
|
134
|
+
args.push("--message", `"${message}"`);
|
|
135
|
+
if (modifiedFiles.length) {
|
|
136
|
+
await gitAdd(modifiedFiles);
|
|
137
|
+
args.push(...modifiedFiles);
|
|
138
|
+
} else if (shouldStageAll) {
|
|
139
|
+
args.push("--all");
|
|
140
|
+
}
|
|
141
|
+
if (!shouldVerify) {
|
|
142
|
+
args.push("--no-verify");
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
await execa.execa("git", ["commit", ...args]);
|
|
146
|
+
s.stop(`commit message: ${colorette.green(message)}`);
|
|
147
|
+
} catch (e) {
|
|
148
|
+
s.stop(colorette.red(e.shortMessage));
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
async function gitPush(options) {
|
|
154
|
+
const { shouldFollowTags = true, remote, branch } = options || {};
|
|
155
|
+
const s = prompts.spinner();
|
|
156
|
+
s.start("pushing");
|
|
157
|
+
const originUrl = await gitOriginUrl();
|
|
158
|
+
const args = [];
|
|
159
|
+
if (shouldFollowTags) {
|
|
160
|
+
args.push("--follow-tags");
|
|
161
|
+
}
|
|
162
|
+
if (remote) {
|
|
163
|
+
args.push(remote);
|
|
164
|
+
if (branch) {
|
|
165
|
+
args.push(branch);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (process.env.DRY) {
|
|
169
|
+
args.push("--dry-run");
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
await execa.execa("git", ["push", ...args]);
|
|
173
|
+
s.stop(`pushed to repo: ${colorette.gray(originUrl)}`);
|
|
174
|
+
} catch (e) {
|
|
175
|
+
s.stop(colorette.red(e.shortMessage));
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
async function gitOriginUrl() {
|
|
181
|
+
return (await execa.execa("git", ["remote", "get-url", "origin"])).stdout.trim();
|
|
182
|
+
}
|
|
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
|
+
|
|
197
|
+
var ExitCode = /* @__PURE__ */ ((ExitCode2) => {
|
|
198
|
+
ExitCode2[ExitCode2["Success"] = 0] = "Success";
|
|
199
|
+
ExitCode2[ExitCode2["FatalError"] = 1] = "FatalError";
|
|
200
|
+
ExitCode2[ExitCode2["InvalidArgument"] = 9] = "InvalidArgument";
|
|
201
|
+
return ExitCode2;
|
|
202
|
+
})(ExitCode || {});
|
|
203
|
+
|
|
204
|
+
var __accessCheck = (obj, member, msg) => {
|
|
205
|
+
if (!member.has(obj))
|
|
206
|
+
throw TypeError("Cannot " + msg);
|
|
207
|
+
};
|
|
208
|
+
var __privateAdd = (obj, member, value) => {
|
|
209
|
+
if (member.has(obj))
|
|
210
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
211
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
212
|
+
};
|
|
213
|
+
var __privateMethod = (obj, member, method) => {
|
|
214
|
+
__accessCheck(obj, member, "access private method");
|
|
215
|
+
return method;
|
|
216
|
+
};
|
|
217
|
+
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;
|
|
218
|
+
function message(msg) {
|
|
219
|
+
const bar = isUnicodeSupported__default["default"]() ? "\u2502" : "|";
|
|
220
|
+
console.log(`${colorette.gray(bar)} ${msg}`);
|
|
221
|
+
}
|
|
222
|
+
function handleUserCancel() {
|
|
223
|
+
prompts.cancel("User cancel");
|
|
224
|
+
process.exit(ExitCode.InvalidArgument);
|
|
225
|
+
}
|
|
226
|
+
async function chooseVersion(projectVersion) {
|
|
227
|
+
var _a;
|
|
228
|
+
const versionObj = crossBump.parseVersion(projectVersion);
|
|
229
|
+
const {
|
|
230
|
+
nextMajor,
|
|
231
|
+
nextMinor,
|
|
232
|
+
nextPatch,
|
|
233
|
+
nextRelease,
|
|
234
|
+
nextPreMajor,
|
|
235
|
+
nextPreMinor,
|
|
236
|
+
nextPrePatch
|
|
237
|
+
} = crossBump.getNextVersions(versionObj != null ? versionObj : void 0);
|
|
238
|
+
const C_CUSTOM = "custom";
|
|
239
|
+
const versions = [
|
|
240
|
+
{ label: "custom...", value: C_CUSTOM },
|
|
241
|
+
{ label: `next (${nextRelease})`, value: nextRelease },
|
|
242
|
+
{ label: `patch (${nextPatch})`, value: nextPatch },
|
|
243
|
+
{ label: `minor (${nextMinor})`, value: nextMinor },
|
|
244
|
+
{ label: `major (${nextMajor})`, value: nextMajor },
|
|
245
|
+
{ label: `pre-patch (${nextPrePatch})`, value: nextPrePatch },
|
|
246
|
+
{ label: `pre-minor (${nextPreMinor})`, value: nextPreMinor },
|
|
247
|
+
{ label: `pre-major (${nextPreMajor})`, value: nextPreMajor }
|
|
248
|
+
];
|
|
249
|
+
const selectedValue = await prompts.select({
|
|
250
|
+
message: `Pick a project version. (current: ${projectVersion})`,
|
|
251
|
+
options: versions,
|
|
252
|
+
initialValue: (_a = versions[1].value) != null ? _a : C_CUSTOM
|
|
253
|
+
});
|
|
254
|
+
if (!selectedValue || selectedValue === C_CUSTOM) {
|
|
255
|
+
return await prompts.text({
|
|
256
|
+
message: "Input your custom version number",
|
|
257
|
+
placeholder: "version number",
|
|
258
|
+
validate: (value) => {
|
|
259
|
+
if (!crossBump.isVersionValid(value)) {
|
|
260
|
+
return "Invalid";
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
} else {
|
|
265
|
+
return selectedValue;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
class App {
|
|
269
|
+
constructor() {
|
|
270
|
+
__privateAdd(this, _checkDryRun);
|
|
271
|
+
__privateAdd(this, _getNextVersion);
|
|
272
|
+
__privateAdd(this, _getProjects);
|
|
273
|
+
__privateAdd(this, _confirmReleaseOptions);
|
|
274
|
+
__privateAdd(this, _addTask);
|
|
275
|
+
__privateAdd(this, _start);
|
|
276
|
+
__privateAdd(this, _done);
|
|
277
|
+
__privateAdd(this, _check);
|
|
278
|
+
this.currentVersion = "";
|
|
279
|
+
this.nextVersion = "";
|
|
280
|
+
this.modifiedFiles = [];
|
|
281
|
+
// TODO: record the task execution status to rollback when execution fails
|
|
282
|
+
this.taskQueue = [];
|
|
283
|
+
this.taskStatus = "pending";
|
|
284
|
+
this.options = parseOptions();
|
|
285
|
+
}
|
|
286
|
+
async run() {
|
|
287
|
+
__privateMethod(this, _start, start_fn).call(this);
|
|
288
|
+
await __privateMethod(this, _getNextVersion, getNextVersion_fn).call(this);
|
|
289
|
+
await __privateMethod(this, _getProjects, getProjects_fn).call(this);
|
|
290
|
+
await __privateMethod(this, _confirmReleaseOptions, confirmReleaseOptions_fn).call(this);
|
|
291
|
+
for await (const task of this.taskQueue) {
|
|
292
|
+
if (this.taskStatus === "failed") {
|
|
293
|
+
break;
|
|
294
|
+
} else {
|
|
295
|
+
await task.exec();
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
__privateMethod(this, _done, done_fn).call(this);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Accepts a message string template (e.g. "release %s" or "This is the %s release").
|
|
302
|
+
* If the template contains any "%s" placeholders, then they are replaced with the version number;
|
|
303
|
+
* otherwise, the version number is appended to the string.
|
|
304
|
+
*/
|
|
305
|
+
formatMessageString(template, nextVersion) {
|
|
306
|
+
if (template.includes("%s")) {
|
|
307
|
+
return template.replace(/%s/g, nextVersion);
|
|
308
|
+
} else {
|
|
309
|
+
return template + nextVersion;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
_checkDryRun = new WeakSet();
|
|
314
|
+
checkDryRun_fn = function() {
|
|
315
|
+
if (this.options.isDry) {
|
|
316
|
+
prompts.log.message(colorette.bgBlue(" DRY RUN "));
|
|
317
|
+
process.env.DRY = "true";
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
_getNextVersion = new WeakSet();
|
|
321
|
+
getNextVersion_fn = async function() {
|
|
322
|
+
const { dir, excludes, version } = this.options;
|
|
323
|
+
const projectFile = await crossBump.findProjectFiles(dir, excludes);
|
|
324
|
+
if (!projectFile.length) {
|
|
325
|
+
throw new Error("can't found any project file in the project root");
|
|
326
|
+
}
|
|
327
|
+
const projectVersion = await crossBump.getProjectVersion(projectFile[0]);
|
|
328
|
+
this.currentVersion = projectVersion || "";
|
|
329
|
+
if (crossBump.isVersionValid(version)) {
|
|
330
|
+
this.nextVersion = version;
|
|
331
|
+
} else {
|
|
332
|
+
const nextVersion = await chooseVersion(projectVersion);
|
|
333
|
+
if (prompts.isCancel(nextVersion)) {
|
|
334
|
+
handleUserCancel();
|
|
335
|
+
} else {
|
|
336
|
+
this.nextVersion = nextVersion;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
_getProjects = new WeakSet();
|
|
341
|
+
getProjects_fn = async function() {
|
|
342
|
+
const { options: { dir, excludes, isRecursive }, nextVersion, currentVersion } = this;
|
|
343
|
+
const projectFiles = await crossBump.findProjectFiles(dir, excludes, isRecursive);
|
|
344
|
+
__privateMethod(this, _addTask, addTask_fn).call(this, {
|
|
345
|
+
name: "upgradeVersion",
|
|
346
|
+
exec: () => {
|
|
347
|
+
return Promise.all(projectFiles.map(async (projectFile) => {
|
|
348
|
+
await crossBump.upgradeProjectVersion(nextVersion, projectFile).then(() => {
|
|
349
|
+
this.modifiedFiles.push(projectFile.path);
|
|
350
|
+
message(`upgrade version to ${colorette.blue(nextVersion)} for ${colorette.gray(path__default["default"].relative(dir, projectFile.path))}`);
|
|
351
|
+
}).catch((e) => {
|
|
352
|
+
this.taskStatus = "failed";
|
|
353
|
+
prompts.log.error(String(e));
|
|
354
|
+
});
|
|
355
|
+
}));
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
};
|
|
359
|
+
_confirmReleaseOptions = new WeakSet();
|
|
360
|
+
confirmReleaseOptions_fn = async function() {
|
|
361
|
+
const { isAllYes, commit } = this.options;
|
|
362
|
+
const confirmAndSet = async (optionName, message3, taskName, execFn) => {
|
|
363
|
+
if (isAllYes) {
|
|
364
|
+
this.options[optionName] = true;
|
|
365
|
+
} else if (!this.options[optionName]) {
|
|
366
|
+
const confirmation = await prompts.confirm({ message: message3 });
|
|
367
|
+
if (!prompts.isCancel(confirmation)) {
|
|
368
|
+
this.options[optionName] = confirmation;
|
|
369
|
+
} else {
|
|
370
|
+
handleUserCancel();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (this.options[optionName]) {
|
|
374
|
+
__privateMethod(this, _addTask, addTask_fn).call(this, {
|
|
375
|
+
name: taskName,
|
|
376
|
+
exec: execFn
|
|
377
|
+
// rollback: rollbackFn,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
const message2 = this.formatMessageString(commit.template, this.nextVersion);
|
|
382
|
+
await confirmAndSet(
|
|
383
|
+
"shouldCommit",
|
|
384
|
+
"should commit this release?",
|
|
385
|
+
"commit",
|
|
386
|
+
async () => {
|
|
387
|
+
__privateMethod(this, _check, check_fn).call(this, await gitCommit(message2, { modifiedFiles: this.modifiedFiles, shouldStageAll: false }));
|
|
388
|
+
}
|
|
389
|
+
// async () => {
|
|
390
|
+
// if (!process.env.DRY) {
|
|
391
|
+
// await gitReset({ files: this.modifiedFiles })
|
|
392
|
+
// }
|
|
393
|
+
// log.info("rollback: git reset")
|
|
394
|
+
// },
|
|
395
|
+
);
|
|
396
|
+
const tagName = `v${this.nextVersion}`;
|
|
397
|
+
await confirmAndSet(
|
|
398
|
+
"shouldTag",
|
|
399
|
+
"should create a tag for this release?",
|
|
400
|
+
"tag",
|
|
401
|
+
async () => {
|
|
402
|
+
__privateMethod(this, _check, check_fn).call(this, await gitTag(tagName, { message: message2 }));
|
|
403
|
+
}
|
|
404
|
+
// async () => {
|
|
405
|
+
// await gitTag(tagName, { isDel: true })
|
|
406
|
+
// log.info("rollback: git tag")
|
|
407
|
+
// },
|
|
408
|
+
);
|
|
409
|
+
await confirmAndSet(
|
|
410
|
+
"shouldPush",
|
|
411
|
+
"should push to remote repository?",
|
|
412
|
+
"push",
|
|
413
|
+
async () => {
|
|
414
|
+
__privateMethod(this, _check, check_fn).call(this, await gitPush({ shouldFollowTags: this.options.push.isTagOnly }));
|
|
415
|
+
}
|
|
416
|
+
// () => undefined,
|
|
417
|
+
);
|
|
418
|
+
};
|
|
419
|
+
_addTask = new WeakSet();
|
|
420
|
+
addTask_fn = function(task) {
|
|
421
|
+
const expect = this.taskQueue.length + 1;
|
|
422
|
+
return this.taskQueue.push(task) === expect;
|
|
423
|
+
};
|
|
424
|
+
_start = new WeakSet();
|
|
425
|
+
start_fn = function() {
|
|
426
|
+
prompts.intro("Cross release");
|
|
427
|
+
__privateMethod(this, _checkDryRun, checkDryRun_fn).call(this);
|
|
428
|
+
};
|
|
429
|
+
_done = new WeakSet();
|
|
430
|
+
done_fn = function() {
|
|
431
|
+
prompts.outro("Done");
|
|
432
|
+
};
|
|
433
|
+
_check = new WeakSet();
|
|
434
|
+
check_fn = function(status) {
|
|
435
|
+
if (!status) {
|
|
436
|
+
this.taskStatus = "failed";
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
var app = new App();
|
|
440
|
+
|
|
441
|
+
void app.run();
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cross-release-cli",
|
|
3
|
+
"version": "0.0.1-alpha.1",
|
|
4
|
+
"description": "command line app for cross language bump utility",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "rainbowatcher",
|
|
7
|
+
"email": "rainbow-w@qq.com",
|
|
8
|
+
"url": "https://github.com/rainbowatcher"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"homepage": "https://github.com/rainbowatcher/cross-release/blob/main/packages/cross-release-cli/README.md",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/rainbowatcher/cross-release.git"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/rainbowatcher/cross-release/issues"
|
|
18
|
+
},
|
|
19
|
+
"main": "dist/index.cjs",
|
|
20
|
+
"bin": {
|
|
21
|
+
"cross-release": "./bin/cross-release.js"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"bin"
|
|
26
|
+
],
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@clack/prompts": "^0.7.0",
|
|
29
|
+
"cac": "^6.7.14",
|
|
30
|
+
"colorette": "^2.0.20",
|
|
31
|
+
"debug": "^4.3.4",
|
|
32
|
+
"defu": "^6.1.2",
|
|
33
|
+
"execa": "^8.0.1",
|
|
34
|
+
"is-unicode-supported": "^1.3.0",
|
|
35
|
+
"cross-bump": "0.0.1-alpha.1"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "pkgroll"
|
|
39
|
+
}
|
|
40
|
+
}
|