release-it 15.0.0-esm.0 → 15.0.0-esm.4

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/test/plugins.js CHANGED
@@ -5,13 +5,15 @@ import Log from '../lib/log.js';
5
5
  import Spinner from '../lib/spinner.js';
6
6
  import Config from '../lib/config.js';
7
7
  import { parseGitUrl } from '../lib/util.js';
8
- import runTasks from '../lib/tasks.js';
8
+ import runTasks from '../lib/index.js';
9
9
  import MyPlugin from './stub/plugin.js';
10
10
  import ReplacePlugin from './stub/plugin-replace.js';
11
11
  import ContextPlugin from './stub/plugin-context.js';
12
12
  import { mkTmpDir } from './util/helpers.js';
13
13
  import ShellStub from './stub/shell.js';
14
14
 
15
+ const rootDir = new URL('..', import.meta.url);
16
+
15
17
  const noop = Promise.resolve();
16
18
 
17
19
  const sandbox = sinon.createSandbox();
@@ -48,26 +50,30 @@ test.serial.afterEach(() => {
48
50
  });
49
51
 
50
52
  test.serial('should instantiate plugins and execute all release-cycle methods', async t => {
51
- sh.exec('npm init -f');
53
+ sh.ShellString(JSON.stringify({ name: 'project', version: '1.0.0', type: 'module' })).toEnd('package.json');
54
+ sh.exec(`npm install ${rootDir}`);
52
55
 
53
- sh.mkdir('my-plugin');
54
- sh.pushd('-q', 'my-plugin');
55
- sh.exec('npm link release-it');
56
- sh.ShellString("const { Plugin } = require('release-it'); module.exports = " + MyPlugin.toString()).toEnd('index.js');
56
+ const pluginDir = mkTmpDir();
57
+ sh.pushd('-q', pluginDir);
58
+ sh.ShellString(JSON.stringify({ name: 'my-plugin', version: '1.0.0', type: 'module' })).toEnd('package.json');
59
+ sh.exec(`npm install ${rootDir}`);
60
+ const content = "import { Plugin } from 'release-it'; " + MyPlugin.toString() + '; export default MyPlugin;';
61
+ sh.ShellString(content).toEnd('index.js');
57
62
  sh.popd();
58
63
 
59
64
  sh.mkdir('-p', 'my/plugin');
60
65
  sh.pushd('-q', 'my/plugin');
61
- sh.exec('npm link release-it');
62
- sh.ShellString("const { Plugin } = require('release-it'); module.exports = " + MyPlugin.toString()).toEnd('index.js');
66
+ sh.ShellString(content).toEnd('index.js');
63
67
  sh.popd();
64
68
 
69
+ sh.exec(`npm install ${pluginDir}`);
70
+
65
71
  const config = {
66
72
  plugins: {
67
73
  'my-plugin': {
68
74
  name: 'foo'
69
75
  },
70
- './my/plugin': [
76
+ './my/plugin/index.js': [
71
77
  'named-plugin',
72
78
  {
73
79
  name: 'bar'
@@ -108,17 +114,14 @@ test.serial('should instantiate plugins and execute all release-cycle methods',
108
114
  });
109
115
 
110
116
  test.serial('should disable core plugins', async t => {
111
- sh.exec('npm init -f');
112
- sh.mkdir('replace-plugin');
113
- sh.pushd('-q', 'replace-plugin');
114
- sh.exec('npm link release-it');
117
+ sh.ShellString(JSON.stringify({ name: 'project', version: '1.0.0' })).toEnd('package.json');
118
+ sh.exec(`npm install release-it@^14`);
115
119
  const content = "const { Plugin } = require('release-it'); module.exports = " + ReplacePlugin.toString();
116
- sh.ShellString(content).toEnd('index.js');
117
- sh.popd();
120
+ sh.ShellString(content).toEnd('replace-plugin.js');
118
121
 
119
122
  const config = {
120
123
  plugins: {
121
- 'replace-plugin': {}
124
+ './replace-plugin.js': {}
122
125
  }
123
126
  };
124
127
  const container = getContainer(config);
@@ -128,50 +131,22 @@ test.serial('should disable core plugins', async t => {
128
131
  t.deepEqual(result, {
129
132
  changelog: undefined,
130
133
  name: undefined,
131
- latestVersion: undefined,
134
+ latestVersion: '0.0.0',
132
135
  version: undefined
133
136
  });
134
137
  });
135
138
 
136
- test.serial('should support ESM-based plugins', async t => {
137
- sh.exec('npm init -f');
138
- sh.mkdir('my-plugin');
139
- sh.pushd('-q', 'my-plugin');
140
- sh.ShellString('{"name":"my-plugin","version":"1.0.0","type": "module"}').toEnd('package.json');
141
- sh.exec('npm link release-it');
142
- const content = "import { Plugin } from 'release-it'; " + MyPlugin.toString() + '; export default MyPlugin;';
143
- sh.ShellString(content).toEnd('index.js');
144
- sh.popd();
145
-
146
- const config = {
147
- plugins: {
148
- 'my-plugin': {}
149
- }
150
- };
151
- const container = getContainer(config);
152
-
153
- const result = await runTasks({}, container);
139
+ test.serial('should expose context to execute commands', async t => {
140
+ sh.ShellString(JSON.stringify({ name: 'pkg-name', version: '1.0.0', type: 'module' })).toEnd('package.json');
141
+ sh.exec(`npm install ${rootDir}`);
154
142
 
155
- t.deepEqual(result, {
156
- changelog: undefined,
157
- name: 'new-project-name',
158
- latestVersion: '1.2.3',
159
- version: '1.3.0'
160
- });
161
- });
143
+ const content =
144
+ "import { Plugin } from 'release-it'; " + ContextPlugin.toString() + '; export default ContextPlugin;';
145
+ sh.ShellString(content).toEnd('context-plugin.js');
162
146
 
163
- test.serial('should expose context to execute commands', async t => {
164
- sh.ShellString('{"name":"pkg-name","version":"1.0.0"}').toEnd('package.json');
165
147
  const repo = parseGitUrl('https://github.com/user/pkg');
166
148
 
167
- sh.mkdir('context-plugin');
168
- sh.pushd('-q', 'context-plugin');
169
- sh.exec('npm link release-it');
170
- const content = "const { Plugin } = require('release-it'); module.exports = " + ContextPlugin.toString();
171
- sh.ShellString(content).toEnd('index.js');
172
- sh.popd();
173
-
174
- const container = getContainer({ plugins: { 'context-plugin': {} } });
149
+ const container = getContainer({ plugins: { './context-plugin.js': {} } });
175
150
  const exec = sinon.spy(container.shell, 'execFormattedCommand');
176
151
 
177
152
  container.config.setContext({ repo });
package/test/prompt.js CHANGED
@@ -63,7 +63,7 @@ test('should create prompt', async t => {
63
63
  git: { tagName: 'v${version}' },
64
64
  npm: { name: 'my-pkg', tag: 'next' }
65
65
  });
66
- config.setContext({ version: '1.0.0', git: { tagName: '1.0.0' } });
66
+ config.setContext({ version: '1.0.0', tagName: '1.0.0' });
67
67
  const inquirer = t.context.getInquirer(stub);
68
68
  const p = factory(Prompt, { container: { inquirer } });
69
69
  p.register(prompts[namespace], namespace);
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.promise.callCount, 0);
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.promise.callCount, 1);
39
- t.is(ora.promise.firstCall.args[0], task.firstCall.returnValue);
40
- t.is(ora.promise.firstCall.args[1], label);
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.promise.callCount, 0);
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.promise.callCount, 1);
58
+ t.is(ora.callCount, 1);
61
59
  });
@@ -1,16 +1,19 @@
1
1
  import nock from 'nock';
2
2
 
3
- const interceptAuthentication = ({ api = 'https://api.github.com', username = 'john' } = {}) =>
3
+ const interceptAuthentication = ({ api = 'https://api.github.com', username = 'john' } = {}) => {
4
4
  nock(api).get('/user').reply(200, {
5
5
  login: username
6
6
  });
7
+ };
7
8
 
8
9
  const interceptCollaborator = ({
9
10
  api = 'https://api.github.com',
10
11
  owner = 'user',
11
12
  project = 'repo',
12
13
  username = 'john'
13
- } = {}) => nock(api).get(`/repos/${owner}/${project}/collaborators/${username}`).reply(204);
14
+ } = {}) => {
15
+ nock(api).get(`/repos/${owner}/${project}/collaborators/${username}`).reply(204);
16
+ };
14
17
 
15
18
  const interceptListReleases = ({
16
19
  host = 'github.com',
@@ -18,7 +21,7 @@ const interceptListReleases = ({
18
21
  owner = 'user',
19
22
  project = 'repo',
20
23
  tag_name
21
- } = {}) =>
24
+ } = {}) => {
22
25
  nock(api)
23
26
  .get(`/repos/${owner}/${project}/releases?per_page=1&page=1`)
24
27
  .reply(200, [
@@ -34,16 +37,24 @@ const interceptListReleases = ({
34
37
  prerelease: false
35
38
  }
36
39
  ]);
40
+ };
37
41
 
38
42
  const interceptCreate = ({
39
43
  api = 'https://api.github.com',
40
44
  host = 'github.com',
41
45
  owner = 'user',
42
46
  project = 'repo',
43
- body: { tag_name, name = '', body = null, prerelease = false, draft = false }
44
- } = {}) =>
47
+ body: { tag_name, name = '', body = '', prerelease = false, draft = false, generate_release_notes = false }
48
+ } = {}) => {
45
49
  nock(api)
46
- .post(`/repos/${owner}/${project}/releases`, { tag_name, name, body, prerelease, draft })
50
+ .post(`/repos/${owner}/${project}/releases`, {
51
+ tag_name,
52
+ name,
53
+ body,
54
+ prerelease,
55
+ draft,
56
+ generate_release_notes
57
+ })
47
58
  .reply(() => {
48
59
  const id = 1;
49
60
  const responseBody = {
@@ -53,21 +64,23 @@ const interceptCreate = ({
53
64
  body,
54
65
  prerelease,
55
66
  draft,
67
+ generate_release_notes,
56
68
  upload_url: `https://uploads.${host}/repos/${owner}/${project}/releases/${id}/assets{?name,label}`,
57
69
  html_url: `https://${host}/${owner}/${project}/releases/tag/${tag_name}`
58
70
  };
59
71
  return [200, responseBody, { location: `${api}/repos/${owner}/${project}/releases/${id}` }];
60
72
  });
73
+ };
61
74
 
62
75
  const interceptUpdate = ({
63
76
  host = 'github.com',
64
77
  api = 'https://api.github.com',
65
78
  owner = 'user',
66
79
  project = 'repo',
67
- body: { tag_name, name = '', body = null, prerelease = false, draft = false }
68
- } = {}) =>
80
+ body: { tag_name, name = '', body = '', prerelease = false, draft = false, generate_release_notes = false }
81
+ } = {}) => {
69
82
  nock(api)
70
- .patch(`/repos/${owner}/${project}/releases/1`, { tag_name, name, body, draft, prerelease })
83
+ .patch(`/repos/${owner}/${project}/releases/1`, { tag_name, name, body, draft, prerelease, generate_release_notes })
71
84
  .reply(200, {
72
85
  id: 1,
73
86
  tag_name,
@@ -75,9 +88,11 @@ const interceptUpdate = ({
75
88
  body,
76
89
  prerelease,
77
90
  draft,
91
+ generate_release_notes,
78
92
  upload_url: `https://uploads.${host}/repos/${owner}/${project}/releases/1/assets{?name,label}`,
79
93
  html_url: `https://${host}/${owner}/${project}/releases/tag/${tag_name}`
80
94
  });
95
+ };
81
96
 
82
97
  const interceptAsset = ({
83
98
  api = 'https://api.github.com',
@@ -86,7 +101,7 @@ const interceptAsset = ({
86
101
  project = 'repo',
87
102
  tagName,
88
103
  body = {}
89
- } = {}) =>
104
+ } = {}) => {
90
105
  nock(`https://uploads.${host}`)
91
106
  .post(`/repos/${owner}/${project}/releases/1/assets`, body)
92
107
  .query(true)
@@ -103,6 +118,7 @@ const interceptAsset = ({
103
118
  browser_download_url: `https://${host}/${owner}/${project}/releases/download/${tagName}/${name}`
104
119
  };
105
120
  });
121
+ };
106
122
 
107
123
  export {
108
124
  interceptAuthentication,
@@ -7,7 +7,7 @@ import Log from '../lib/log.js';
7
7
  import Spinner from '../lib/spinner.js';
8
8
  import Prompt from '../lib/prompt.js';
9
9
  import Config from '../lib/config.js';
10
- import runTasks from '../lib/tasks.js';
10
+ import runTasks from '../lib/index.js';
11
11
  import { mkTmpDir, gitAdd } from './util/helpers.js';
12
12
  import ShellStub from './stub/shell.js';
13
13
  import { interceptPublish as interceptGitLabPublish } from './stub/gitlab.js';
package/test/tasks.js CHANGED
@@ -6,7 +6,7 @@ import sinon from 'sinon';
6
6
  import Log from '../lib/log.js';
7
7
  import Spinner from '../lib/spinner.js';
8
8
  import Config from '../lib/config.js';
9
- import runTasks from '../lib/tasks.js';
9
+ import runTasks from '../lib/index.js';
10
10
  import { mkTmpDir, gitAdd, getArgs } from './util/helpers.js';
11
11
  import ShellStub from './stub/shell.js';
12
12
  import {
@@ -22,6 +22,8 @@ import {
22
22
  interceptAsset as interceptGitHubAsset
23
23
  } from './stub/github.js';
24
24
 
25
+ const rootDir = new URL('..', import.meta.url);
26
+
25
27
  const noop = Promise.resolve();
26
28
 
27
29
  const sandbox = sinon.createSandbox();
@@ -395,16 +397,53 @@ test.serial('should propagate errors', async t => {
395
397
  t.is(log.error.callCount, 1);
396
398
  });
397
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
+
398
441
  {
399
442
  test.serial('should run all hooks', async t => {
400
- gitAdd(`{"name":"hooked","version":"1.0.0"}`, 'package.json', 'Add package.json');
401
- sh.mkdir('my-plugin');
402
- sh.pushd('-q', 'my-plugin');
403
- sh.exec('npm init -f');
404
- sh.exec('npm link release-it');
405
- const plugin = "const { Plugin } = require('release-it'); module.exports = class MyPlugin extends Plugin {};";
406
- sh.ShellString(plugin).toEnd('index.js');
407
- sh.popd();
443
+ gitAdd(`{"name":"hooked","version":"1.0.0","type":"module"}`, 'package.json', 'Add package.json');
444
+ sh.exec(`npm install ${rootDir}`);
445
+ const plugin = "import { Plugin } from 'release-it'; class MyPlugin extends Plugin {}; export default MyPlugin;";
446
+ sh.ShellString(plugin).toEnd('my-plugin.js');
408
447
 
409
448
  const hooks = {};
410
449
  ['before', 'after'].forEach(prefix => {
@@ -415,7 +454,11 @@ test.serial('should propagate errors', async t => {
415
454
  });
416
455
  });
417
456
  });
418
- const container = getContainer({ plugins: { 'my-plugin': {} }, hooks });
457
+ const container = getContainer({
458
+ plugins: { './my-plugin.js': {} },
459
+ git: { requireCleanWorkingDir: false },
460
+ hooks
461
+ });
419
462
  const exec = sinon.spy(container.shell, 'execFormattedCommand');
420
463
 
421
464
  await runTasks({}, container);
@@ -30,23 +30,14 @@ export let factory = (Definition, { namespace, options = {}, container = {} } =
30
30
  });
31
31
  };
32
32
 
33
- const getIncrement = (plugin, { latestVersion }) => {
34
- return (
35
- plugin.getIncrement({
36
- latestVersion,
37
- increment: plugin.options.increment,
38
- isPreRelease: false,
39
- preReleaseId: null
40
- }) ||
41
- plugin.getContext('increment') ||
42
- plugin.config.getContext('increment')
43
- );
44
- };
33
+ const getIncrement = plugin =>
34
+ plugin.getIncrement(plugin.options) || plugin.getContext('increment') || plugin.config.getContext('increment');
45
35
 
46
- const getVersion = async (plugin, { latestVersion, increment }) => {
36
+ const getVersion = async (plugin, options) => {
37
+ const { latestVersion, increment } = options;
47
38
  return (
48
- (await plugin.getIncrementedVersionCI({ latestVersion, increment })) ||
49
- (await plugin.getIncrementedVersion({ latestVersion, increment })) ||
39
+ (await plugin.getIncrementedVersionCI(options)) ||
40
+ (await plugin.getIncrementedVersion(options)) ||
50
41
  (increment !== false ? semver.inc(latestVersion, increment || 'patch') : latestVersion)
51
42
  );
52
43
  };
@@ -57,18 +48,22 @@ export let runTasks = async plugin => {
57
48
  const name = (await plugin.getName()) || '__test__';
58
49
  const latestVersion = (await plugin.getLatestVersion()) || '1.0.0';
59
50
  const changelog = (await plugin.getChangelog(latestVersion)) || null;
60
- const increment = getIncrement(plugin, { latestVersion });
51
+ const increment = getIncrement(plugin);
61
52
 
62
53
  plugin.config.setContext({ name, latestVersion, latestTag: latestVersion, changelog });
63
54
 
64
- const version = await getVersion(plugin, { latestVersion, increment });
55
+ const { preRelease } = plugin.config.options;
56
+ const isPreRelease = Boolean(preRelease);
57
+ const preReleaseId = typeof preRelease === 'string' ? preRelease : null;
58
+ const version = await getVersion(plugin, { latestVersion, increment, isPreRelease, preReleaseId });
65
59
 
66
60
  plugin.config.setContext(parseVersion(version));
67
61
 
68
62
  await plugin.beforeBump();
69
63
  await plugin.bump(version);
70
64
 
71
- plugin.config.setContext({ tagName: version });
65
+ const tagName = plugin.config.getContext('tagName') || version;
66
+ plugin.config.setContext({ tagName });
72
67
 
73
68
  await plugin.beforeRelease();
74
69
  await plugin.release();
package/test/version.js CHANGED
@@ -148,21 +148,26 @@ test('should run tasks without errors', async t => {
148
148
  await runTasks(v);
149
149
 
150
150
  t.is(getIncrement.callCount, 1);
151
- t.deepEqual(getIncrement.firstCall.args[0], {
152
- latestVersion: '0.0.0',
151
+ t.deepEqual(getIncrement.firstCall.args[0], { increment: 'minor' });
152
+ t.is(getIncrementedVersionCI.callCount, 1);
153
+ t.deepEqual(getIncrementedVersionCI.firstCall.args[0], {
154
+ latestVersion: '1.0.0',
153
155
  increment: 'minor',
154
156
  isPreRelease: false,
155
157
  preReleaseId: null
156
158
  });
157
- t.is(getIncrementedVersionCI.callCount, 1);
158
- t.deepEqual(getIncrementedVersionCI.firstCall.args[0], { latestVersion: '0.0.0', increment: 'minor' });
159
- t.is(await incrementVersion.firstCall.returnValue, '0.1.0');
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: '0.0.0', increment: 'minor' });
162
- t.is(incrementVersion.firstCall.returnValue, '0.1.0');
161
+ t.deepEqual(incrementVersion.firstCall.args[0], {
162
+ latestVersion: '1.0.0',
163
+ increment: 'minor',
164
+ isPreRelease: false,
165
+ preReleaseId: null
166
+ });
167
+ t.is(incrementVersion.firstCall.returnValue, '1.1.0');
163
168
  const { latestVersion, version, isPreRelease, preReleaseId } = v.config.getContext();
164
- t.is(latestVersion, '0.0.0');
165
- t.is(version, '0.1.0');
169
+ t.is(latestVersion, '1.0.0');
170
+ t.is(version, '1.1.0');
166
171
  t.is(isPreRelease, false);
167
172
  t.is(preReleaseId, null);
168
173
  });
package/lib/tasks.js DELETED
@@ -1,139 +0,0 @@
1
- import _ from 'lodash';
2
- import { getPlugins } from './plugin/factory.js';
3
- import Logger from './log.js';
4
- import Config from './config.js';
5
- import Shell from './shell.js';
6
- import Prompt from './prompt.js';
7
- import Spinner from './spinner.js';
8
- import Metrics from './metrics.js';
9
- import { reduceUntil, parseVersion } from './util.js';
10
- import handleDeprecated from './deprecated.js';
11
-
12
- const runTasks = async (opts, di) => {
13
- let container = {};
14
-
15
- try {
16
- Object.assign(container, di);
17
- container.config = container.config || new Config(opts);
18
-
19
- const { config } = container;
20
- const { isCI, isVerbose, verbosityLevel, isDryRun } = config;
21
-
22
- container.log = container.log || new Logger({ isCI, isVerbose, verbosityLevel, isDryRun });
23
- container.spinner = container.spinner || new Spinner({ container, config });
24
- container.prompt = container.prompt || new Prompt({ container: { config } });
25
- container.metrics = new Metrics({ isEnabled: config.isCollectMetrics });
26
- container.shell = container.shell || new Shell({ container });
27
-
28
- const { log, metrics, shell, spinner } = container;
29
-
30
- const options = handleDeprecated(config.getContext(), log);
31
-
32
- metrics.trackEvent('start', options);
33
-
34
- const { hooks } = options;
35
-
36
- const runHook = async (...name) => {
37
- const scripts = hooks[name.join(':')];
38
- if (!scripts || !scripts.length) return;
39
- const context = config.getContext();
40
- const external = true;
41
- for (const script of _.castArray(scripts)) {
42
- const task = () => shell.exec(script, { external }, context);
43
- await spinner.show({ task, label: script, context, external });
44
- }
45
- };
46
-
47
- const runLifeCycleHook = async (plugin, name, ...args) => {
48
- if (plugin === _.first(plugins)) await runHook('before', name);
49
- await runHook('before', plugin.namespace, name);
50
- const willHookRun = (await plugin[name](...args)) !== false;
51
- if (willHookRun) {
52
- await runHook('after', plugin.namespace, name);
53
- }
54
- if (plugin === _.last(plugins)) await runHook('after', name);
55
- };
56
-
57
- const [internal, external] = await getPlugins(config, container);
58
- let plugins = [...external, ...internal];
59
-
60
- for (const plugin of plugins) {
61
- await runLifeCycleHook(plugin, 'init');
62
- }
63
-
64
- const { increment, isPreRelease, preReleaseId } = options.version;
65
-
66
- const name = await reduceUntil(plugins, plugin => plugin.getName());
67
- const latestVersion = await reduceUntil(plugins, plugin => plugin.getLatestVersion());
68
- const changelog = await reduceUntil(plugins, plugin => plugin.getChangelog(latestVersion));
69
-
70
- const incrementBase = { latestVersion, increment, isPreRelease, preReleaseId };
71
-
72
- let version;
73
- if (config.isUpdate) {
74
- version = latestVersion;
75
- } else {
76
- incrementBase.increment = await reduceUntil(plugins, plugin => plugin.getIncrement(incrementBase));
77
- version = await reduceUntil(plugins, plugin => plugin.getIncrementedVersionCI(incrementBase));
78
- }
79
-
80
- if (config.isReleaseVersion) {
81
- log.log(version);
82
- process.exit(0);
83
- }
84
-
85
- config.setContext({ name, latestVersion, version, changelog });
86
-
87
- const action = config.isUpdate ? 'update' : 'release';
88
- const suffix = version && !config.isUpdate ? `${latestVersion}...${version}` : `currently at ${latestVersion}`;
89
-
90
- log.obtrusive(`🚀 Let's ${action} ${name} (${suffix})`);
91
-
92
- log.preview({ title: 'changelog', text: changelog });
93
-
94
- if (!config.isUpdate) {
95
- version = version || (await reduceUntil(plugins, plugin => plugin.getIncrementedVersion(incrementBase)));
96
- }
97
-
98
- config.setContext(parseVersion(version));
99
-
100
- if (config.isPromptOnlyVersion) {
101
- config.setCI(true);
102
- }
103
-
104
- for (const hook of ['beforeBump', 'bump', 'beforeRelease']) {
105
- for (const plugin of plugins) {
106
- const args = hook === 'bump' ? [version] : [];
107
- await runLifeCycleHook(plugin, hook, ...args);
108
- }
109
- }
110
-
111
- plugins = [...internal, ...external];
112
-
113
- for (const hook of ['release', 'afterRelease']) {
114
- for (const plugin of plugins) {
115
- await runLifeCycleHook(plugin, hook);
116
- }
117
- }
118
-
119
- await metrics.trackEvent('end');
120
-
121
- log.log(`🏁 Done (in ${Math.floor(process.uptime())}s.)`);
122
-
123
- return {
124
- name,
125
- changelog,
126
- latestVersion,
127
- version
128
- };
129
- } catch (err) {
130
- const { log, metrics } = container;
131
- if (metrics) {
132
- await metrics.trackException(err);
133
- }
134
- log ? log.error(err.message || err) : console.error(err); // eslint-disable-line no-console
135
- throw err;
136
- }
137
- };
138
-
139
- export default runTasks;