release-it 15.0.0-esm.2 → 15.0.0-esm.5
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 +22 -16
- package/config/release-it.json +5 -1
- package/lib/config.js +7 -15
- package/lib/index.js +13 -21
- package/lib/log.js +1 -1
- package/lib/plugin/GitBase.js +2 -2
- package/lib/plugin/GitRelease.js +1 -1
- package/lib/plugin/Plugin.js +1 -1
- package/lib/plugin/factory.js +5 -5
- package/lib/plugin/git/Git.js +11 -4
- package/lib/plugin/github/GitHub.js +59 -15
- package/lib/plugin/gitlab/GitLab.js +69 -15
- package/lib/plugin/npm/npm.js +3 -2
- package/lib/plugin/version/Version.js +5 -5
- package/lib/shell.js +3 -3
- package/lib/spinner.js +3 -3
- package/lib/util.js +2 -2
- package/package.json +36 -42
- package/test/config.js +21 -28
- package/test/git.init.js +32 -7
- package/test/git.js +5 -2
- package/test/github.js +116 -19
- package/test/gitlab.js +69 -18
- package/test/log.js +1 -1
- package/test/npm.js +12 -3
- package/test/plugins.js +34 -22
- package/test/spinner.js +8 -11
- package/test/stub/config/default/.release-it.json +5 -0
- package/test/stub/config/invalid-config-rc +1 -0
- package/test/stub/config/invalid-config-txt +2 -0
- package/test/stub/config/merge/.release-it.json +5 -0
- package/test/stub/config/merge/package.json +7 -0
- package/test/stub/config/toml/.release-it.toml +2 -0
- package/test/stub/config/yaml/.release-it.yaml +2 -0
- package/test/stub/config/yml/.release-it.yml +2 -0
- package/test/stub/github.js +26 -10
- package/test/stub/gitlab.js +15 -7
- package/test/stub/shell.js +2 -2
- package/test/tasks.interactive.js +2 -3
- package/test/tasks.js +44 -4
- package/test/util/helpers.js +6 -6
- package/test/util/index.js +13 -18
- package/test/utils.js +1 -1
- package/test/version.js +14 -9
- package/config/.codecov.yml +0 -5
- package/config/deprecated.json +0 -1
- package/lib/deprecated.js +0 -22
- package/lib/metrics.js +0 -76
- package/test/deprecated.js +0 -11
- package/test/metrics.js +0 -17
package/README.md
CHANGED
|
@@ -19,7 +19,6 @@ system, and hooks to execute any command you need to test, build, and/or publish
|
|
|
19
19
|
|
|
20
20
|
[](https://github.com/release-it/release-it/actions)
|
|
21
21
|
[](https://www.npmjs.com/package/release-it)
|
|
22
|
-
[](https://codecov.io/gh/release-it/release-it)
|
|
23
22
|
|
|
24
23
|
## Links
|
|
25
24
|
|
|
@@ -156,19 +155,18 @@ remote.
|
|
|
156
155
|
|
|
157
156
|
## GitHub Releases
|
|
158
157
|
|
|
159
|
-
|
|
158
|
+
GitHub projects can have releases attached to Git tags, containing release notes and assets. There are two ways to add
|
|
160
159
|
[GitHub releases](https://help.github.com/articles/creating-releases) in your release-it flow:
|
|
161
160
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
(release-it only needs "repo" access; no "admin" or other scopes).
|
|
165
|
-
- Make sure the token is [available as an environment variable](./docs/environment-variables.md).
|
|
161
|
+
1. Automated (requires a `GITHUB_TOKEN`)
|
|
162
|
+
2. Manual (using the GitHub web interface with pre-populated fields)
|
|
166
163
|
|
|
167
164
|
→ See [GitHub Releases](./docs/github-releases.md) for more details.
|
|
168
165
|
|
|
169
166
|
## GitLab Releases
|
|
170
167
|
|
|
171
|
-
|
|
168
|
+
GitLab projects can have releases attached to Git tags, containing release notes and assets. To automate
|
|
169
|
+
[GitLab releases](https://docs.gitlab.com/ce/user/project/releases/):
|
|
172
170
|
|
|
173
171
|
- Configure `gitlab.release: true`
|
|
174
172
|
- Obtain a [personal access token](https://gitlab.com/profile/personal_access_tokens) (release-it only needs the "api"
|
|
@@ -257,7 +255,7 @@ will run one after another. Some example release-it configuration:
|
|
|
257
255
|
The variables can be found in the [default configuration](./config/release-it.json). Additionally, the following
|
|
258
256
|
variables are exposed:
|
|
259
257
|
|
|
260
|
-
```
|
|
258
|
+
```text
|
|
261
259
|
version
|
|
262
260
|
latestVersion
|
|
263
261
|
changelog
|
|
@@ -273,6 +271,14 @@ Use `--verbose` to log the output of the commands.
|
|
|
273
271
|
For the sake of verbosity, the full list of hooks is actually: `init`, `beforeBump`, `bump`, `beforeRelease`, `release`
|
|
274
272
|
or `afterRelease`. However, hooks like `before:beforeRelease` look weird and are usually not useful in practice.
|
|
275
273
|
|
|
274
|
+
Note that arguments need to be quoted properly when used from the command line:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
release-it --'hooks.after:release="echo Successfully released ${name} v${version} to ${repo.repository}."'
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Using Inquirer.js inside custom hook scripts might cause issues (since release-it also uses this itself).
|
|
281
|
+
|
|
276
282
|
## Plugins
|
|
277
283
|
|
|
278
284
|
Since v11, release-it can be extended in many, many ways. Here are some plugins:
|
|
@@ -300,14 +306,13 @@ Deprecated. Please see [distribution repository](./docs/recipes/distribution-rep
|
|
|
300
306
|
|
|
301
307
|
## Metrics
|
|
302
308
|
|
|
303
|
-
|
|
304
|
-
[lib/metrics.js](./lib/metrics.js). Please consider to not opt-out: more data means more support for future development.
|
|
309
|
+
In release-it v15, anonymous metrics have been removed from the codebase and no data is sent or stored anywhere.
|
|
305
310
|
|
|
306
311
|
## Troubleshooting & debugging
|
|
307
312
|
|
|
308
313
|
- With `release-it --verbose` (or `-V`), release-it prints the output of every user-defined [hook](#hooks).
|
|
309
314
|
- With `release-it -VV`, release-it also prints the output of every internal command.
|
|
310
|
-
- Use `
|
|
315
|
+
- Use `NODE_DEBUG=release-it:* release-it [...]` to print configuration and more error details.
|
|
311
316
|
|
|
312
317
|
Use `verbose: 2` in a configuration file to have the equivalent of `-VV` on the command line.
|
|
313
318
|
|
|
@@ -322,17 +327,18 @@ While mostly used as a CLI tool, release-it can be used as a dependency to integ
|
|
|
322
327
|
- [blockchain/blockchain-wallet-v4-frontend](https://github.com/blockchain/blockchain-wallet-v4-frontend)
|
|
323
328
|
- [callstack/linaria](https://github.com/callstack/linaria)
|
|
324
329
|
- [ember-cli/ember-cli](https://github.com/ember-cli/ember-cli)
|
|
325
|
-
|
|
330
|
+
- [metalsmith/metalsmith](https://github.com/metalsmith/metalsmith)
|
|
331
|
+
- [react-native-paper](https://github.com/callstack/react-native-paper)
|
|
326
332
|
- [js-cookie/js-cookie](https://github.com/js-cookie/js-cookie)
|
|
327
|
-
- [
|
|
333
|
+
- [saleor/saleor](https://github.com/saleor/saleor)
|
|
328
334
|
- [mozilla/readability](https://github.com/mozilla/readability)
|
|
329
|
-
- [
|
|
335
|
+
- [redis/node-redis](https://github.com/redis/node-redis)
|
|
330
336
|
- [shipshapecode/shepherd](https://github.com/shipshapecode/shepherd)
|
|
331
337
|
- [swagger-api/swagger-ui](https://github.com/swagger-api/swagger-ui) +
|
|
332
338
|
[swagger-editor](https://github.com/swagger-api/swagger-editor)
|
|
333
339
|
- [StevenBlack/hosts](https://github.com/StevenBlack/hosts)
|
|
334
|
-
- [tabler](https://github.com/tabler/tabler) + [tabler-icons](https://github.com/tabler/tabler-icons)
|
|
335
|
-
- [youzan/vant](https://github.com/youzan/vant
|
|
340
|
+
- [tabler/tabler](https://github.com/tabler/tabler) + [tabler-icons](https://github.com/tabler/tabler-icons)
|
|
341
|
+
- [youzan/vant](https://github.com/youzan/vant)
|
|
336
342
|
- [Repositories that depend on release-it](https://github.com/release-it/release-it/network/dependents)
|
|
337
343
|
- GitHub search for [filename:.release-it.json](https://github.com/search?q=filename%3A.release-it.json)
|
|
338
344
|
|
package/config/release-it.json
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"tag": null,
|
|
27
27
|
"otp": null,
|
|
28
28
|
"ignoreVersion": false,
|
|
29
|
+
"allowSameVersion": false,
|
|
29
30
|
"skipChecks": false,
|
|
30
31
|
"timeout": 10
|
|
31
32
|
},
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
"release": false,
|
|
34
35
|
"releaseName": "Release ${version}",
|
|
35
36
|
"releaseNotes": null,
|
|
37
|
+
"autoGenerate": false,
|
|
36
38
|
"preRelease": false,
|
|
37
39
|
"draft": false,
|
|
38
40
|
"tokenRef": "GITHUB_TOKEN",
|
|
@@ -40,12 +42,14 @@
|
|
|
40
42
|
"host": null,
|
|
41
43
|
"timeout": 0,
|
|
42
44
|
"proxy": null,
|
|
43
|
-
"skipChecks": false
|
|
45
|
+
"skipChecks": false,
|
|
46
|
+
"web": false
|
|
44
47
|
},
|
|
45
48
|
"gitlab": {
|
|
46
49
|
"release": false,
|
|
47
50
|
"releaseName": "Release ${version}",
|
|
48
51
|
"releaseNotes": null,
|
|
52
|
+
"milestones": [],
|
|
49
53
|
"tokenRef": "GITLAB_TOKEN",
|
|
50
54
|
"tokenHeader": "Private-Token",
|
|
51
55
|
"certificateAuthorityFile": null,
|
package/lib/config.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
+
import util from 'node:util';
|
|
1
2
|
import { cosmiconfigSync } from 'cosmiconfig';
|
|
2
|
-
import parseJson from 'parse-json';
|
|
3
3
|
import parseToml from '@iarna/toml/parse-string.js';
|
|
4
|
-
import yaml from 'yaml';
|
|
5
4
|
import _ from 'lodash';
|
|
6
5
|
import isCI from 'is-ci';
|
|
7
|
-
import _debug from 'debug';
|
|
8
6
|
import { readJSON, getSystemInfo } from './util.js';
|
|
9
7
|
|
|
10
|
-
const debug =
|
|
8
|
+
const debug = util.debug('release-it:config');
|
|
11
9
|
const defaultConfig = readJSON(new URL('../config/release-it.json', import.meta.url));
|
|
12
10
|
|
|
13
11
|
const searchPlaces = [
|
|
@@ -21,19 +19,17 @@ const searchPlaces = [
|
|
|
21
19
|
];
|
|
22
20
|
|
|
23
21
|
const loaders = {
|
|
24
|
-
'.
|
|
25
|
-
'.toml': (_, content) => parseToml(content),
|
|
26
|
-
'.yaml': (_, content) => yaml.parse(content)
|
|
22
|
+
'.toml': (_, content) => parseToml(content)
|
|
27
23
|
};
|
|
28
24
|
|
|
29
|
-
const getLocalConfig =
|
|
25
|
+
const getLocalConfig = ({ file, dir = process.cwd() }) => {
|
|
30
26
|
let localConfig = {};
|
|
31
|
-
if (
|
|
27
|
+
if (file === false) return localConfig;
|
|
32
28
|
const explorer = cosmiconfigSync('release-it', {
|
|
33
29
|
searchPlaces,
|
|
34
30
|
loaders
|
|
35
31
|
});
|
|
36
|
-
const result =
|
|
32
|
+
const result = file ? explorer.load(file) : explorer.search(dir);
|
|
37
33
|
if (result && typeof result.config === 'string') {
|
|
38
34
|
throw new Error(`Invalid configuration file at ${result.filepath}`);
|
|
39
35
|
}
|
|
@@ -44,7 +40,7 @@ const getLocalConfig = localConfigFile => {
|
|
|
44
40
|
class Config {
|
|
45
41
|
constructor(config = {}) {
|
|
46
42
|
this.constructorConfig = config;
|
|
47
|
-
this.localConfig = getLocalConfig(config.config);
|
|
43
|
+
this.localConfig = getLocalConfig({ file: config.config, dir: config.configDir });
|
|
48
44
|
this.options = this.mergeOptions();
|
|
49
45
|
this.options = this.expandPreReleaseShorthand(this.options);
|
|
50
46
|
this.contextOptions = {};
|
|
@@ -123,10 +119,6 @@ class Config {
|
|
|
123
119
|
get isReleaseVersion() {
|
|
124
120
|
return Boolean(this.options['release-version']);
|
|
125
121
|
}
|
|
126
|
-
|
|
127
|
-
get isCollectMetrics() {
|
|
128
|
-
return !this.options['disable-metrics'];
|
|
129
|
-
}
|
|
130
122
|
}
|
|
131
123
|
|
|
132
124
|
export default Config;
|
package/lib/index.js
CHANGED
|
@@ -5,9 +5,7 @@ import Config from './config.js';
|
|
|
5
5
|
import Shell from './shell.js';
|
|
6
6
|
import Prompt from './prompt.js';
|
|
7
7
|
import Spinner from './spinner.js';
|
|
8
|
-
import Metrics from './metrics.js';
|
|
9
8
|
import { reduceUntil, parseVersion } from './util.js';
|
|
10
|
-
import handleDeprecated from './deprecated.js';
|
|
11
9
|
import Plugin from './plugin/Plugin.js';
|
|
12
10
|
|
|
13
11
|
const runTasks = async (opts, di) => {
|
|
@@ -23,14 +21,11 @@ const runTasks = async (opts, di) => {
|
|
|
23
21
|
container.log = container.log || new Logger({ isCI, isVerbose, verbosityLevel, isDryRun });
|
|
24
22
|
container.spinner = container.spinner || new Spinner({ container, config });
|
|
25
23
|
container.prompt = container.prompt || new Prompt({ container: { config } });
|
|
26
|
-
container.metrics = new Metrics({ isEnabled: config.isCollectMetrics });
|
|
27
24
|
container.shell = container.shell || new Shell({ container });
|
|
28
25
|
|
|
29
|
-
const { log,
|
|
26
|
+
const { log, shell, spinner } = container;
|
|
30
27
|
|
|
31
|
-
const options =
|
|
32
|
-
|
|
33
|
-
metrics.trackEvent('start', options);
|
|
28
|
+
const options = config.getContext();
|
|
34
29
|
|
|
35
30
|
const { hooks } = options;
|
|
36
31
|
|
|
@@ -65,7 +60,7 @@ const runTasks = async (opts, di) => {
|
|
|
65
60
|
const { increment, isPreRelease, preReleaseId } = options.version;
|
|
66
61
|
|
|
67
62
|
const name = await reduceUntil(plugins, plugin => plugin.getName());
|
|
68
|
-
const latestVersion = await reduceUntil(plugins, plugin => plugin.getLatestVersion());
|
|
63
|
+
const latestVersion = (await reduceUntil(plugins, plugin => plugin.getLatestVersion())) || '0.0.0';
|
|
69
64
|
const changelog = await reduceUntil(plugins, plugin => plugin.getChangelog(latestVersion));
|
|
70
65
|
|
|
71
66
|
const incrementBase = { latestVersion, increment, isPreRelease, preReleaseId };
|
|
@@ -78,24 +73,26 @@ const runTasks = async (opts, di) => {
|
|
|
78
73
|
version = latestVersion;
|
|
79
74
|
}
|
|
80
75
|
|
|
81
|
-
if (config.isReleaseVersion) {
|
|
82
|
-
log.log(version);
|
|
83
|
-
process.exit(0);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
76
|
config.setContext({ name, latestVersion, version, changelog });
|
|
87
77
|
|
|
88
78
|
const action = config.isIncrement ? 'release' : 'update';
|
|
89
79
|
const suffix = version && config.isIncrement ? `${latestVersion}...${version}` : `currently at ${latestVersion}`;
|
|
90
80
|
|
|
91
|
-
|
|
81
|
+
if (!config.isReleaseVersion) {
|
|
82
|
+
log.obtrusive(`🚀 Let's ${action} ${name} (${suffix})`);
|
|
92
83
|
|
|
93
|
-
|
|
84
|
+
log.preview({ title: 'changelog', text: changelog });
|
|
85
|
+
}
|
|
94
86
|
|
|
95
87
|
if (config.isIncrement) {
|
|
96
88
|
version = version || (await reduceUntil(plugins, plugin => plugin.getIncrementedVersion(incrementBase)));
|
|
97
89
|
}
|
|
98
90
|
|
|
91
|
+
if (config.isReleaseVersion) {
|
|
92
|
+
console.log(version);
|
|
93
|
+
process.exit(0);
|
|
94
|
+
}
|
|
95
|
+
|
|
99
96
|
config.setContext(parseVersion(version));
|
|
100
97
|
|
|
101
98
|
if (config.isPromptOnlyVersion) {
|
|
@@ -117,8 +114,6 @@ const runTasks = async (opts, di) => {
|
|
|
117
114
|
}
|
|
118
115
|
}
|
|
119
116
|
|
|
120
|
-
await metrics.trackEvent('end');
|
|
121
|
-
|
|
122
117
|
log.log(`🏁 Done (in ${Math.floor(process.uptime())}s.)`);
|
|
123
118
|
|
|
124
119
|
return {
|
|
@@ -128,10 +123,7 @@ const runTasks = async (opts, di) => {
|
|
|
128
123
|
version
|
|
129
124
|
};
|
|
130
125
|
} catch (err) {
|
|
131
|
-
const { log
|
|
132
|
-
if (metrics) {
|
|
133
|
-
await metrics.trackException(err);
|
|
134
|
-
}
|
|
126
|
+
const { log } = container;
|
|
135
127
|
log ? log.error(err.message || err) : console.error(err); // eslint-disable-line no-console
|
|
136
128
|
throw err;
|
|
137
129
|
}
|
package/lib/log.js
CHANGED
package/lib/plugin/GitBase.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EOL } from 'os';
|
|
1
|
+
import { EOL } from 'node:os';
|
|
2
2
|
import { format, parseGitUrl } from '../util.js';
|
|
3
3
|
import Plugin from './Plugin.js';
|
|
4
4
|
|
|
@@ -99,7 +99,7 @@ class GitBase extends Plugin {
|
|
|
99
99
|
const sha = await this.exec(`git rev-list ${latestTag || '--skip=1'} --tags --max-count=1`, {
|
|
100
100
|
options
|
|
101
101
|
});
|
|
102
|
-
return this.exec(`git describe --tags --abbrev=0 ${sha}
|
|
102
|
+
return this.exec(`git describe --tags --abbrev=0 "${sha}^"`, { options }).catch(() => null);
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
package/lib/plugin/GitRelease.js
CHANGED
|
@@ -12,7 +12,7 @@ class GitRelease extends GitBase {
|
|
|
12
12
|
getInitialOptions(options) {
|
|
13
13
|
const baseOptions = super.getInitialOptions(...arguments);
|
|
14
14
|
const git = options.git || defaultConfig.git;
|
|
15
|
-
const gitOptions = _.pick(git, ['tagName', 'pushRepo', 'changelog']);
|
|
15
|
+
const gitOptions = _.pick(git, ['tagName', 'tagMatch', 'pushRepo', 'changelog']);
|
|
16
16
|
return _.defaults(baseOptions, gitOptions);
|
|
17
17
|
}
|
|
18
18
|
|
package/lib/plugin/Plugin.js
CHANGED
package/lib/plugin/factory.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import url from 'url';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import
|
|
1
|
+
import url from 'node:url';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import util from 'node:util';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
4
5
|
import _ from 'lodash';
|
|
5
|
-
import _debug from 'debug';
|
|
6
6
|
import Version from './version/Version.js';
|
|
7
7
|
import Git from './git/Git.js';
|
|
8
8
|
import GitLab from './gitlab/GitLab.js';
|
|
9
9
|
import GitHub from './github/GitHub.js';
|
|
10
10
|
import npm from './npm/npm.js';
|
|
11
11
|
|
|
12
|
-
const debug =
|
|
12
|
+
const debug = util.debug('release-it:plugins');
|
|
13
13
|
|
|
14
14
|
const pluginNames = ['npm', 'git', 'github', 'gitlab', 'version'];
|
|
15
15
|
|
package/lib/plugin/git/Git.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { EOL } from 'os';
|
|
1
|
+
import { EOL } from 'node:os';
|
|
2
2
|
import _ from 'lodash';
|
|
3
|
-
import
|
|
3
|
+
import { execa } from 'execa';
|
|
4
|
+
import matcher from 'wildcard-match';
|
|
4
5
|
import { format, e } from '../../util.js';
|
|
5
6
|
import GitBase from '../GitBase.js';
|
|
6
7
|
import prompts from './prompts.js';
|
|
@@ -12,6 +13,12 @@ const fixArgs = args => (args ? (typeof args === 'string' ? args.split(' ') : ar
|
|
|
12
13
|
|
|
13
14
|
const docs = 'https://git.io/release-it-git';
|
|
14
15
|
|
|
16
|
+
const isGitRepo = () =>
|
|
17
|
+
execa('git', ['rev-parse', '--git-dir']).then(
|
|
18
|
+
() => true,
|
|
19
|
+
() => false
|
|
20
|
+
);
|
|
21
|
+
|
|
15
22
|
class Git extends GitBase {
|
|
16
23
|
constructor(...args) {
|
|
17
24
|
super(...args);
|
|
@@ -19,7 +26,7 @@ class Git extends GitBase {
|
|
|
19
26
|
}
|
|
20
27
|
|
|
21
28
|
static async isEnabled(options) {
|
|
22
|
-
return options !== false && (await
|
|
29
|
+
return options !== false && (await isGitRepo());
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
async init() {
|
|
@@ -88,7 +95,7 @@ class Git extends GitBase {
|
|
|
88
95
|
async isRequiredBranch() {
|
|
89
96
|
const branch = await this.getBranchName();
|
|
90
97
|
const requiredBranches = _.castArray(this.options.requireBranch);
|
|
91
|
-
return requiredBranches
|
|
98
|
+
return matcher(requiredBranches)(branch);
|
|
92
99
|
}
|
|
93
100
|
|
|
94
101
|
async hasUpstreamBranch() {
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import open from 'open';
|
|
3
4
|
import { Octokit } from '@octokit/rest';
|
|
4
|
-
import globby from 'globby';
|
|
5
|
+
import { globby } from 'globby';
|
|
5
6
|
import mime from 'mime-types';
|
|
6
7
|
import _ from 'lodash';
|
|
7
8
|
import retry from 'async-retry';
|
|
9
|
+
import newGithubReleaseUrl from 'new-github-release-url';
|
|
10
|
+
import ProxyAgent from 'proxy-agent';
|
|
8
11
|
import { format, parseVersion, readJSON, e } from '../../util.js';
|
|
9
12
|
import Release from '../GitRelease.js';
|
|
10
13
|
import prompts from './prompts.js';
|
|
@@ -21,7 +24,7 @@ const parseErrormsg = err => {
|
|
|
21
24
|
let msg = err;
|
|
22
25
|
if (err instanceof Error) {
|
|
23
26
|
const { status, message } = err;
|
|
24
|
-
const
|
|
27
|
+
const headers = err.response ? err.response.headers : {};
|
|
25
28
|
msg = `${_.get(headers, 'status', status)} (${message})`;
|
|
26
29
|
}
|
|
27
30
|
return msg;
|
|
@@ -36,13 +39,22 @@ class GitHub extends Release {
|
|
|
36
39
|
async init() {
|
|
37
40
|
await super.init();
|
|
38
41
|
|
|
39
|
-
const { skipChecks, tokenRef, update } = this.options;
|
|
42
|
+
const { skipChecks, tokenRef, web, update, assets } = this.options;
|
|
40
43
|
|
|
41
|
-
if (!
|
|
42
|
-
if (!
|
|
43
|
-
|
|
44
|
+
if (!this.token || web) {
|
|
45
|
+
if (!web) {
|
|
46
|
+
this.log.warn(`Environment variable "${tokenRef}" is required for automated GitHub Releases.`);
|
|
47
|
+
this.log.warn('Falling back to web-based GitHub Release.');
|
|
44
48
|
}
|
|
49
|
+
this.setContext({ isWeb: true });
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
45
52
|
|
|
53
|
+
if (web && assets) {
|
|
54
|
+
this.log.warn('Assets are not included in web-based releases.');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!skipChecks) {
|
|
46
58
|
// If we're running on GitHub Actions, we can skip the authentication and
|
|
47
59
|
// collaborator checks. Ref: https://bit.ly/2vsyRzu
|
|
48
60
|
if (process.env.GITHUB_ACTIONS) {
|
|
@@ -108,13 +120,16 @@ class GitHub extends Release {
|
|
|
108
120
|
|
|
109
121
|
async release() {
|
|
110
122
|
const { assets } = this.options;
|
|
111
|
-
const { isUpdate } = this.getContext();
|
|
123
|
+
const { isWeb, isUpdate } = this.getContext();
|
|
112
124
|
const { isCI } = this.config;
|
|
113
125
|
|
|
114
126
|
const type = isUpdate ? 'update' : 'create';
|
|
115
127
|
const publishMethod = `${type}Release`;
|
|
116
128
|
|
|
117
|
-
if (
|
|
129
|
+
if (isWeb) {
|
|
130
|
+
const task = () => this.createWebRelease();
|
|
131
|
+
return this.step({ task, label: 'Generating link to GitHub Release web interface', prompt: 'release' });
|
|
132
|
+
} else if (isCI) {
|
|
118
133
|
await this.step({ task: () => this[publishMethod](), label: `GitHub ${type} release` });
|
|
119
134
|
return this.step({ enabled: assets, task: () => this.uploadAssets(), label: 'GitHub upload assets' });
|
|
120
135
|
} else {
|
|
@@ -154,7 +169,7 @@ class GitHub extends Release {
|
|
|
154
169
|
};
|
|
155
170
|
|
|
156
171
|
if (proxy) {
|
|
157
|
-
options.
|
|
172
|
+
options.request.agent = new ProxyAgent(proxy);
|
|
158
173
|
}
|
|
159
174
|
|
|
160
175
|
const client = new Octokit(options);
|
|
@@ -178,12 +193,12 @@ class GitHub extends Release {
|
|
|
178
193
|
|
|
179
194
|
getOctokitReleaseOptions(options = {}) {
|
|
180
195
|
const { owner, project: repo } = this.getContext('repo');
|
|
181
|
-
const { releaseName, draft = false, preRelease = false } = this.options;
|
|
196
|
+
const { releaseName, draft = false, preRelease = false, autoGenerate = false } = this.options;
|
|
182
197
|
const { tagName } = this.config.getContext();
|
|
183
|
-
const { version, releaseNotes } = this.getContext();
|
|
198
|
+
const { version, releaseNotes, isUpdate } = this.getContext();
|
|
184
199
|
const { isPreRelease } = parseVersion(version);
|
|
185
200
|
const name = format(releaseName, this.config.getContext());
|
|
186
|
-
const body = releaseNotes;
|
|
201
|
+
const body = autoGenerate ? (isUpdate ? null : '') : releaseNotes;
|
|
187
202
|
|
|
188
203
|
return Object.assign(options, {
|
|
189
204
|
owner,
|
|
@@ -192,7 +207,8 @@ class GitHub extends Release {
|
|
|
192
207
|
name,
|
|
193
208
|
body,
|
|
194
209
|
draft,
|
|
195
|
-
prerelease: isPreRelease || preRelease
|
|
210
|
+
prerelease: isPreRelease || preRelease,
|
|
211
|
+
generate_release_notes: autoGenerate
|
|
196
212
|
});
|
|
197
213
|
}
|
|
198
214
|
|
|
@@ -285,6 +301,34 @@ class GitHub extends Release {
|
|
|
285
301
|
return `https://${host}/${repository}/releases/tag/${tagName}`;
|
|
286
302
|
}
|
|
287
303
|
|
|
304
|
+
generateWebUrl() {
|
|
305
|
+
const host = this.options.host || this.getContext('repo.host');
|
|
306
|
+
const isGitHub = host === 'github.com';
|
|
307
|
+
|
|
308
|
+
const options = this.getOctokitReleaseOptions();
|
|
309
|
+
const url = newGithubReleaseUrl({
|
|
310
|
+
user: options.owner,
|
|
311
|
+
repo: options.repo,
|
|
312
|
+
tag: options.tag_name,
|
|
313
|
+
isPrerelease: options.prerelease,
|
|
314
|
+
title: options.name,
|
|
315
|
+
body: options.body
|
|
316
|
+
});
|
|
317
|
+
return isGitHub ? url : url.replace('github.com', host);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
async createWebRelease() {
|
|
321
|
+
const { isCI } = this.config;
|
|
322
|
+
const { tagName } = this.config.getContext();
|
|
323
|
+
const url = this.generateWebUrl();
|
|
324
|
+
if (isCI) {
|
|
325
|
+
this.setContext({ isReleased: true, releaseUrl: url });
|
|
326
|
+
} else {
|
|
327
|
+
await open(url);
|
|
328
|
+
this.setContext({ isReleased: true, releaseUrl: this.getReleaseUrlFallback(tagName) });
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
288
332
|
updateRelease() {
|
|
289
333
|
const { isDryRun } = this.config;
|
|
290
334
|
const release_id = this.getContext('releaseId');
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
3
|
import got from 'got';
|
|
4
|
-
import globby from 'globby';
|
|
4
|
+
import { globby } from 'globby';
|
|
5
5
|
import FormData from 'form-data';
|
|
6
|
+
import allSettled from 'promise.allsettled';
|
|
6
7
|
import _ from 'lodash';
|
|
7
8
|
import Release from '../GitRelease.js';
|
|
8
9
|
import { format, e } from '../../util.js';
|
|
@@ -91,20 +92,68 @@ class GitLab extends Release {
|
|
|
91
92
|
return access_level && access_level >= 30;
|
|
92
93
|
} catch (err) {
|
|
93
94
|
this.debug(err);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async beforeRelease() {
|
|
100
|
+
await super.beforeRelease();
|
|
101
|
+
await this.checkReleaseMilestones();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async checkReleaseMilestones() {
|
|
105
|
+
if (this.options.skipChecks) return;
|
|
106
|
+
|
|
107
|
+
const releaseMilestones = this.getReleaseMilestones();
|
|
108
|
+
if (releaseMilestones.length < 1) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
this.log.exec(`gitlab releases#checkReleaseMilestones`);
|
|
113
|
+
|
|
114
|
+
const { id } = this.getContext();
|
|
115
|
+
const endpoint = `projects/${id}/milestones`;
|
|
116
|
+
const requests = releaseMilestones.map(milestone => {
|
|
117
|
+
const options = {
|
|
118
|
+
method: 'GET',
|
|
119
|
+
searchParams: {
|
|
120
|
+
title: milestone,
|
|
121
|
+
include_parent_milestones: true
|
|
103
122
|
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
123
|
+
};
|
|
124
|
+
return this.request(endpoint, options).then(response => {
|
|
125
|
+
if (!Array.isArray(response)) {
|
|
126
|
+
const { baseUrl } = this.getContext();
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Unexpected response from ${baseUrl}/${endpoint}. Expected an array but got: ${JSON.stringify(response)}`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (response.length === 0) {
|
|
132
|
+
const error = new Error(`Milestone '${milestone}' does not exist.`);
|
|
133
|
+
this.log.warn(error.message);
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
this.log.verbose(`gitlab releases#checkReleaseMilestones: milestone '${milestone}' exists`);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
try {
|
|
140
|
+
await allSettled(requests).then(results => {
|
|
141
|
+
for (const result of results) {
|
|
142
|
+
if (result.status === 'rejected') {
|
|
143
|
+
throw e('Missing one or more milestones in GitLab. Creating a GitLab release will fail.', docs);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
} catch (err) {
|
|
148
|
+
this.debug(err);
|
|
149
|
+
throw err;
|
|
107
150
|
}
|
|
151
|
+
this.log.verbose('gitlab releases#checkReleaseMilestones: done');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
getReleaseMilestones() {
|
|
155
|
+
const { milestones } = this.options;
|
|
156
|
+
return (milestones || []).map(milestone => format(milestone, this.config.getContext()));
|
|
108
157
|
}
|
|
109
158
|
|
|
110
159
|
async release() {
|
|
@@ -138,6 +187,7 @@ class GitLab extends Release {
|
|
|
138
187
|
const name = format(releaseName, this.config.getContext());
|
|
139
188
|
const description = releaseNotes || '-';
|
|
140
189
|
const releaseUrl = `${origin}/${repo.repository}/-/releases`;
|
|
190
|
+
const releaseMilestones = this.getReleaseMilestones();
|
|
141
191
|
|
|
142
192
|
this.log.exec(`gitlab releases#createRelease "${name}" (${tagName})`, { isDryRun });
|
|
143
193
|
|
|
@@ -161,6 +211,10 @@ class GitLab extends Release {
|
|
|
161
211
|
};
|
|
162
212
|
}
|
|
163
213
|
|
|
214
|
+
if (releaseMilestones.length) {
|
|
215
|
+
options.json.milestones = releaseMilestones;
|
|
216
|
+
}
|
|
217
|
+
|
|
164
218
|
try {
|
|
165
219
|
await this.request(endpoint, options);
|
|
166
220
|
this.log.verbose('gitlab releases#createRelease: done');
|
package/lib/plugin/npm/npm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import path from 'path';
|
|
1
|
+
import path from 'node:path';
|
|
2
2
|
import semver from 'semver';
|
|
3
3
|
import urlJoin from 'url-join';
|
|
4
4
|
import Plugin from '../Plugin.js';
|
|
@@ -82,7 +82,8 @@ class npm extends Plugin {
|
|
|
82
82
|
|
|
83
83
|
if (!this.config.isIncrement) return false;
|
|
84
84
|
|
|
85
|
-
const
|
|
85
|
+
const allowSameVersion = this.options.allowSameVersion ? ' --allow-same-version' : '';
|
|
86
|
+
const task = () => this.exec(`npm version ${version} --no-git-tag-version${allowSameVersion}`);
|
|
86
87
|
return this.spinner.show({ task, label: 'npm version' });
|
|
87
88
|
}
|
|
88
89
|
|