release-it 15.0.0-esm.2 → 15.0.0-esm.3
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 +6 -7
- package/config/release-it.json +2 -1
- package/lib/index.js +1 -1
- package/lib/plugin/GitBase.js +1 -1
- package/lib/plugin/git/Git.js +8 -2
- package/lib/plugin/github/GitHub.js +46 -8
- package/lib/plugin/gitlab/GitLab.js +1 -1
- package/lib/plugin/version/Version.js +0 -4
- package/lib/shell.js +1 -1
- package/lib/spinner.js +3 -3
- package/package.json +28 -27
- package/test/config.js +2 -2
- package/test/github.js +77 -9
- package/test/plugins.js +1 -1
- package/test/spinner.js +7 -9
- package/test/tasks.js +41 -0
- package/test/util/index.js +1 -1
- package/test/version.js +7 -7
package/README.md
CHANGED
|
@@ -156,19 +156,18 @@ remote.
|
|
|
156
156
|
|
|
157
157
|
## GitHub Releases
|
|
158
158
|
|
|
159
|
-
|
|
159
|
+
GitHub projects can have releases attached to Git tags, containing release notes and assets. There are two ways to add
|
|
160
160
|
[GitHub releases](https://help.github.com/articles/creating-releases) in your release-it flow:
|
|
161
161
|
|
|
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).
|
|
162
|
+
1. Automated (requires a `GITHUB_TOKEN`)
|
|
163
|
+
2. Manual (using the GitHub web interface with pre-populated fields)
|
|
166
164
|
|
|
167
165
|
→ See [GitHub Releases](./docs/github-releases.md) for more details.
|
|
168
166
|
|
|
169
167
|
## GitLab Releases
|
|
170
168
|
|
|
171
|
-
|
|
169
|
+
GitLab projects can have releases attached to Git tags, containing release notes and assets. To automate
|
|
170
|
+
[GitLab releases](https://docs.gitlab.com/ce/user/project/releases/):
|
|
172
171
|
|
|
173
172
|
- Configure `gitlab.release: true`
|
|
174
173
|
- Obtain a [personal access token](https://gitlab.com/profile/personal_access_tokens) (release-it only needs the "api"
|
|
@@ -322,7 +321,7 @@ While mostly used as a CLI tool, release-it can be used as a dependency to integ
|
|
|
322
321
|
- [blockchain/blockchain-wallet-v4-frontend](https://github.com/blockchain/blockchain-wallet-v4-frontend)
|
|
323
322
|
- [callstack/linaria](https://github.com/callstack/linaria)
|
|
324
323
|
- [ember-cli/ember-cli](https://github.com/ember-cli/ember-cli)
|
|
325
|
-
|
|
324
|
+
- [react-native-paper](https://github.com/callstack/react-native-paper)
|
|
326
325
|
- [js-cookie/js-cookie](https://github.com/js-cookie/js-cookie)
|
|
327
326
|
- [mirumee/saleor](https://github.com/mirumee/saleor)
|
|
328
327
|
- [mozilla/readability](https://github.com/mozilla/readability)
|
package/config/release-it.json
CHANGED
package/lib/index.js
CHANGED
|
@@ -65,7 +65,7 @@ const runTasks = async (opts, di) => {
|
|
|
65
65
|
const { increment, isPreRelease, preReleaseId } = options.version;
|
|
66
66
|
|
|
67
67
|
const name = await reduceUntil(plugins, plugin => plugin.getName());
|
|
68
|
-
const latestVersion = await reduceUntil(plugins, plugin => plugin.getLatestVersion());
|
|
68
|
+
const latestVersion = (await reduceUntil(plugins, plugin => plugin.getLatestVersion())) || '0.0.0';
|
|
69
69
|
const changelog = await reduceUntil(plugins, plugin => plugin.getChangelog(latestVersion));
|
|
70
70
|
|
|
71
71
|
const incrementBase = { latestVersion, increment, isPreRelease, preReleaseId };
|
package/lib/plugin/GitBase.js
CHANGED
|
@@ -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/git/Git.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EOL } from 'os';
|
|
2
2
|
import _ from 'lodash';
|
|
3
|
-
import
|
|
3
|
+
import { execa } from 'execa';
|
|
4
4
|
import { format, e } from '../../util.js';
|
|
5
5
|
import GitBase from '../GitBase.js';
|
|
6
6
|
import prompts from './prompts.js';
|
|
@@ -12,6 +12,12 @@ const fixArgs = args => (args ? (typeof args === 'string' ? args.split(' ') : ar
|
|
|
12
12
|
|
|
13
13
|
const docs = 'https://git.io/release-it-git';
|
|
14
14
|
|
|
15
|
+
const isGitRepo = () =>
|
|
16
|
+
execa('git', ['rev-parse', '--git-dir']).then(
|
|
17
|
+
() => true,
|
|
18
|
+
() => false
|
|
19
|
+
);
|
|
20
|
+
|
|
15
21
|
class Git extends GitBase {
|
|
16
22
|
constructor(...args) {
|
|
17
23
|
super(...args);
|
|
@@ -19,7 +25,7 @@ class Git extends GitBase {
|
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
static async isEnabled(options) {
|
|
22
|
-
return options !== false && (await
|
|
28
|
+
return options !== false && (await isGitRepo());
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
async init() {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from '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';
|
|
8
10
|
import { format, parseVersion, readJSON, e } from '../../util.js';
|
|
9
11
|
import Release from '../GitRelease.js';
|
|
10
12
|
import prompts from './prompts.js';
|
|
@@ -21,7 +23,7 @@ const parseErrormsg = err => {
|
|
|
21
23
|
let msg = err;
|
|
22
24
|
if (err instanceof Error) {
|
|
23
25
|
const { status, message } = err;
|
|
24
|
-
const
|
|
26
|
+
const headers = err.response ? err.response.headers : {};
|
|
25
27
|
msg = `${_.get(headers, 'status', status)} (${message})`;
|
|
26
28
|
}
|
|
27
29
|
return msg;
|
|
@@ -36,13 +38,18 @@ class GitHub extends Release {
|
|
|
36
38
|
async init() {
|
|
37
39
|
await super.init();
|
|
38
40
|
|
|
39
|
-
const { skipChecks, tokenRef, update } = this.options;
|
|
41
|
+
const { skipChecks, tokenRef, web, update } = this.options;
|
|
40
42
|
|
|
41
|
-
if (!
|
|
42
|
-
if (!
|
|
43
|
-
|
|
43
|
+
if (!this.token || web) {
|
|
44
|
+
if (!web) {
|
|
45
|
+
this.log.warn(`Environment variable "${tokenRef}" is required for automated GitHub Releases.`);
|
|
46
|
+
this.log.warn('Falling back to web-based GitHub Release.');
|
|
44
47
|
}
|
|
48
|
+
this.setContext({ isWeb: true });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
45
51
|
|
|
52
|
+
if (!skipChecks) {
|
|
46
53
|
// If we're running on GitHub Actions, we can skip the authentication and
|
|
47
54
|
// collaborator checks. Ref: https://bit.ly/2vsyRzu
|
|
48
55
|
if (process.env.GITHUB_ACTIONS) {
|
|
@@ -108,13 +115,16 @@ class GitHub extends Release {
|
|
|
108
115
|
|
|
109
116
|
async release() {
|
|
110
117
|
const { assets } = this.options;
|
|
111
|
-
const { isUpdate } = this.getContext();
|
|
118
|
+
const { isWeb, isUpdate } = this.getContext();
|
|
112
119
|
const { isCI } = this.config;
|
|
113
120
|
|
|
114
121
|
const type = isUpdate ? 'update' : 'create';
|
|
115
122
|
const publishMethod = `${type}Release`;
|
|
116
123
|
|
|
117
|
-
if (
|
|
124
|
+
if (isWeb) {
|
|
125
|
+
const task = () => this.createWebRelease();
|
|
126
|
+
return this.step({ task, label: 'Generating link to GitHub Release web interface', prompt: 'release' });
|
|
127
|
+
} else if (isCI) {
|
|
118
128
|
await this.step({ task: () => this[publishMethod](), label: `GitHub ${type} release` });
|
|
119
129
|
return this.step({ enabled: assets, task: () => this.uploadAssets(), label: 'GitHub upload assets' });
|
|
120
130
|
} else {
|
|
@@ -285,6 +295,34 @@ class GitHub extends Release {
|
|
|
285
295
|
return `https://${host}/${repository}/releases/tag/${tagName}`;
|
|
286
296
|
}
|
|
287
297
|
|
|
298
|
+
generateWebUrl() {
|
|
299
|
+
const host = this.options.host || this.getContext('repo.host');
|
|
300
|
+
const isGitHub = host === 'github.com';
|
|
301
|
+
|
|
302
|
+
const options = this.getOctokitReleaseOptions();
|
|
303
|
+
const url = newGithubReleaseUrl({
|
|
304
|
+
user: options.owner,
|
|
305
|
+
repo: options.repo,
|
|
306
|
+
tag: options.tag_name,
|
|
307
|
+
isPrerelease: options.prerelease,
|
|
308
|
+
title: options.name,
|
|
309
|
+
body: options.body
|
|
310
|
+
});
|
|
311
|
+
return isGitHub ? url : url.replace('github.com', host);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
async createWebRelease() {
|
|
315
|
+
const { isCI } = this.config;
|
|
316
|
+
const { tagName } = this.config.getContext();
|
|
317
|
+
const url = this.generateWebUrl();
|
|
318
|
+
if (isCI) {
|
|
319
|
+
this.setContext({ isReleased: true, releaseUrl: url });
|
|
320
|
+
} else {
|
|
321
|
+
await open(url);
|
|
322
|
+
this.setContext({ isReleased: true, releaseUrl: this.getReleaseUrlFallback(tagName) });
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
288
326
|
updateRelease() {
|
|
289
327
|
const { isDryRun } = this.config;
|
|
290
328
|
const release_id = this.getContext('releaseId');
|
package/lib/shell.js
CHANGED
package/lib/spinner.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { oraPromise } from 'ora';
|
|
2
2
|
import { format } from './util.js';
|
|
3
3
|
|
|
4
4
|
const noop = Promise.resolve();
|
|
@@ -6,7 +6,7 @@ const noop = Promise.resolve();
|
|
|
6
6
|
class Spinner {
|
|
7
7
|
constructor({ container = {} } = {}) {
|
|
8
8
|
this.config = container.config;
|
|
9
|
-
this.ora = container.ora ||
|
|
9
|
+
this.ora = container.ora || oraPromise;
|
|
10
10
|
}
|
|
11
11
|
show({ enabled = true, task, label, external = false, context }) {
|
|
12
12
|
if (!enabled) return noop;
|
|
@@ -19,7 +19,7 @@ class Spinner {
|
|
|
19
19
|
|
|
20
20
|
if (!this.isSpinnerDisabled || (external && this.canForce)) {
|
|
21
21
|
const text = format(label, context);
|
|
22
|
-
this.ora
|
|
22
|
+
this.ora(awaitTask, text);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
return awaitTask;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-it",
|
|
3
|
-
"version": "15.0.0-esm.
|
|
3
|
+
"version": "15.0.0-esm.3",
|
|
4
4
|
"description": "Generic CLI tool to automate versioning and package publishing related tasks.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"build",
|
|
@@ -62,24 +62,25 @@
|
|
|
62
62
|
"license": "MIT",
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@iarna/toml": "2.2.5",
|
|
65
|
-
"@octokit/rest": "18.
|
|
66
|
-
"async-retry": "1.3.
|
|
67
|
-
"chalk": "4.1.
|
|
68
|
-
"cosmiconfig": "7.0.
|
|
69
|
-
"debug": "4.3.
|
|
65
|
+
"@octokit/rest": "18.12.0",
|
|
66
|
+
"async-retry": "1.3.3",
|
|
67
|
+
"chalk": "4.1.2",
|
|
68
|
+
"cosmiconfig": "7.0.1",
|
|
69
|
+
"debug": "4.3.3",
|
|
70
70
|
"deprecated-obj": "2.0.0",
|
|
71
|
-
"execa": "
|
|
72
|
-
"find-up": "5.0.0",
|
|
71
|
+
"execa": "6.0.0",
|
|
73
72
|
"form-data": "4.0.0",
|
|
74
|
-
"git-url-parse": "11.
|
|
75
|
-
"globby": "
|
|
76
|
-
"got": "11.8.
|
|
77
|
-
"inquirer": "8.
|
|
78
|
-
"is-ci": "3.0.
|
|
73
|
+
"git-url-parse": "11.6.0",
|
|
74
|
+
"globby": "12.0.2",
|
|
75
|
+
"got": "11.8.3",
|
|
76
|
+
"inquirer": "8.2.0",
|
|
77
|
+
"is-ci": "3.0.1",
|
|
79
78
|
"lodash": "4.17.21",
|
|
80
|
-
"mime-types": "2.1.
|
|
81
|
-
"
|
|
82
|
-
"
|
|
79
|
+
"mime-types": "2.1.34",
|
|
80
|
+
"new-github-release-url": "2.0.0",
|
|
81
|
+
"open": "8.4.0",
|
|
82
|
+
"ora": "6.0.1",
|
|
83
|
+
"os-name": "5.0.1",
|
|
83
84
|
"parse-json": "5.2.0",
|
|
84
85
|
"semver": "7.3.5",
|
|
85
86
|
"shelljs": "0.8.4",
|
|
@@ -87,25 +88,25 @@
|
|
|
87
88
|
"url-join": "4.0.1",
|
|
88
89
|
"uuid": "8.3.2",
|
|
89
90
|
"yaml": "1.10.2",
|
|
90
|
-
"yargs-parser": "
|
|
91
|
+
"yargs-parser": "21.0.0"
|
|
91
92
|
},
|
|
92
93
|
"devDependencies": {
|
|
93
94
|
"@octokit/request-error": "2.1.0",
|
|
94
95
|
"ava": "3.15.0",
|
|
95
|
-
"codecov": "3.8.
|
|
96
|
-
"eslint": "
|
|
96
|
+
"codecov": "3.8.3",
|
|
97
|
+
"eslint": "8.3.0",
|
|
97
98
|
"eslint-config-prettier": "8.3.0",
|
|
98
|
-
"eslint-plugin-ava": "
|
|
99
|
-
"eslint-plugin-import": "2.
|
|
100
|
-
"eslint-plugin-prettier": "
|
|
99
|
+
"eslint-plugin-ava": "13.1.0",
|
|
100
|
+
"eslint-plugin-import": "2.25.3",
|
|
101
|
+
"eslint-plugin-prettier": "4.0.0",
|
|
101
102
|
"markdown-toc": "1.2.0",
|
|
102
|
-
"mock-fs": "5.
|
|
103
|
+
"mock-fs": "5.1.2",
|
|
103
104
|
"mock-stdio": "1.0.3",
|
|
104
|
-
"nock": "13.
|
|
105
|
+
"nock": "13.2.1",
|
|
105
106
|
"nyc": "15.1.0",
|
|
106
|
-
"prettier": "2.
|
|
107
|
-
"sinon": "
|
|
108
|
-
"strip-ansi": "
|
|
107
|
+
"prettier": "2.5.0",
|
|
108
|
+
"sinon": "12.0.1",
|
|
109
|
+
"strip-ansi": "7.0.1"
|
|
109
110
|
},
|
|
110
111
|
"engines": {
|
|
111
112
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
package/test/config.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
2
|
import mock from 'mock-fs';
|
|
3
|
+
import isCI from 'is-ci';
|
|
3
4
|
import Config from '../lib/config.js';
|
|
4
5
|
import { readJSON } from '../lib/util.js';
|
|
5
6
|
|
|
@@ -44,8 +45,7 @@ test('should set CI mode', t => {
|
|
|
44
45
|
t.is(config.isCI, true);
|
|
45
46
|
});
|
|
46
47
|
|
|
47
|
-
test('should detect CI mode',
|
|
48
|
-
const { default: isCI } = await import('is-ci');
|
|
48
|
+
test('should detect CI mode', t => {
|
|
49
49
|
const config = new Config();
|
|
50
50
|
t.is(config.options.ci, isCI);
|
|
51
51
|
t.is(config.isCI, isCI);
|
package/test/github.js
CHANGED
|
@@ -18,15 +18,11 @@ const host = 'github.com';
|
|
|
18
18
|
const git = { changelog: null };
|
|
19
19
|
const requestErrorOptions = { request: { url: '', headers: {} }, response: { headers: {} } };
|
|
20
20
|
|
|
21
|
-
test.serial('should
|
|
21
|
+
test.serial('should check token and perform checks', async t => {
|
|
22
22
|
const tokenRef = 'MY_GITHUB_TOKEN';
|
|
23
23
|
const options = { github: { release: true, tokenRef, pushRepo } };
|
|
24
24
|
const github = factory(GitHub, { options });
|
|
25
|
-
delete process.env[tokenRef];
|
|
26
25
|
|
|
27
|
-
await t.throwsAsync(github.init(), {
|
|
28
|
-
message: /^Environment variable "MY_GITHUB_TOKEN" is required for GitHub releases/
|
|
29
|
-
});
|
|
30
26
|
process.env[tokenRef] = '123'; // eslint-disable-line require-atomic-updates
|
|
31
27
|
|
|
32
28
|
interceptAuthentication();
|
|
@@ -34,6 +30,18 @@ test.serial('should validate token', async t => {
|
|
|
34
30
|
await t.notThrowsAsync(github.init());
|
|
35
31
|
});
|
|
36
32
|
|
|
33
|
+
test.serial('should check token and warn', async t => {
|
|
34
|
+
const tokenRef = 'MY_GITHUB_TOKEN';
|
|
35
|
+
const options = { github: { release: true, tokenRef, pushRepo } };
|
|
36
|
+
const github = factory(GitHub, { options });
|
|
37
|
+
delete process.env[tokenRef];
|
|
38
|
+
|
|
39
|
+
await t.notThrowsAsync(github.init());
|
|
40
|
+
|
|
41
|
+
t.is(github.log.warn.args[0][0], 'Environment variable "MY_GITHUB_TOKEN" is required for automated GitHub Releases.');
|
|
42
|
+
t.is(github.log.warn.args[1][0], 'Falling back to web-based GitHub Release.');
|
|
43
|
+
});
|
|
44
|
+
|
|
37
45
|
test('should release and upload assets', async t => {
|
|
38
46
|
const options = {
|
|
39
47
|
git,
|
|
@@ -48,6 +56,7 @@ test('should release and upload assets', async t => {
|
|
|
48
56
|
};
|
|
49
57
|
const github = factory(GitHub, { options });
|
|
50
58
|
const exec = sinon.stub(github.shell, 'exec').callThrough();
|
|
59
|
+
exec.withArgs('git log --pretty=format:"* %s (%h)" ${from}...${to}').resolves('');
|
|
51
60
|
exec.withArgs('git describe --tags --match=* --abbrev=0').resolves('2.0.1');
|
|
52
61
|
|
|
53
62
|
interceptAuthentication();
|
|
@@ -77,6 +86,7 @@ test('should create a pre-release and draft release notes', async t => {
|
|
|
77
86
|
};
|
|
78
87
|
const github = factory(GitHub, { options });
|
|
79
88
|
const exec = sinon.stub(github.shell, 'exec').callThrough();
|
|
89
|
+
exec.withArgs('git log --pretty=format:"* %s (%h)" ${from}...${to}').resolves('');
|
|
80
90
|
exec.withArgs('git describe --tags --match=* --abbrev=0').resolves('2.0.1');
|
|
81
91
|
|
|
82
92
|
interceptAuthentication();
|
|
@@ -108,9 +118,10 @@ test('should update release and upload assets', async t => {
|
|
|
108
118
|
};
|
|
109
119
|
const github = factory(GitHub, { options });
|
|
110
120
|
const exec = sinon.stub(github.shell, 'exec').callThrough();
|
|
121
|
+
exec.withArgs('git log --pretty=format:"* %s (%h)" ${from}...${to}').resolves('');
|
|
111
122
|
exec.withArgs('git describe --tags --match=* --abbrev=0').resolves('2.0.1');
|
|
112
|
-
exec.withArgs('git rev-list 2.0.1 --tags --max-count=1').resolves('
|
|
113
|
-
exec.withArgs('git describe --tags --
|
|
123
|
+
exec.withArgs('git rev-list 2.0.1 --tags --max-count=1').resolves('a123456');
|
|
124
|
+
exec.withArgs('git describe --tags --abbrev=0 "a123456^"').resolves('2.0.1');
|
|
114
125
|
|
|
115
126
|
interceptAuthentication();
|
|
116
127
|
interceptCollaborator();
|
|
@@ -141,9 +152,10 @@ test('should create new release for unreleased tag', async t => {
|
|
|
141
152
|
};
|
|
142
153
|
const github = factory(GitHub, { options });
|
|
143
154
|
const exec = sinon.stub(github.shell, 'exec').callThrough();
|
|
155
|
+
exec.withArgs('git log --pretty=format:"* %s (%h)" ${from}...${to}').resolves('');
|
|
144
156
|
exec.withArgs('git describe --tags --match=* --abbrev=0').resolves('2.0.1');
|
|
145
|
-
exec.withArgs('git rev-list 2.0.1 --tags --max-count=1').resolves('
|
|
146
|
-
exec.withArgs('git describe --tags --
|
|
157
|
+
exec.withArgs('git rev-list 2.0.1 --tags --max-count=1').resolves('b123456');
|
|
158
|
+
exec.withArgs('git describe --tags --abbrev=0 "b123456^"').resolves('2.0.1');
|
|
147
159
|
|
|
148
160
|
interceptAuthentication();
|
|
149
161
|
interceptCollaborator();
|
|
@@ -194,6 +206,7 @@ test('should release to alternative host and proxy', async t => {
|
|
|
194
206
|
};
|
|
195
207
|
const github = factory(GitHub, { options });
|
|
196
208
|
const exec = sinon.stub(github.shell, 'exec').callThrough();
|
|
209
|
+
exec.withArgs('git log --pretty=format:"* %s (%h)" ${from}...${to}').resolves('');
|
|
197
210
|
exec.withArgs('git describe --tags --match=* --abbrev=0').resolves('1.0.0');
|
|
198
211
|
|
|
199
212
|
await runTasks(github);
|
|
@@ -210,6 +223,7 @@ test('should release to git.pushRepo', async t => {
|
|
|
210
223
|
const options = { git: { pushRepo: 'upstream', changelog: null }, github: { tokenRef, skipChecks: true } };
|
|
211
224
|
const github = factory(GitHub, { options });
|
|
212
225
|
const exec = sinon.stub(github.shell, 'exec').callThrough();
|
|
226
|
+
exec.withArgs('git log --pretty=format:"* %s (%h)" ${from}...${to}').resolves('');
|
|
213
227
|
exec.withArgs('git describe --tags --match=* --abbrev=0').resolves('1.0.0');
|
|
214
228
|
exec.withArgs('git remote get-url upstream').resolves('https://my-custom-host.org/user/repo');
|
|
215
229
|
|
|
@@ -308,6 +322,7 @@ test('should not call octokit client in dry run', async t => {
|
|
|
308
322
|
const github = factory(GitHub, { options });
|
|
309
323
|
const spy = sinon.spy(github, 'client', ['get']);
|
|
310
324
|
const exec = sinon.stub(github.shell, 'exec').callThrough();
|
|
325
|
+
exec.withArgs('git log --pretty=format:"* %s (%h)" ${from}...${to}').resolves('');
|
|
311
326
|
exec.withArgs('git describe --tags --match=* --abbrev=0').resolves('v1.0.0');
|
|
312
327
|
|
|
313
328
|
await runTasks(github);
|
|
@@ -327,3 +342,56 @@ test('should skip checks', async t => {
|
|
|
327
342
|
const github = factory(GitHub, { options });
|
|
328
343
|
await t.notThrowsAsync(github.init());
|
|
329
344
|
});
|
|
345
|
+
|
|
346
|
+
test('should generate GitHub web release url', async t => {
|
|
347
|
+
const options = {
|
|
348
|
+
github: {
|
|
349
|
+
pushRepo,
|
|
350
|
+
release: true,
|
|
351
|
+
web: true,
|
|
352
|
+
releaseName: 'Release ${tagName}',
|
|
353
|
+
releaseNotes: 'echo Custom notes'
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
const github = factory(GitHub, { options });
|
|
357
|
+
const exec = sinon.stub(github.shell, 'exec').callThrough();
|
|
358
|
+
exec.withArgs('git log --pretty=format:"* %s (%h)" ${from}...${to}').resolves('');
|
|
359
|
+
exec.withArgs('git describe --tags --match=* --abbrev=0').resolves('2.0.1');
|
|
360
|
+
|
|
361
|
+
await runTasks(github);
|
|
362
|
+
|
|
363
|
+
const { isReleased, releaseUrl } = github.getContext();
|
|
364
|
+
t.true(isReleased);
|
|
365
|
+
t.is(
|
|
366
|
+
releaseUrl,
|
|
367
|
+
'https://github.com/user/repo/releases/new?tag=2.0.2&title=Release+2.0.2&body=Custom+notes&prerelease=false'
|
|
368
|
+
);
|
|
369
|
+
exec.restore();
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
test('should generate GitHub web release url for enterprise host', async t => {
|
|
373
|
+
const options = {
|
|
374
|
+
github: {
|
|
375
|
+
pushRepo: 'git://my-custom-host.org:user/repo',
|
|
376
|
+
release: true,
|
|
377
|
+
web: true,
|
|
378
|
+
host: 'my-custom-host.org',
|
|
379
|
+
releaseName: 'The Launch',
|
|
380
|
+
releaseNotes: 'echo It happened'
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
const github = factory(GitHub, { options });
|
|
384
|
+
const exec = sinon.stub(github.shell, 'exec').callThrough();
|
|
385
|
+
exec.withArgs('git log --pretty=format:"* %s (%h)" ${from}...${to}').resolves('');
|
|
386
|
+
exec.withArgs('git describe --tags --match=* --abbrev=0').resolves('2.0.1');
|
|
387
|
+
|
|
388
|
+
await runTasks(github);
|
|
389
|
+
|
|
390
|
+
const { isReleased, releaseUrl } = github.getContext();
|
|
391
|
+
t.true(isReleased);
|
|
392
|
+
t.is(
|
|
393
|
+
releaseUrl,
|
|
394
|
+
'https://my-custom-host.org/user/repo/releases/new?tag=2.0.2&title=The+Launch&body=It+happened&prerelease=false'
|
|
395
|
+
);
|
|
396
|
+
exec.restore();
|
|
397
|
+
});
|
package/test/plugins.js
CHANGED
package/test/spinner.js
CHANGED
|
@@ -4,9 +4,7 @@ import Spinner from '../lib/spinner.js';
|
|
|
4
4
|
import Config from '../lib/config.js';
|
|
5
5
|
|
|
6
6
|
test.beforeEach(t => {
|
|
7
|
-
t.context.ora =
|
|
8
|
-
promise: sinon.spy()
|
|
9
|
-
};
|
|
7
|
+
t.context.ora = sinon.spy();
|
|
10
8
|
});
|
|
11
9
|
|
|
12
10
|
const getConfig = options => {
|
|
@@ -24,7 +22,7 @@ test('should not show spinner and not execute task if disabled', async t => {
|
|
|
24
22
|
const spinner = new Spinner({ container: { ora } });
|
|
25
23
|
await spinner.show({ enabled: false, task });
|
|
26
24
|
t.is(task.callCount, 0);
|
|
27
|
-
t.is(ora.
|
|
25
|
+
t.is(ora.callCount, 0);
|
|
28
26
|
});
|
|
29
27
|
|
|
30
28
|
test('should show spinner and run task by default', async t => {
|
|
@@ -35,9 +33,9 @@ test('should show spinner and run task by default', async t => {
|
|
|
35
33
|
const spinner = new Spinner({ container: { ora, config } });
|
|
36
34
|
await spinner.show({ task, label });
|
|
37
35
|
t.is(task.callCount, 1);
|
|
38
|
-
t.is(ora.
|
|
39
|
-
t.is(ora.
|
|
40
|
-
t.is(ora.
|
|
36
|
+
t.is(ora.callCount, 1);
|
|
37
|
+
t.is(ora.firstCall.args[0], task.firstCall.returnValue);
|
|
38
|
+
t.is(ora.firstCall.args[1], label);
|
|
41
39
|
});
|
|
42
40
|
|
|
43
41
|
test('should run task, but not show spinner if interactive', async t => {
|
|
@@ -47,7 +45,7 @@ test('should run task, but not show spinner if interactive', async t => {
|
|
|
47
45
|
const spinner = new Spinner({ container: { ora, config } });
|
|
48
46
|
await spinner.show({ task });
|
|
49
47
|
t.is(task.callCount, 1);
|
|
50
|
-
t.is(ora.
|
|
48
|
+
t.is(ora.callCount, 0);
|
|
51
49
|
});
|
|
52
50
|
|
|
53
51
|
test('should run task and show spinner if interactive, but external', async t => {
|
|
@@ -57,5 +55,5 @@ test('should run task and show spinner if interactive, but external', async t =>
|
|
|
57
55
|
const spinner = new Spinner({ container: { ora, config } });
|
|
58
56
|
await spinner.show({ task, external: true });
|
|
59
57
|
t.is(task.callCount, 1);
|
|
60
|
-
t.is(ora.
|
|
58
|
+
t.is(ora.callCount, 1);
|
|
61
59
|
});
|
package/test/tasks.js
CHANGED
|
@@ -397,6 +397,47 @@ test.serial('should propagate errors', async t => {
|
|
|
397
397
|
t.is(log.error.callCount, 1);
|
|
398
398
|
});
|
|
399
399
|
|
|
400
|
+
test.serial('should use custom changelog command with context', async t => {
|
|
401
|
+
const { bare } = t.context;
|
|
402
|
+
const project = path.basename(bare);
|
|
403
|
+
const owner = path.basename(path.dirname(bare));
|
|
404
|
+
sh.exec('git tag v1.0.0');
|
|
405
|
+
gitAdd('line', 'file', 'More file');
|
|
406
|
+
|
|
407
|
+
interceptGitHubAuthentication();
|
|
408
|
+
interceptGitHubCollaborator({ owner, project });
|
|
409
|
+
interceptGitHubCreate({
|
|
410
|
+
owner,
|
|
411
|
+
project,
|
|
412
|
+
body: {
|
|
413
|
+
tag_name: 'v1.1.0',
|
|
414
|
+
name: 'Release 1.1.0',
|
|
415
|
+
body: 'custom-changelog-generator --from=v1.0.0 --to=v1.1.0',
|
|
416
|
+
draft: false,
|
|
417
|
+
prerelease: false
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
const container = getContainer({
|
|
422
|
+
increment: 'minor',
|
|
423
|
+
github: {
|
|
424
|
+
release: true,
|
|
425
|
+
releaseNotes: 'echo custom-changelog-generator --from=${latestTag} --to=${tagName}',
|
|
426
|
+
pushRepo: `https://github.com/${owner}/${project}`
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
const exec = sinon.spy(container.shell, 'execStringCommand');
|
|
431
|
+
|
|
432
|
+
await runTasks({}, container);
|
|
433
|
+
|
|
434
|
+
const command = exec.args.find(([command]) => command.includes('custom-changelog-generator'));
|
|
435
|
+
|
|
436
|
+
t.is(command[0], 'echo custom-changelog-generator --from=v1.0.0 --to=v1.1.0');
|
|
437
|
+
|
|
438
|
+
exec.restore();
|
|
439
|
+
});
|
|
440
|
+
|
|
400
441
|
{
|
|
401
442
|
test.serial('should run all hooks', async t => {
|
|
402
443
|
gitAdd(`{"name":"hooked","version":"1.0.0","type":"module"}`, 'package.json', 'Add package.json');
|
package/test/util/index.js
CHANGED
|
@@ -56,7 +56,7 @@ export let runTasks = async plugin => {
|
|
|
56
56
|
|
|
57
57
|
const name = (await plugin.getName()) || '__test__';
|
|
58
58
|
const latestVersion = (await plugin.getLatestVersion()) || '1.0.0';
|
|
59
|
-
const changelog = (await plugin.getChangelog(
|
|
59
|
+
const changelog = (await plugin.getChangelog()) || null;
|
|
60
60
|
const increment = getIncrement(plugin, { latestVersion });
|
|
61
61
|
|
|
62
62
|
plugin.config.setContext({ name, latestVersion, latestTag: latestVersion, changelog });
|
package/test/version.js
CHANGED
|
@@ -149,20 +149,20 @@ test('should run tasks without errors', async t => {
|
|
|
149
149
|
|
|
150
150
|
t.is(getIncrement.callCount, 1);
|
|
151
151
|
t.deepEqual(getIncrement.firstCall.args[0], {
|
|
152
|
-
latestVersion: '
|
|
152
|
+
latestVersion: '1.0.0',
|
|
153
153
|
increment: 'minor',
|
|
154
154
|
isPreRelease: false,
|
|
155
155
|
preReleaseId: null
|
|
156
156
|
});
|
|
157
157
|
t.is(getIncrementedVersionCI.callCount, 1);
|
|
158
|
-
t.deepEqual(getIncrementedVersionCI.firstCall.args[0], { latestVersion: '
|
|
159
|
-
t.is(await incrementVersion.firstCall.returnValue, '
|
|
158
|
+
t.deepEqual(getIncrementedVersionCI.firstCall.args[0], { latestVersion: '1.0.0', increment: 'minor' });
|
|
159
|
+
t.is(await incrementVersion.firstCall.returnValue, '1.1.0');
|
|
160
160
|
t.is(incrementVersion.callCount, 1);
|
|
161
|
-
t.deepEqual(incrementVersion.firstCall.args[0], { latestVersion: '
|
|
162
|
-
t.is(incrementVersion.firstCall.returnValue, '
|
|
161
|
+
t.deepEqual(incrementVersion.firstCall.args[0], { latestVersion: '1.0.0', increment: 'minor' });
|
|
162
|
+
t.is(incrementVersion.firstCall.returnValue, '1.1.0');
|
|
163
163
|
const { latestVersion, version, isPreRelease, preReleaseId } = v.config.getContext();
|
|
164
|
-
t.is(latestVersion, '
|
|
165
|
-
t.is(version, '
|
|
164
|
+
t.is(latestVersion, '1.0.0');
|
|
165
|
+
t.is(version, '1.1.0');
|
|
166
166
|
t.is(isPreRelease, false);
|
|
167
167
|
t.is(preReleaseId, null);
|
|
168
168
|
});
|