semantic-release 17.1.1 → 17.2.2
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 +10 -3
- package/docs/extending/plugins-list.md +7 -0
- package/docs/recipes/README.md +1 -0
- package/docs/recipes/github-actions.md +19 -2
- package/docs/recipes/jenkins-ci.md +61 -0
- package/docs/support/FAQ.md +3 -1
- package/docs/support/resources.md +1 -0
- package/docs/usage/configuration.md +4 -2
- package/docs/usage/plugins.md +3 -3
- package/lib/get-git-auth-url.js +70 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -150,9 +150,16 @@ Let people know that your package is published using **semantic-release** by inc
|
|
|
150
150
|
|
|
151
151
|
## Team
|
|
152
152
|
|
|
153
|
-
| [](https://github.com/gr2m) | [](https://github.com/pvdlg) | [](https://github.com/travi) |
|
|
154
|
+
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
|
|
155
|
+
| [Gregor Martynus](https://github.com/gr2m) | [Pierre Vanduynslager](https://github.com/pvdlg) | [Matt Travi](https://github.com/travi) |
|
|
156
|
+
|
|
157
|
+
## Alumni
|
|
158
|
+
|
|
159
|
+
| [](https://github.com/boennemann) | [](https://github.com/relekang) | [](https://github.com/jo) | [](https://github.com/finnp) | [](https://github.com/christophwitzko) |
|
|
160
|
+
| ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
161
|
+
| [Stephan Bönnemann](https://github.com/boennemann) | [Rolf Erik Lekang](https://github.com/relekang) | [Johannes Jörg Schmidt](https://github.com/jo) | [Finn Pauls](https://github.com/finnp) | [Christoph Witzko](https://github.com/christophwitzko) |
|
|
162
|
+
|
|
156
163
|
|
|
157
164
|
<p align="center">
|
|
158
165
|
<img alt="Kill all humans" src="media/bender.png">
|
|
@@ -101,3 +101,10 @@
|
|
|
101
101
|
- `addChannel`: Update a Gitea release's pre-release field.
|
|
102
102
|
- [@google/semantic-release-replace-plugin](https://github.com/google/semantic-release-replace-plugin)
|
|
103
103
|
- `prepare`: Replace version strings in files using regex and glob.
|
|
104
|
+
- [semantic-release-rubygem](https://github.com/Gusto/semantic-release-rubygem)
|
|
105
|
+
- `verifyConditions`: Locate and validate a `.gemspec` file, locate and validate a `lib/**/version.rb` file, verify the presence of the `GEM_HOST_API_KEY` environment variable, and create a credentials file with the API key.
|
|
106
|
+
- `prepare`: Update the version in the `lib/**/version.rb` version file and [build](https://guides.rubygems.org/command-reference/#gem-build) the gem.
|
|
107
|
+
- `publish`: [Push the Ruby gem](https://guides.rubygems.org/command-reference/#gem-push) to the gem server.
|
|
108
|
+
- [semantic-release-npm-deprecate-old-versions](https://github.com/ghusse/semantic-release-npm-deprecate-old-versions)
|
|
109
|
+
- `verifyConditions`: Validates configuration.
|
|
110
|
+
- `publish`: Deprecates old versions, based on the declaration of supported versions in the config.
|
package/docs/recipes/README.md
CHANGED
|
@@ -28,7 +28,9 @@ jobs:
|
|
|
28
28
|
runs-on: ubuntu-18.04
|
|
29
29
|
steps:
|
|
30
30
|
- name: Checkout
|
|
31
|
-
uses: actions/checkout@
|
|
31
|
+
uses: actions/checkout@v2
|
|
32
|
+
with:
|
|
33
|
+
fetch-depth: 0
|
|
32
34
|
- name: Setup Node.js
|
|
33
35
|
uses: actions/setup-node@v1
|
|
34
36
|
with:
|
|
@@ -48,9 +50,23 @@ To keep `package.json` updated in the `master` branch, [`@semantic-release/git`]
|
|
|
48
50
|
|
|
49
51
|
**Note**: Automatically populated `GITHUB_TOKEN` cannot be used if branch protection is enabled for the target branch. It is **not** advised to mitigate this limitation by overriding an automatically populated `GITHUB_TOKEN` variable with a [Personal Access Tokens](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line), as it poses a security risk. Since Secret Variables are available for Workflows triggered by any branch, it becomes a potential vector of attack, where a Workflow triggered from a non-protected branch can expose and use a token with elevated permissions, yielding branch protection insignificant. One can use Personal Access Tokens in trusted environments, where all developers should have the ability to perform administrative actions in the given repository and branch protection is enabled solely for convenience purposes, to remind about required reviews or CI checks.
|
|
50
52
|
|
|
53
|
+
If the risk is acceptible, some extra configuration is needed. The [actions/checkout `persist-credentials`](https://github.com/marketplace/actions/checkout#usage) option needs to be `false`, otherwise the generated `GITHUB_TOKEN` will interfere with the custom one. Example:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
- name: Checkout
|
|
57
|
+
uses: actions/checkout@v2
|
|
58
|
+
with:
|
|
59
|
+
fetch-depth: 0
|
|
60
|
+
persist-credentials: false # <--- this
|
|
61
|
+
```
|
|
62
|
+
|
|
51
63
|
## Trigger semantic-release on demand
|
|
52
64
|
|
|
53
|
-
|
|
65
|
+
### Using GUI:
|
|
66
|
+
You can use [Manual Triggers](https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/) for GitHub Actions.
|
|
67
|
+
|
|
68
|
+
### Using HTTP:
|
|
69
|
+
Use [`repository_dispatch`](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#repository_dispatch) event to have control on when to generate a release by making an HTTP request, e.g.:
|
|
54
70
|
|
|
55
71
|
```yaml
|
|
56
72
|
name: Release
|
|
@@ -67,6 +83,7 @@ To trigger a release, call (with a [Personal Access Tokens](https://help.github.
|
|
|
67
83
|
$ curl -v -H "Accept: application/vnd.github.everest-preview+json" -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/[org-name-or-username]/[repository]/dispatches -d '{ "event_type": "semantic-release" }'
|
|
68
84
|
```
|
|
69
85
|
|
|
86
|
+
### Using 3rd party apps:
|
|
70
87
|
If you'd like to use a GitHub app to manage this instead of creating a personal access token, you could consider using a project like:
|
|
71
88
|
|
|
72
89
|
* [Actions Panel](https://www.actionspanel.app/) - A declaratively configured way for triggering GitHub Actions
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Using semantic-release with [Jenkins CI](https://www.jenkins.io/doc/book/pipeline/)
|
|
2
|
+
|
|
3
|
+
## Environment variables
|
|
4
|
+
|
|
5
|
+
The [Authentication](../usage/ci-configuration.md#authentication) environment variables can be configured in [Jenkins Project Settings](https://www.jenkins.io/doc/pipeline/tour/environment/)..
|
|
6
|
+
|
|
7
|
+
Alternatively, the default `NPM_TOKEN` and `GH_TOKEN` can be easily [setup with semantic-release-cli](../usage/getting-started.md#getting-started).
|
|
8
|
+
|
|
9
|
+
## Node.js project configuration
|
|
10
|
+
|
|
11
|
+
### `Jenkinsfile (Declarative Pipeline)` configuration for a Node.js job
|
|
12
|
+
|
|
13
|
+
**Note**: The publish pipeline must run a [Node >= 10.18 version](../support/FAQ.md#why-does-semantic-release-require-node-version--1018).
|
|
14
|
+
|
|
15
|
+
This example is a minimal configuration for **semantic-release** with a build running Node 10.18. See [Jenkins documentation](https://www.jenkins.io/doc/) for additional configuration options.
|
|
16
|
+
|
|
17
|
+
The`semantic-release` execution command varies depending if you are using a [local](../usage/installation.md#local-installation) or [global](../usage/installation.md#global-installation) **semantic-release** installation.
|
|
18
|
+
|
|
19
|
+
```yaml
|
|
20
|
+
// The release stage in the pipeline will run only if the test stage in the pipeline is successful
|
|
21
|
+
pipeline {
|
|
22
|
+
agent any
|
|
23
|
+
environment {
|
|
24
|
+
GH_TOKEN = credentials('some-id')
|
|
25
|
+
}
|
|
26
|
+
stages {
|
|
27
|
+
stage('Test') {
|
|
28
|
+
steps {
|
|
29
|
+
sh '''
|
|
30
|
+
# Configure your test steps here (checkout, npm install, tests etc)
|
|
31
|
+
npm install
|
|
32
|
+
npm test
|
|
33
|
+
'''
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
stage('Release') {
|
|
37
|
+
tools {
|
|
38
|
+
nodejs "node 10.18"
|
|
39
|
+
}
|
|
40
|
+
steps {
|
|
41
|
+
sh '''
|
|
42
|
+
# Run optional required steps before releasing
|
|
43
|
+
npx semantic-release
|
|
44
|
+
'''
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### `package.json` configuration for a Node job
|
|
52
|
+
|
|
53
|
+
A `package.json` is required only for [local](../usage/installation.md#local-installation) **semantic-release** installation.
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"semantic-release": "^15.0.0"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
package/docs/support/FAQ.md
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## Why is the `package.json`’s version not updated in my repository?
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[`@semantic-release/npm`](https://github.com/semantic-release/npm) takes care of updating the `package.json`’s version before publishing to [npm](https://www.npmjs.com).
|
|
6
6
|
|
|
7
7
|
By default, only the published package will contain the version, which is the only place where it is *really* required, but the updated `package.json` will not be pushed to the Git repository
|
|
8
8
|
|
|
9
9
|
However, the [`@semantic-release/git`](https://github.com/semantic-release/git) plugin can be used to push the updated `package.json` as well as other files to the Git repository.
|
|
10
10
|
|
|
11
|
+
If you wish to only update the `package.json` and push via Git you can set the project to `"private": true,` within your `package.json` to prevent publishing to [npm](https://www.npmjs.com). This can be useful for using **semantic-release** with a non-node project.
|
|
12
|
+
|
|
11
13
|
## How can I use a npm build script that requires the `package.json`’s version ?
|
|
12
14
|
|
|
13
15
|
The `package.json`’s version will be updated by the `semantic-release` command just before publishing to [npm](https://www.npmjs.com), therefore it won't be available for scripts ran before the `semantic-release` command.
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
- ["Introduction to SemVer" - Irina Gebauer](https://blog.greenkeeper.io/introduction-to-semver-d272990c44f2)
|
|
16
16
|
- ["Introduction to Semantic Release" - liv](https://blog.greenkeeper.io/introduction-to-semantic-release-33f73b117c8)
|
|
17
|
+
- ["Series - Semantic Release Automation" - Abdelrahman Wahdan](https://dev.to/abdelrahmanahmed/semantic-release-and-how-to-automate-it-part-1-4pa2)
|
|
17
18
|
|
|
18
19
|
## Tutorials
|
|
19
20
|
|
|
@@ -74,7 +74,7 @@ The branches on which releases should happen. By default **semantic-release** wi
|
|
|
74
74
|
|
|
75
75
|
**Note**: If your repository does not have a release branch, then **semantic-release** will fail with an `ERELEASEBRANCHES` error message. If you are using the default configuration, you can fix this error by pushing a `master` branch.
|
|
76
76
|
|
|
77
|
-
**Note**: Once **semantic-release** is configured, any user with the permission to push commits on one of those branches will be able to publish a release. It is recommended to protect those branches, for example with [GitHub protected branches](https://
|
|
77
|
+
**Note**: Once **semantic-release** is configured, any user with the permission to push commits on one of those branches will be able to publish a release. It is recommended to protect those branches, for example with [GitHub protected branches](https://docs.github.com/github/administering-a-repository/about-protected-branches).
|
|
78
78
|
|
|
79
79
|
See [Workflow configuration](workflow-configuration.md#workflow-configuration) for more details.
|
|
80
80
|
|
|
@@ -116,7 +116,9 @@ Type: `Boolean`<br>
|
|
|
116
116
|
Default: `false` if running in a CI environment, `true` otherwise<br>
|
|
117
117
|
CLI arguments: `-d`, `--dry-run`
|
|
118
118
|
|
|
119
|
-
Dry-run mode
|
|
119
|
+
The objective of the dry-run mode is to get a preview of the pending release. Dry-run mode skips the following steps: prepare, publish, success and fail. In addition to this it prints the next version and release notes to the console.
|
|
120
|
+
|
|
121
|
+
**Note**: The Dry-run mode verifies the repository push permission, even though nothing will be pushed. The verification is done to help user to figure out potential configuration issues.
|
|
120
122
|
|
|
121
123
|
### ci
|
|
122
124
|
|
package/docs/usage/plugins.md
CHANGED
|
@@ -21,12 +21,12 @@ A plugin is a npm module that can implement one or more of the following steps:
|
|
|
21
21
|
|
|
22
22
|
### Default plugins
|
|
23
23
|
|
|
24
|
-
These four plugins are already part of **semantic-release** and
|
|
24
|
+
These four plugins are already part of **semantic-release** and are listed in order of execution. They do not have to be installed separately:
|
|
25
25
|
```
|
|
26
26
|
"@semantic-release/commit-analyzer"
|
|
27
|
-
"@semantic-release/github"
|
|
28
|
-
"@semantic-release/npm"
|
|
29
27
|
"@semantic-release/release-notes-generator"
|
|
28
|
+
"@semantic-release/npm"
|
|
29
|
+
"@semantic-release/github"
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
### Additional plugins
|
package/lib/get-git-auth-url.js
CHANGED
|
@@ -2,6 +2,49 @@ const {parse, format} = require('url'); // eslint-disable-line node/no-deprecate
|
|
|
2
2
|
const {isNil} = require('lodash');
|
|
3
3
|
const hostedGitInfo = require('hosted-git-info');
|
|
4
4
|
const {verifyAuth} = require('./git');
|
|
5
|
+
const debug = require('debug')('semantic-release:get-git-auth-url');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Machinery to format a repository URL with the given credentials
|
|
9
|
+
*
|
|
10
|
+
* @param {String} protocol URL protocol (which should not be present in repositoryUrl)
|
|
11
|
+
* @param {String} repositoryUrl User-given repository URL
|
|
12
|
+
* @param {String} gitCredentials The basic auth part of the URL
|
|
13
|
+
*
|
|
14
|
+
* @return {String} The formatted Git repository URL.
|
|
15
|
+
*/
|
|
16
|
+
function formatAuthUrl(protocol, repositoryUrl, gitCredentials) {
|
|
17
|
+
const [match, auth, host, basePort, path] =
|
|
18
|
+
/^(?!.+:\/\/)(?:(?<auth>.*)@)?(?<host>.*?):(?<port>\d+)?:?\/?(?<path>.*)$/.exec(repositoryUrl) || [];
|
|
19
|
+
const {port, hostname, ...parsed} = parse(
|
|
20
|
+
match ? `ssh://${auth ? `${auth}@` : ''}${host}${basePort ? `:${basePort}` : ''}/${path}` : repositoryUrl
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
return format({
|
|
24
|
+
...parsed,
|
|
25
|
+
auth: gitCredentials,
|
|
26
|
+
host: `${hostname}${protocol === 'ssh:' ? '' : port ? `:${port}` : ''}`,
|
|
27
|
+
protocol: protocol && /http[^s]/.test(protocol) ? 'http' : 'https',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Verify authUrl by calling git.verifyAuth, but don't throw on failure
|
|
33
|
+
*
|
|
34
|
+
* @param {Object} context semantic-release context.
|
|
35
|
+
* @param {String} authUrl Repository URL to verify
|
|
36
|
+
*
|
|
37
|
+
* @return {String} The authUrl as is if the connection was successfull, null otherwise
|
|
38
|
+
*/
|
|
39
|
+
async function ensureValidAuthUrl({cwd, env, branch}, authUrl) {
|
|
40
|
+
try {
|
|
41
|
+
await verifyAuth(authUrl, branch.name, {cwd, env});
|
|
42
|
+
return authUrl;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
debug(error);
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
5
48
|
|
|
6
49
|
/**
|
|
7
50
|
* Determine the the git repository URL to use to push, either:
|
|
@@ -14,7 +57,8 @@ const {verifyAuth} = require('./git');
|
|
|
14
57
|
*
|
|
15
58
|
* @return {String} The formatted Git repository URL.
|
|
16
59
|
*/
|
|
17
|
-
module.exports = async (
|
|
60
|
+
module.exports = async (context) => {
|
|
61
|
+
const {cwd, env, branch} = context;
|
|
18
62
|
const GIT_TOKENS = {
|
|
19
63
|
GIT_CREDENTIALS: undefined,
|
|
20
64
|
GH_TOKEN: undefined,
|
|
@@ -29,6 +73,7 @@ module.exports = async ({cwd, env, branch, options: {repositoryUrl}}) => {
|
|
|
29
73
|
BITBUCKET_TOKEN_BASIC_AUTH: '',
|
|
30
74
|
};
|
|
31
75
|
|
|
76
|
+
let {repositoryUrl} = context.options;
|
|
32
77
|
const info = hostedGitInfo.fromUrl(repositoryUrl, {noGitPlus: true});
|
|
33
78
|
const {protocol, ...parsed} = parse(repositoryUrl);
|
|
34
79
|
|
|
@@ -42,25 +87,34 @@ module.exports = async ({cwd, env, branch, options: {repositoryUrl}}) => {
|
|
|
42
87
|
|
|
43
88
|
// Test if push is allowed without transforming the URL (e.g. is ssh keys are set up)
|
|
44
89
|
try {
|
|
90
|
+
debug('Verifying ssh auth by attempting to push to %s', repositoryUrl);
|
|
45
91
|
await verifyAuth(repositoryUrl, branch.name, {cwd, env});
|
|
46
92
|
} catch (_) {
|
|
47
|
-
|
|
48
|
-
const
|
|
93
|
+
debug('SSH key auth failed, falling back to https.');
|
|
94
|
+
const envVars = Object.keys(GIT_TOKENS).filter((envVar) => !isNil(env[envVar]));
|
|
95
|
+
|
|
96
|
+
// Skip verification if there is no ambiguity on which env var to use for authentication
|
|
97
|
+
if (envVars.length === 1) {
|
|
98
|
+
const gitCredentials = `${GIT_TOKENS[envVars[0]] || ''}${env[envVars[0]]}`;
|
|
99
|
+
return formatAuthUrl(protocol, repositoryUrl, gitCredentials);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (envVars.length > 1) {
|
|
103
|
+
debug(`Found ${envVars.length} credentials in environment, trying all of them`);
|
|
49
104
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
);
|
|
105
|
+
const candidateRepositoryUrls = [];
|
|
106
|
+
for (const envVar of envVars) {
|
|
107
|
+
const gitCredentials = `${GIT_TOKENS[envVar] || ''}${env[envVar]}`;
|
|
108
|
+
const authUrl = formatAuthUrl(protocol, repositoryUrl, gitCredentials);
|
|
109
|
+
candidateRepositoryUrls.push(ensureValidAuthUrl(context, authUrl));
|
|
110
|
+
}
|
|
57
111
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
112
|
+
const validRepositoryUrls = await Promise.all(candidateRepositoryUrls);
|
|
113
|
+
const chosenAuthUrlIndex = validRepositoryUrls.findIndex((url) => url !== null);
|
|
114
|
+
if (chosenAuthUrlIndex > -1) {
|
|
115
|
+
debug(`Using "${envVars[chosenAuthUrlIndex]}" to authenticate`);
|
|
116
|
+
return validRepositoryUrls[chosenAuthUrlIndex];
|
|
117
|
+
}
|
|
64
118
|
}
|
|
65
119
|
}
|
|
66
120
|
|
package/package.json
CHANGED