semantic-release 11.0.1 → 11.2.0
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 +32 -12
- package/cli.js +4 -1
- package/index.js +0 -4
- package/lib/get-commits.js +23 -34
- package/lib/get-config.js +50 -4
- package/lib/git.js +4 -4
- package/lib/plugins/definitions.js +2 -2
- package/lib/plugins/index.js +11 -8
- package/lib/plugins/normalize.js +25 -11
- package/package.json +134 -1
- package/lib/get-version-head.js +0 -52
package/README.md
CHANGED
|
@@ -148,7 +148,9 @@ _[This is what happens under the hood.](https://github.com/semantic-release/cli#
|
|
|
148
148
|
|
|
149
149
|
## Options
|
|
150
150
|
|
|
151
|
-
You can pass options either via command line (in [kebab-case](https://lodash.com/docs#kebabCase)) or in the `release` field of your `package.json` (in [camelCase](https://lodash.com/docs#camelCase)).
|
|
151
|
+
You can pass options either via command line (in [kebab-case](https://lodash.com/docs#kebabCase)) or in the `release` field of your `package.json` (in [camelCase](https://lodash.com/docs#camelCase)). Alternatively the configuration can also be defined in `.releaserc.yml`, `.releaserc.js`, `.releaserc.js` or `release.config.js`.
|
|
152
|
+
|
|
153
|
+
The following two examples are the same, but CLI arguments take precedence.
|
|
152
154
|
|
|
153
155
|
##### CLI
|
|
154
156
|
```bash
|
|
@@ -169,18 +171,17 @@ These options are currently available:
|
|
|
169
171
|
- `branch`: The branch on which releases should happen. Default: `'master'`
|
|
170
172
|
- `repositoryUrl`: The git repository URL. Default: `repository` property in `package.json` or git origin url. Any valid git url format is supported (See [Git protocols](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols)). If the [Github plugin](https://github.com/semantic-release/github) is used the URL must be a valid Github URL that include the `owner`, the `repository` name and the `host`. The Github shorthand URL is not supported.
|
|
171
173
|
- `dry-run`: Dry-run mode, skipping verifyConditions, publishing and release, printing next version and release notes
|
|
174
|
+
- `extends`: Array of module or files path containing a shareable configuration. Options defined via CLI or in the `release` property will take precedence over the one defined in a shareable configuration.
|
|
172
175
|
- `debug`: Output debugging information
|
|
173
176
|
|
|
174
177
|
_A few notes on `npm` config_:
|
|
175
178
|
1. The `npm` token can only be defined in the environment as `NPM_TOKEN`, because that’s where `npm` itself is going to read it from.
|
|
176
|
-
|
|
177
179
|
2. In order to publish to a different `npm` registry you can specify that inside the `package.json`’s [`publishConfig`](https://docs.npmjs.com/files/package.json#publishconfig) field.
|
|
178
|
-
|
|
179
180
|
3. If you want to use another dist-tag for your publishes than `'latest'` you can specify that inside the `package.json`’s [`publishConfig`](https://docs.npmjs.com/files/package.json#publishconfig) field.
|
|
180
181
|
|
|
181
182
|
## Plugins
|
|
182
183
|
|
|
183
|
-
There are numerous steps where you can customize `semantic-release`’s
|
|
184
|
+
There are numerous steps where you can customize `semantic-release`’s behavior using plugins. A plugin is a regular [option](#options), but passed inside the `release` block of `package.json`:
|
|
184
185
|
|
|
185
186
|
```json
|
|
186
187
|
{
|
|
@@ -190,24 +191,27 @@ There are numerous steps where you can customize `semantic-release`’s behaviou
|
|
|
190
191
|
"verifyConditions": {
|
|
191
192
|
"path": "./path/to/a/module",
|
|
192
193
|
"additional": "config"
|
|
193
|
-
}
|
|
194
|
+
},
|
|
195
|
+
"globalPluginOptions": "globalConfig"
|
|
194
196
|
}
|
|
195
197
|
}
|
|
196
198
|
```
|
|
197
199
|
|
|
198
|
-
```
|
|
200
|
+
```bash
|
|
199
201
|
semantic-release --analyze-commits="npm-module-name"
|
|
200
202
|
```
|
|
201
203
|
|
|
204
|
+
**Note**: The plugin CLI arguments can be only used to override the plugins to use. Plugins options cannot be defined via CLI arguments and must be defined in the main configuration file or in a shareable config.
|
|
205
|
+
|
|
202
206
|
A plugin itself is an async function that always receives three arguments.
|
|
203
207
|
|
|
204
208
|
```js
|
|
205
209
|
module.exports = function (pluginConfig, config, callback) {}
|
|
206
210
|
```
|
|
207
211
|
|
|
208
|
-
- `pluginConfig`: If the user of your plugin specifies additional plugin config in the `package.json` (see the `verifyConditions` example above) then it’s this object.
|
|
212
|
+
- `pluginConfig`: If the user of your plugin specifies additional plugin config in the `package.json` (see the `verifyConditions` example above) then it’s this object. Options defined directly under `release` will be passed to each plugins. Options defined within a plugin will passed only to that instance of the plugin.
|
|
209
213
|
- `config`: A config object containing a lot of information to act upon.
|
|
210
|
-
- `options`: `semantic-release` options like `
|
|
214
|
+
- `options`: `semantic-release` options like `repositoryUrl`, or `branch`
|
|
211
215
|
- For certain plugins the `config` object contains even more information. See below.
|
|
212
216
|
|
|
213
217
|
### `analyzeCommits`
|
|
@@ -222,9 +226,9 @@ Have a look at the [default implementation](https://github.com/semantic-release/
|
|
|
222
226
|
|
|
223
227
|
This plugins is responsible for verifying that a release should happen in the first place.
|
|
224
228
|
The default implementations are:
|
|
225
|
-
- [travis](https://github.com/semantic-release/condition-travis/): verifies that the publish is happening on Travis, that it’s the right branch, and that all other build jobs succeeded.
|
|
226
|
-
- [github](https://github.com/semantic-release/github/): verifies a Github authentication is set and valid.
|
|
227
|
-
- [npm](https://github.com/semantic-release/npm/): verifies an npm authentication is set and valid.
|
|
229
|
+
- [travis](https://github.com/semantic-release/condition-travis/): verifies that the publish is happening on Travis, that it’s the right branch, and that all other build jobs succeeded.
|
|
230
|
+
- [github](https://github.com/semantic-release/github/): verifies a Github authentication is set and valid.
|
|
231
|
+
- [npm](https://github.com/semantic-release/npm/): verifies an npm authentication is set and valid.
|
|
228
232
|
|
|
229
233
|
Passing an array of plugins will run them in series.
|
|
230
234
|
|
|
@@ -245,7 +249,7 @@ It receives a `commits` array, the `lastRelease` and `nextRelease` inside `confi
|
|
|
245
249
|
|
|
246
250
|
### `publish`
|
|
247
251
|
|
|
248
|
-
This plugins is responsible for publishing the release. The default implementations publish on [npm](https://github.com/semantic-release/npm) and [github](https://github.com/semantic-release/github).
|
|
252
|
+
This plugins is responsible for publishing the release. The default implementations publish on [npm](https://github.com/semantic-release/npm) and [github](https://github.com/semantic-release/github).
|
|
249
253
|
|
|
250
254
|
Passing an array of plugins will run them in series.
|
|
251
255
|
|
|
@@ -287,6 +291,8 @@ Being able to write code for just the most recent node versions greatly simplifi
|
|
|
287
291
|
|
|
288
292
|
For a special purpose tool like `semantic-release`, that's only meant to be used in controlled CI environments, we think it's okay to have such a high version requirement. As `semantic-release` handles package publishing we expect almost every project to have at least one build job running node 8 already – and that's all it takes. Even if that's not that case `semantic-release` can still be executed with the help of [npx](https://www.npmjs.com/package/npx) (`npx -p node@8 npm run semantic-release`).
|
|
289
293
|
|
|
294
|
+
Please see our [Node Support Policy](#node-support-policy) for our long-term promise for supporting Node.
|
|
295
|
+
|
|
290
296
|
## Badge
|
|
291
297
|
|
|
292
298
|
Use this in one of your projects? Include one of these badges in your README.md to let people know that your package is published using `semantic-release`.
|
|
@@ -309,6 +315,20 @@ Use this in one of your projects? Include one of these badges in your README.md
|
|
|
309
315
|
[](https://github.com/semantic-release/semantic-release)
|
|
310
316
|
```
|
|
311
317
|
|
|
318
|
+
## Node Support Policy
|
|
319
|
+
|
|
320
|
+
We only support [Long-Term Support](https://github.com/nodejs/Release) versions of Node starting with [Node 8.9.0 (LTS)](https://nodejs.org/en/blog/release/v8.9.0/).
|
|
321
|
+
|
|
322
|
+
We specifically limit our support to LTS versions of Node, not because this package won't work on other versions, but because we have a limited amount of time, and supporting LTS offers the greatest return on that investment.
|
|
323
|
+
|
|
324
|
+
It's possible this package will work correctly on newer versions of Node. It may even be possible to use this package on older versions of Node, though that's more unlikely as we'll make every effort to take advantage of features available in the oldest LTS version we support.
|
|
325
|
+
|
|
326
|
+
As each Node LTS version reaches its end-of-life we will remove that version from the node engines property of our package's package.json file. Removing a Node version is considered a breaking change and will entail the publishing of a new major version of this package. We will not accept any requests to support an end-of-life version of Node. Any merge requests or issues supporting an end-of-life version of Node will be closed.
|
|
327
|
+
|
|
328
|
+
We will accept code that allows this package to run on newer, non-LTS, versions of Node. Furthermore, we will attempt to ensure our own changes work on the latest version of Node. To help in that commitment, our continuous integration setup runs against all LTS versions of Node in addition the most recent Node release; called current.
|
|
329
|
+
|
|
330
|
+
JavaScript package managers should allow you to install this package with any version of Node, with, at most, a warning if your version of Node does not fall within the range specified by our node engines property. If you encounter issues installing this package, please report the issue to your package manager.
|
|
331
|
+
|
|
312
332
|
## License
|
|
313
333
|
|
|
314
334
|
MIT License
|
package/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const program = require('commander');
|
|
2
|
+
const {pickBy, isUndefined} = require('lodash');
|
|
2
3
|
const logger = require('./lib/logger');
|
|
3
4
|
|
|
4
5
|
function list(values) {
|
|
@@ -11,6 +12,7 @@ module.exports = async () => {
|
|
|
11
12
|
.description('Run automated package publishing')
|
|
12
13
|
.option('-b, --branch <branch>', 'Branch to release from')
|
|
13
14
|
.option('-r, --repositoryUrl <repositoryUrl>', 'Git repository URL')
|
|
15
|
+
.option('-e, --extends <paths>', 'Comma separated list of shareable config paths or packages name', list)
|
|
14
16
|
.option(
|
|
15
17
|
'--verify-conditions <paths>',
|
|
16
18
|
'Comma separated list of paths or packages name for the verifyConditions plugin(s)',
|
|
@@ -42,7 +44,8 @@ module.exports = async () => {
|
|
|
42
44
|
program.outputHelp();
|
|
43
45
|
process.exitCode = 1;
|
|
44
46
|
} else {
|
|
45
|
-
|
|
47
|
+
// Remove option with undefined values, as commander.js sets non defined options as `undefined`
|
|
48
|
+
await require('.')(pickBy(program.opts(), value => !isUndefined(value)));
|
|
46
49
|
}
|
|
47
50
|
} catch (err) {
|
|
48
51
|
// If error is a SemanticReleaseError then it's an expected exception case (no release to be done, running on a PR etc..) and the cli will return with 0
|
package/index.js
CHANGED
|
@@ -15,10 +15,6 @@ module.exports = async opts => {
|
|
|
15
15
|
const config = await getConfig(opts, logger);
|
|
16
16
|
const {plugins, options} = config;
|
|
17
17
|
|
|
18
|
-
if (!options.repositoryUrl) {
|
|
19
|
-
throw new SemanticReleaseError('The repositoryUrl option is required', 'ENOREPOURL');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
18
|
logger.log('Run automated release from branch %s', options.branch);
|
|
23
19
|
|
|
24
20
|
if (!options.dryRun) {
|
package/lib/get-commits.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const gitLogParser = require('git-log-parser');
|
|
2
2
|
const getStream = require('get-stream');
|
|
3
3
|
const debug = require('debug')('semantic-release:get-commits');
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const SemanticReleaseError = require('@semantic-release/error');
|
|
5
|
+
const {unshallow, gitCommitTag, gitTagHead, isCommitInHistory} = require('./git');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Commit message.
|
|
@@ -44,22 +44,28 @@ const getVersionHead = require('./get-version-head');
|
|
|
44
44
|
* @return {Promise<Result>} The list of commits on the branch `branch` since the last release and the updated lastRelease with the gitHead used to retrieve the commits.
|
|
45
45
|
*
|
|
46
46
|
* @throws {SemanticReleaseError} with code `ENOTINHISTORY` if `lastRelease.gitHead` or the commit sha derived from `config.lastRelease.version` is not in the direct history of `branch`.
|
|
47
|
-
* @throws {SemanticReleaseError} with code `ENOGITHEAD` if `lastRelease.gitHead` is undefined and no commit sha can be found for the `config.lastRelease.version`.
|
|
48
47
|
*/
|
|
49
48
|
module.exports = async ({version, gitHead} = {}, branch, logger) => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
if (gitHead) {
|
|
50
|
+
// If gitHead doesn't exists in release branch
|
|
51
|
+
if (!await isCommitInHistory(gitHead)) {
|
|
52
|
+
// Unshallow the repository
|
|
53
|
+
await unshallow();
|
|
54
|
+
}
|
|
55
|
+
// If gitHead still doesn't exists in release branch
|
|
56
|
+
if (!await isCommitInHistory(gitHead)) {
|
|
57
|
+
// Try to find the commit corresponding to the version, using got tags
|
|
58
|
+
const tagHead = (await gitTagHead(`v${version}`)) || (await gitTagHead(version));
|
|
59
|
+
|
|
60
|
+
// If tagHead doesn't exists in release branch
|
|
61
|
+
if (!tagHead || !await isCommitInHistory(tagHead)) {
|
|
62
|
+
// Then the commit corresponding to the version cannot be found in the bracnh hsitory
|
|
63
|
+
logger.error(notInHistoryMessage(gitHead, branch, version));
|
|
64
|
+
throw new SemanticReleaseError('Commit not in history', 'ENOTINHISTORY');
|
|
59
65
|
}
|
|
60
|
-
|
|
66
|
+
gitHead = tagHead;
|
|
61
67
|
}
|
|
62
|
-
|
|
68
|
+
debug('Use gitHead: %s', gitHead);
|
|
63
69
|
} else {
|
|
64
70
|
logger.log('No previous release found, retrieving all commits');
|
|
65
71
|
// If there is no gitHead nor a version, there is no previous release. Unshallow the repo in order to retrieve all commits
|
|
@@ -76,32 +82,15 @@ module.exports = async ({version, gitHead} = {}, branch, logger) => {
|
|
|
76
82
|
);
|
|
77
83
|
logger.log('Found %s commits since last release', commits.length);
|
|
78
84
|
debug('Parsed commits: %o', commits);
|
|
79
|
-
return {commits, lastRelease: {version, gitHead, gitTag}};
|
|
85
|
+
return {commits, lastRelease: {version, gitHead, gitTag: await gitCommitTag(gitHead)}};
|
|
80
86
|
};
|
|
81
87
|
|
|
82
|
-
function noGitHeadMessage(branch, version) {
|
|
83
|
-
return `The commit the last release of this package was derived from cannot be determined from the release metadata nor from the repository tags.
|
|
84
|
-
This means semantic-release can not extract the commits between now and then.
|
|
85
|
-
This is usually caused by releasing from outside the repository directory or with innaccessible git metadata.
|
|
86
|
-
|
|
87
|
-
You can recover from this error by creating a tag for the version "${
|
|
88
|
-
version
|
|
89
|
-
}" on the commit corresponding to this release:
|
|
90
|
-
$ git tag -f v${version} <commit sha1 corresponding to last release>
|
|
91
|
-
$ git push -f --tags origin ${branch}
|
|
92
|
-
`;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
88
|
function notInHistoryMessage(gitHead, branch, version) {
|
|
96
|
-
return `The commit the last release of this package was derived from is not in the direct history of the "${
|
|
97
|
-
branch
|
|
98
|
-
}" branch.
|
|
89
|
+
return `The commit the last release of this package was derived from is not in the direct history of the "${branch}" branch.
|
|
99
90
|
This means semantic-release can not extract the commits between now and then.
|
|
100
91
|
This is usually caused by force pushing, releasing from an unrelated branch, or using an already existing package name.
|
|
101
92
|
|
|
102
|
-
You can recover from this error by restoring the commit "${gitHead}" or by creating a tag for the version "${
|
|
103
|
-
version
|
|
104
|
-
}" on the commit corresponding to this release:
|
|
93
|
+
You can recover from this error by restoring the commit "${gitHead}" or by creating a tag for the version "${version}" on the commit corresponding to this release:
|
|
105
94
|
$ git tag -f v${version || '<version>'} <commit sha1 corresponding to last release>
|
|
106
95
|
$ git push -f --tags origin ${branch}
|
|
107
96
|
`;
|
package/lib/get-config.js
CHANGED
|
@@ -1,14 +1,56 @@
|
|
|
1
1
|
const readPkgUp = require('read-pkg-up');
|
|
2
|
-
const {
|
|
2
|
+
const {castArray, pickBy, isUndefined, isNull, isString, isPlainObject} = require('lodash');
|
|
3
3
|
const cosmiconfig = require('cosmiconfig');
|
|
4
|
+
const resolveFrom = require('resolve-from');
|
|
5
|
+
const SemanticReleaseError = require('@semantic-release/error');
|
|
4
6
|
const debug = require('debug')('semantic-release:config');
|
|
5
7
|
const {repoUrl} = require('./git');
|
|
8
|
+
const PLUGINS_DEFINITION = require('./plugins/definitions');
|
|
6
9
|
const plugins = require('./plugins');
|
|
7
10
|
|
|
8
11
|
module.exports = async (opts, logger) => {
|
|
9
12
|
const {config} = (await cosmiconfig('release', {rcExtensions: true}).load(process.cwd())) || {};
|
|
10
|
-
|
|
13
|
+
// Merge config file options and CLI/API options
|
|
14
|
+
let options = {...config, ...opts};
|
|
15
|
+
const pluginsPath = {};
|
|
16
|
+
let extendPaths;
|
|
17
|
+
({extends: extendPaths, ...options} = options);
|
|
18
|
+
if (extendPaths) {
|
|
19
|
+
// If `extends` is defined, load and merge each shareable config with `options`
|
|
20
|
+
options = {
|
|
21
|
+
...castArray(extendPaths).reduce((result, extendPath) => {
|
|
22
|
+
const extendsOpts = require(resolveFrom.silent(__dirname, extendPath) ||
|
|
23
|
+
resolveFrom(process.cwd(), extendPath));
|
|
11
24
|
|
|
25
|
+
// For each plugin defined in a shareable config, save in `pluginsPath` the extendable config path,
|
|
26
|
+
// so those plugin will be loaded relatively to the config file
|
|
27
|
+
Object.keys(extendsOpts).reduce((pluginsPath, option) => {
|
|
28
|
+
if (PLUGINS_DEFINITION[option]) {
|
|
29
|
+
castArray(extendsOpts[option])
|
|
30
|
+
.filter(plugin => isString(plugin) || (isPlainObject(plugin) && isString(plugin.path)))
|
|
31
|
+
.map(plugin => (isString(plugin) ? plugin : plugin.path))
|
|
32
|
+
.forEach(plugin => {
|
|
33
|
+
pluginsPath[plugin] = extendPath;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return pluginsPath;
|
|
37
|
+
}, pluginsPath);
|
|
38
|
+
|
|
39
|
+
return {...result, ...extendsOpts};
|
|
40
|
+
}, {}),
|
|
41
|
+
...options,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Set default options values if not defined yet
|
|
46
|
+
options = {
|
|
47
|
+
branch: 'master',
|
|
48
|
+
repositoryUrl: (await pkgRepoUrl()) || (await repoUrl()),
|
|
49
|
+
// Remove `null` and `undefined` options so they can be replaced with default ones
|
|
50
|
+
...pickBy(options, option => !isUndefined(option) && !isNull(option)),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
debug('options values: %O', Object.keys(options));
|
|
12
54
|
debug('name: %O', options.name);
|
|
13
55
|
debug('branch: %O', options.branch);
|
|
14
56
|
debug('repositoryUrl: %O', options.repositoryUrl);
|
|
@@ -18,10 +60,14 @@ module.exports = async (opts, logger) => {
|
|
|
18
60
|
debug('verifyRelease: %O', options.verifyRelease);
|
|
19
61
|
debug('publish: %O', options.publish);
|
|
20
62
|
|
|
21
|
-
|
|
63
|
+
if (!options.repositoryUrl) {
|
|
64
|
+
throw new SemanticReleaseError('The repositoryUrl option is required', 'ENOREPOURL');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {options, plugins: await plugins(options, pluginsPath, logger)};
|
|
22
68
|
};
|
|
23
69
|
|
|
24
70
|
async function pkgRepoUrl() {
|
|
25
71
|
const {pkg} = await readPkgUp();
|
|
26
|
-
return pkg && pkg.repository ? pkg.repository.url :
|
|
72
|
+
return pkg && pkg.repository ? pkg.repository.url : undefined;
|
|
27
73
|
}
|
package/lib/git.js
CHANGED
|
@@ -25,7 +25,7 @@ async function gitTagHead(tagName) {
|
|
|
25
25
|
*
|
|
26
26
|
* @param {string} gitHead The commit sha for which to retrieve the associated tag.
|
|
27
27
|
*
|
|
28
|
-
* @return {string} The tag associatedwith the sha in parameter or `
|
|
28
|
+
* @return {string} The tag associatedwith the sha in parameter or `undefined`.
|
|
29
29
|
*/
|
|
30
30
|
async function gitCommitTag(gitHead) {
|
|
31
31
|
try {
|
|
@@ -34,7 +34,7 @@ async function gitCommitTag(gitHead) {
|
|
|
34
34
|
return shell.stdout;
|
|
35
35
|
} catch (err) {
|
|
36
36
|
debug(err);
|
|
37
|
-
return
|
|
37
|
+
return undefined;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -73,10 +73,10 @@ async function gitHead() {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
|
-
* @return {string|
|
|
76
|
+
* @return {string|undefined} The value of the remote git URL.
|
|
77
77
|
*/
|
|
78
78
|
async function repoUrl() {
|
|
79
|
-
return (await execa.stdout('git', ['remote', 'get-url', 'origin'], {reject: false})) ||
|
|
79
|
+
return (await execa.stdout('git', ['remote', 'get-url', 'origin'], {reject: false})) || undefined;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
/**
|
|
@@ -24,9 +24,9 @@ module.exports = {
|
|
|
24
24
|
validator: output =>
|
|
25
25
|
!output ||
|
|
26
26
|
(isObject(output) && !output.version) ||
|
|
27
|
-
(isString(output.version) && Boolean(semver.valid(semver.clean(output.version)))),
|
|
27
|
+
(isString(output.version) && Boolean(semver.valid(semver.clean(output.version))) && Boolean(output.gitHead)),
|
|
28
28
|
message:
|
|
29
|
-
'The "getLastRelease" plugin output if defined, must be an object with
|
|
29
|
+
'The "getLastRelease" plugin output if defined, must be an object with a valid semver version in the "version" property and the corresponding git reference in "gitHead" property.',
|
|
30
30
|
},
|
|
31
31
|
},
|
|
32
32
|
analyzeCommits: {
|
package/lib/plugins/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
const {isArray, isObject} = require('lodash');
|
|
2
|
-
const
|
|
1
|
+
const {isArray, isObject, omit} = require('lodash');
|
|
2
|
+
const SemanticReleaseError = require('@semantic-release/error');
|
|
3
|
+
const PLUGINS_DEFINITION = require('./definitions');
|
|
3
4
|
const pipeline = require('./pipeline');
|
|
4
5
|
const normalize = require('./normalize');
|
|
5
6
|
|
|
6
|
-
module.exports = (options, logger) =>
|
|
7
|
-
Object.keys(
|
|
8
|
-
const {config, output, default: def} =
|
|
7
|
+
module.exports = (options, pluginsPath, logger) =>
|
|
8
|
+
Object.keys(PLUGINS_DEFINITION).reduce((plugins, pluginType) => {
|
|
9
|
+
const {config, output, default: def} = PLUGINS_DEFINITION[pluginType];
|
|
9
10
|
let pluginConfs;
|
|
10
11
|
if (options[pluginType]) {
|
|
11
12
|
// If an object is passed and the path is missing, set the default one for single plugins
|
|
@@ -13,16 +14,18 @@ module.exports = (options, logger) =>
|
|
|
13
14
|
options[pluginType].path = def;
|
|
14
15
|
}
|
|
15
16
|
if (config && !config.validator(options[pluginType])) {
|
|
16
|
-
throw new
|
|
17
|
+
throw new SemanticReleaseError(config.message, 'EPLUGINCONF');
|
|
17
18
|
}
|
|
18
19
|
pluginConfs = options[pluginType];
|
|
19
20
|
} else {
|
|
20
21
|
pluginConfs = def;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
const globalOpts = omit(options, Object.keys(PLUGINS_DEFINITION));
|
|
25
|
+
|
|
23
26
|
plugins[pluginType] = isArray(pluginConfs)
|
|
24
|
-
? pipeline(pluginConfs.map(conf => normalize(pluginType, conf, logger, output)))
|
|
25
|
-
: normalize(pluginType, pluginConfs, logger, output);
|
|
27
|
+
? pipeline(pluginConfs.map(conf => normalize(pluginType, pluginsPath, globalOpts, conf, logger, output)))
|
|
28
|
+
: normalize(pluginType, pluginsPath, globalOpts, pluginConfs, logger, output);
|
|
26
29
|
|
|
27
30
|
return plugins;
|
|
28
31
|
}, {});
|
package/lib/plugins/normalize.js
CHANGED
|
@@ -1,25 +1,39 @@
|
|
|
1
|
+
const {dirname} = require('path');
|
|
1
2
|
const {inspect} = require('util');
|
|
3
|
+
const SemanticReleaseError = require('@semantic-release/error');
|
|
2
4
|
const {isString, isObject, isFunction, noop, cloneDeep} = require('lodash');
|
|
3
|
-
const
|
|
5
|
+
const resolveFrom = require('resolve-from');
|
|
4
6
|
|
|
5
|
-
module.exports = (pluginType,
|
|
6
|
-
if (!
|
|
7
|
+
module.exports = (pluginType, pluginsPath, globalOpts, pluginOpts, logger, validator) => {
|
|
8
|
+
if (!pluginOpts) {
|
|
7
9
|
return noop;
|
|
8
10
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
const {path, ...config} = isString(pluginOpts) || isFunction(pluginOpts) ? {path: pluginOpts} : pluginOpts;
|
|
13
|
+
if (!isFunction(pluginOpts)) {
|
|
14
|
+
if (pluginsPath[path]) {
|
|
15
|
+
logger.log('Load plugin %s from %s in shareable config %s', pluginType, path, pluginsPath[path]);
|
|
16
|
+
} else {
|
|
17
|
+
logger.log('Load plugin %s from %s', pluginType, path);
|
|
18
|
+
}
|
|
12
19
|
}
|
|
13
|
-
|
|
20
|
+
|
|
21
|
+
const basePath = pluginsPath[path]
|
|
22
|
+
? dirname(resolveFrom.silent(__dirname, pluginsPath[path]) || resolveFrom(process.cwd(), pluginsPath[path]))
|
|
23
|
+
: __dirname;
|
|
24
|
+
const plugin = isFunction(path)
|
|
25
|
+
? path
|
|
26
|
+
: require(resolveFrom.silent(basePath, path) || resolveFrom(process.cwd(), path));
|
|
14
27
|
|
|
15
28
|
let func;
|
|
16
29
|
if (isFunction(plugin)) {
|
|
17
|
-
func = plugin.bind(null, cloneDeep(config));
|
|
30
|
+
func = plugin.bind(null, cloneDeep({...globalOpts, ...config}));
|
|
18
31
|
} else if (isObject(plugin) && plugin[pluginType] && isFunction(plugin[pluginType])) {
|
|
19
|
-
func = plugin[pluginType].bind(null, cloneDeep(config));
|
|
32
|
+
func = plugin[pluginType].bind(null, cloneDeep({...globalOpts, ...config}));
|
|
20
33
|
} else {
|
|
21
|
-
throw new
|
|
22
|
-
`The ${pluginType} plugin must be a function, or an object with a function in the property ${pluginType}
|
|
34
|
+
throw new SemanticReleaseError(
|
|
35
|
+
`The ${pluginType} plugin must be a function, or an object with a function in the property ${pluginType}.`,
|
|
36
|
+
'EPLUGINCONF'
|
|
23
37
|
);
|
|
24
38
|
}
|
|
25
39
|
|
package/package.json
CHANGED
|
@@ -1 +1,134 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"name": "semantic-release",
|
|
3
|
+
"description": "Automated semver compliant package publishing",
|
|
4
|
+
"version": "11.2.0",
|
|
5
|
+
"author": "Stephan Bönnemann <stephan@boennemann.me> (http://boennemann.me)",
|
|
6
|
+
"bin": {
|
|
7
|
+
"semantic-release": "bin/semantic-release.js"
|
|
8
|
+
},
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/semantic-release/semantic-release/issues"
|
|
11
|
+
},
|
|
12
|
+
"config": {
|
|
13
|
+
"commitizen": {
|
|
14
|
+
"path": "cz-conventional-changelog"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@semantic-release/commit-analyzer": "^5.0.0",
|
|
19
|
+
"@semantic-release/condition-travis": "^7.0.0",
|
|
20
|
+
"@semantic-release/error": "^2.1.0",
|
|
21
|
+
"@semantic-release/github": "^3.0.0",
|
|
22
|
+
"@semantic-release/npm": "^2.0.0",
|
|
23
|
+
"@semantic-release/release-notes-generator": "^6.0.0",
|
|
24
|
+
"chalk": "^2.3.0",
|
|
25
|
+
"commander": "^2.11.0",
|
|
26
|
+
"cosmiconfig": "^3.1.0",
|
|
27
|
+
"debug": "^3.1.0",
|
|
28
|
+
"execa": "^0.8.0",
|
|
29
|
+
"get-stream": "^3.0.0",
|
|
30
|
+
"git-log-parser": "^1.2.0",
|
|
31
|
+
"lodash": "^4.0.0",
|
|
32
|
+
"marked": "^0.3.6",
|
|
33
|
+
"marked-terminal": "^2.0.0",
|
|
34
|
+
"p-reduce": "^1.0.0",
|
|
35
|
+
"read-pkg-up": "^3.0.0",
|
|
36
|
+
"resolve-from": "^4.0.0",
|
|
37
|
+
"semver": "^5.4.1"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"ava": "^0.24.0",
|
|
41
|
+
"codecov": "^3.0.0",
|
|
42
|
+
"commitizen": "^2.9.6",
|
|
43
|
+
"cz-conventional-changelog": "^2.0.0",
|
|
44
|
+
"delay": "^2.0.0",
|
|
45
|
+
"dockerode": "^2.5.2",
|
|
46
|
+
"eslint-config-prettier": "^2.5.0",
|
|
47
|
+
"eslint-plugin-prettier": "^2.3.0",
|
|
48
|
+
"file-url": "^2.0.2",
|
|
49
|
+
"fs-extra": "^5.0.0",
|
|
50
|
+
"got": "^8.0.0",
|
|
51
|
+
"js-yaml": "^3.10.0",
|
|
52
|
+
"mockserver-client": "^5.1.1",
|
|
53
|
+
"nock": "^9.0.2",
|
|
54
|
+
"nyc": "^11.2.1",
|
|
55
|
+
"p-retry": "^1.0.0",
|
|
56
|
+
"prettier": "~1.9.2",
|
|
57
|
+
"proxyquire": "^1.8.0",
|
|
58
|
+
"sinon": "^4.0.0",
|
|
59
|
+
"tempy": "^0.2.1",
|
|
60
|
+
"xo": "^0.18.2"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=4",
|
|
64
|
+
"npm": ">=2"
|
|
65
|
+
},
|
|
66
|
+
"files": [
|
|
67
|
+
"bin",
|
|
68
|
+
"lib",
|
|
69
|
+
"index.js",
|
|
70
|
+
"cli.js"
|
|
71
|
+
],
|
|
72
|
+
"homepage": "https://github.com/semantic-release/semantic-release#readme",
|
|
73
|
+
"keywords": [
|
|
74
|
+
"author",
|
|
75
|
+
"automation",
|
|
76
|
+
"changelog",
|
|
77
|
+
"module",
|
|
78
|
+
"package",
|
|
79
|
+
"publish",
|
|
80
|
+
"release",
|
|
81
|
+
"semver",
|
|
82
|
+
"version"
|
|
83
|
+
],
|
|
84
|
+
"license": "MIT",
|
|
85
|
+
"main": "index.js",
|
|
86
|
+
"nyc": {
|
|
87
|
+
"include": [
|
|
88
|
+
"lib/**/*.js",
|
|
89
|
+
"index.js",
|
|
90
|
+
"cli.js"
|
|
91
|
+
],
|
|
92
|
+
"reporter": [
|
|
93
|
+
"json",
|
|
94
|
+
"text",
|
|
95
|
+
"html"
|
|
96
|
+
],
|
|
97
|
+
"all": true
|
|
98
|
+
},
|
|
99
|
+
"prettier": {
|
|
100
|
+
"printWidth": 120,
|
|
101
|
+
"singleQuote": true,
|
|
102
|
+
"bracketSpacing": false,
|
|
103
|
+
"trailingComma": "es5"
|
|
104
|
+
},
|
|
105
|
+
"publishConfig": {
|
|
106
|
+
"tag": "next"
|
|
107
|
+
},
|
|
108
|
+
"release": {
|
|
109
|
+
"branch": "caribou"
|
|
110
|
+
},
|
|
111
|
+
"repository": {
|
|
112
|
+
"type": "git",
|
|
113
|
+
"url": "git+https://github.com/semantic-release/semantic-release.git"
|
|
114
|
+
},
|
|
115
|
+
"scripts": {
|
|
116
|
+
"cm": "git-cz",
|
|
117
|
+
"codecov": "codecov -f coverage/coverage-final.json",
|
|
118
|
+
"lint": "xo",
|
|
119
|
+
"pretest": "npm run lint",
|
|
120
|
+
"semantic-release": "./bin/semantic-release.js",
|
|
121
|
+
"test": "nyc ava -v"
|
|
122
|
+
},
|
|
123
|
+
"xo": {
|
|
124
|
+
"extends": [
|
|
125
|
+
"prettier"
|
|
126
|
+
],
|
|
127
|
+
"plugins": [
|
|
128
|
+
"prettier"
|
|
129
|
+
],
|
|
130
|
+
"rules": {
|
|
131
|
+
"prettier/prettier": 2
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
package/lib/get-version-head.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
const debug = require('debug')('semantic-release:get-version-head');
|
|
2
|
-
const SemanticReleaseError = require('@semantic-release/error');
|
|
3
|
-
const {gitTagHead, gitCommitTag, isCommitInHistory, unshallow} = require('./git');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Get the commit sha for a given version, if it's contained in the given branch.
|
|
7
|
-
*
|
|
8
|
-
* @param {string} gitHead The commit sha to look for.
|
|
9
|
-
* @param {string} version The version corresponding to the commit sha to look for. Used to search in git tags.
|
|
10
|
-
*
|
|
11
|
-
* @return {Promise<Object>} A Promise that resolves to an object with the `gitHead` and `gitTag` for the the `version`.
|
|
12
|
-
*
|
|
13
|
-
* @throws {SemanticReleaseError} with code `ENOTINHISTORY` if `gitHead` or the commit sha dereived from `version` is not in the direct history of `branch`.
|
|
14
|
-
* @throws {SemanticReleaseError} with code `ENOGITHEAD` if `gitHead` is undefined and no commit sha can be found for the `version`.
|
|
15
|
-
*/
|
|
16
|
-
module.exports = async (gitHead, version) => {
|
|
17
|
-
// Check if gitHead is defined and exists in release branch
|
|
18
|
-
if (gitHead && (await isCommitInHistory(gitHead))) {
|
|
19
|
-
debug('Use gitHead: %s', gitHead);
|
|
20
|
-
return {gitHead, gitTag: await gitCommitTag(gitHead)};
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
await unshallow();
|
|
24
|
-
|
|
25
|
-
// Check if gitHead is defined and exists in release branch again
|
|
26
|
-
if (gitHead && (await isCommitInHistory(gitHead))) {
|
|
27
|
-
debug('Use gitHead: %s', gitHead);
|
|
28
|
-
return {gitHead, gitTag: await gitCommitTag(gitHead)};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let tagHead;
|
|
32
|
-
if (version) {
|
|
33
|
-
// If a version is defined search a corresponding tag
|
|
34
|
-
tagHead = (await gitTagHead(`v${version}`)) || (await gitTagHead(version));
|
|
35
|
-
|
|
36
|
-
// Check if tagHead is found and exists in release branch again
|
|
37
|
-
if (tagHead && (await isCommitInHistory(tagHead))) {
|
|
38
|
-
debug('Use tagHead: %s', tagHead);
|
|
39
|
-
return {gitHead: tagHead, gitTag: await gitCommitTag(tagHead)};
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Either gitHead is defined or a tagHead has been found but none is in the branch history
|
|
44
|
-
if (gitHead || tagHead) {
|
|
45
|
-
const error = new SemanticReleaseError('Commit not in history', 'ENOTINHISTORY');
|
|
46
|
-
error.gitHead = gitHead || tagHead;
|
|
47
|
-
throw error;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// There is no gitHead in the last release and there is no tags correponsing to the last release version
|
|
51
|
-
throw new SemanticReleaseError('There is no commit associated with last release', 'ENOGITHEAD');
|
|
52
|
-
};
|