Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55194c106e | ||
|
|
e24ef71e33 | ||
|
|
0435e35fee | ||
|
|
1d1b52a7dc | ||
|
|
72522c3570 | ||
|
|
5489489dda | ||
|
|
12337175c6 | ||
|
|
8fa4f9a750 | ||
|
|
f668935993 | ||
|
|
0f3c4148c7 | ||
|
|
2e4b901c4f | ||
|
|
971a5e0d16 | ||
|
|
44b3344b91 | ||
|
|
046a845a9e | ||
|
|
48def0c4cc | ||
|
|
2b6c9ba093 | ||
|
|
07f12b9df2 | ||
|
|
2272ce3059 | ||
|
|
3ecc196d8a | ||
|
|
acf8bc4d21 | ||
|
|
67dfb676bc | ||
|
|
f25c3527df | ||
|
|
6013a5633e | ||
|
|
d2782484c8 | ||
|
|
34e5ddad12 | ||
|
|
a9be97b56b | ||
|
|
85bc213f04 | ||
|
|
8e3a6cbef2 | ||
|
|
a2eaed086f | ||
|
|
b22e591c96 | ||
|
|
fc32afa776 | ||
|
|
8ea81ae6c9 | ||
|
|
e4002c8bd7 | ||
|
|
d738dd0fb7 | ||
|
|
4c7222d648 | ||
|
|
54bf761f7e | ||
|
|
ea5e813192 | ||
|
|
a7f008253c | ||
|
|
ece7275743 | ||
|
|
16a9fb00e9 | ||
|
|
854d643bed | ||
|
|
969e460948 | ||
|
|
ab227451fa | ||
|
|
0f37fc3aa6 | ||
|
|
fa7080e0d4 | ||
|
|
0a86d61a00 | ||
|
|
d53e2066cc | ||
|
|
47450fb3b1 | ||
|
|
fb5db83adc | ||
|
|
8262832cda | ||
|
|
cc74a4c890 | ||
|
|
a3c49428e3 | ||
|
|
d95d80a0aa | ||
|
|
b5aa853b22 | ||
|
|
32a2c91d7c | ||
|
|
d2ec8931bc | ||
|
|
9f57b84aaa | ||
|
|
c5719101cc | ||
|
|
7581aa8584 | ||
|
|
21c151f167 | ||
|
|
da75a9c60a | ||
|
|
e211499735 |
@@ -0,0 +1,21 @@
|
||||
name: Release
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- next
|
||||
- beta
|
||||
- "*.x" # maintenance releases branches
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: bahmutov/npm-install@v1
|
||||
- run: npx semantic-release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_BOT_NPM_TOKEN }}
|
||||
@@ -0,0 +1,48 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
# renovate/** branches are generated by https://github.com/apps/renovate
|
||||
- renovate/**
|
||||
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
test_matrix:
|
||||
strategy:
|
||||
matrix:
|
||||
node-version:
|
||||
- 10.18.0
|
||||
- 12
|
||||
- 14
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: git config --global user.name github-actions
|
||||
- run: git config --global user.email github-actions@github.com
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Ensure dependencies are compatible with the version of node
|
||||
run: echo 'engine-strict=true' >> .npmrc
|
||||
- uses: bahmutov/npm-install@v1
|
||||
- run: npm run test:ci
|
||||
|
||||
# separate job to set as required in branch protection,
|
||||
# as the build names above change each time Node versions change
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test_matrix
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: bahmutov/npm-install@v1
|
||||
- run: npm run lint
|
||||
@@ -125,10 +125,6 @@ $RECYCLE.BIN/
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# Lockfiles
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
# Gitbook
|
||||
_book
|
||||
|
||||
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
version: ~> 1.0
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
import:
|
||||
- .travis/node.yml
|
||||
- .travis/node-versions.yml
|
||||
- .travis/semantic-release.yml
|
||||
- .travis/greenkeeper.yml
|
||||
- .travis/codecov.yml
|
||||
@@ -1,2 +0,0 @@
|
||||
after_success:
|
||||
- npm run codecov
|
||||
@@ -1,3 +0,0 @@
|
||||
branches:
|
||||
only:
|
||||
- /^greenkeeper.*$/
|
||||
@@ -1,3 +0,0 @@
|
||||
node_js:
|
||||
- 12
|
||||
- 10.18
|
||||
@@ -1,11 +0,0 @@
|
||||
language: node_js
|
||||
|
||||
cache:
|
||||
npm: false
|
||||
|
||||
# Retry install on fail to avoid failing a build on network/disk/external errors
|
||||
install:
|
||||
- travis_retry npm install
|
||||
|
||||
script:
|
||||
- npm run test
|
||||
@@ -1,15 +0,0 @@
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- next
|
||||
- beta
|
||||
- /^\d+\.(\d+|x)(\.x)?$/
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: release
|
||||
node_js: lts/*
|
||||
install:
|
||||
- travis_retry npm install
|
||||
script:
|
||||
- npm run semantic-release
|
||||
@@ -1,17 +1,11 @@
|
||||
<h1 align="center" style="border-bottom: none;">📦🚀 semantic-release</h1>
|
||||
<h3 align="center">Fully automated version management and package publishing</h3>
|
||||
<p align="center">
|
||||
<a href="https://spectrum.chat/semantic-release">
|
||||
<img alt="Join the community on Spectrum" src="https://withspectrum.github.io/badge/badge.svg">
|
||||
<a href="https://github.com/semantic-release/semantic-release/discussions">
|
||||
<img alt="Join the community on GitHub Discussions" src="https://img.shields.io/badge/Join%20the%20community-on%20GitHub%20Discussions-blue">
|
||||
</a>
|
||||
<a href="https://travis-ci.org/semantic-release/semantic-release">
|
||||
<img alt="Travis" src="https://img.shields.io/travis/semantic-release/semantic-release/master.svg">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/semantic-release/semantic-release">
|
||||
<img alt="Codecov" src="https://img.shields.io/codecov/c/github/semantic-release/semantic-release/master.svg">
|
||||
</a>
|
||||
<a href="https://greenkeeper.io">
|
||||
<img alt="Greenkeeper" src="https://badges.greenkeeper.io/semantic-release/semantic-release.svg">
|
||||
<a href="https://github.com/semantic-release/semantic-release/actions?query=workflow%3ATest+branch%3Amaster">
|
||||
<img alt="Build states" src="https://github.com/semantic-release/semantic-release/workflows/Test/badge.svg">
|
||||
</a>
|
||||
<a href="#badge">
|
||||
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
|
||||
@@ -54,14 +48,14 @@ This removes the immediate connection between human emotions and version numbers
|
||||
|
||||
**semantic-release** uses the commit messages to determine the type of changes in the codebase. Following formalized conventions for commit messages, **semantic-release** automatically determines the next [semantic version](https://semver.org) number, generates a changelog and publishes the release.
|
||||
|
||||
By default **semantic-release** uses [Angular Commit Message Conventions](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines). The commit message format can be changed with the [`preset` or `config` options](docs/usage/configuration.md#options) of the [@semantic-release/commit-analyzer](https://github.com/semantic-release/commit-analyzer#options) and [@semantic-release/release-notes-generator](https://github.com/semantic-release/release-notes-generator#options) plugins.
|
||||
By default **semantic-release** uses [Angular Commit Message Conventions](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-format). The commit message format can be changed with the [`preset` or `config` options](docs/usage/configuration.md#options) of the [@semantic-release/commit-analyzer](https://github.com/semantic-release/commit-analyzer#options) and [@semantic-release/release-notes-generator](https://github.com/semantic-release/release-notes-generator#options) plugins.
|
||||
|
||||
Tools such as [commitizen](https://github.com/commitizen/cz-cli) or [commitlint](https://github.com/conventional-changelog/commitlint) can be used to help contributors and enforce valid commit messages.
|
||||
|
||||
Here is an example of the release type that will be done based on a commit messages:
|
||||
|
||||
| Commit message | Release type |
|
||||
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|
|
||||
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------- |
|
||||
| `fix(pencil): stop graphite breaking when too much pressure applied` | Patch Release |
|
||||
| `feat(pencil): add 'graphiteWidth' option` | ~~Minor~~ Feature Release |
|
||||
| `perf(pencil): remove graphiteWidth option`<br><br>`BREAKING CHANGE: The graphiteWidth option has been removed.`<br>`The default graphite width of 10mm is always used for performance reasons.` | ~~Major~~ Breaking Release |
|
||||
@@ -75,6 +69,7 @@ Here is an example of the release type that will be done based on a commit messa
|
||||
For each new commits added to one of the release branches (for example `master`, `next`, `beta`), with `git push` or by merging a pull request or merging from another branch, a CI build is triggered and runs the `semantic-release` command to make a release if there are codebase changes since the last release that affect the package functionalities.
|
||||
|
||||
**semantic-release** offers various ways to control the timing, the content and the audience of published releases. See example workflows in the following recipes:
|
||||
|
||||
- [Using distribution channels](docs/recipes/distribution-channels.md#publishing-on-distribution-channels)
|
||||
- [Maintenance releases](docs/recipes/maintenance-releases.md#publishing-maintenance-releases)
|
||||
- [Pre-releases](docs/recipes/pre-releases.md#publishing-pre-releases)
|
||||
@@ -84,7 +79,7 @@ For each new commits added to one of the release branches (for example `master`,
|
||||
After running the tests, the command `semantic-release` will execute the following steps:
|
||||
|
||||
| Step | Description |
|
||||
|-------------------|---------------------------------------------------------------------------------------------------------------------------------|
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Verify Conditions | Verify all the conditions to proceed with the release. |
|
||||
| Get last release | Obtain the commit corresponding to the last release by analyzing [Git tags](https://git-scm.com/book/en/v2/Git-Basics-Tagging). |
|
||||
| Analyze commits | Determine the type of release based on the commits added since the last release. |
|
||||
@@ -98,6 +93,7 @@ After running the tests, the command `semantic-release` will execute the followi
|
||||
## Requirements
|
||||
|
||||
In order to use **semantic-release** you need:
|
||||
|
||||
- To host your code in a [Git repository](https://git-scm.com)
|
||||
- Use a Continuous Integration service that allows you to [securely set up credentials](docs/usage/ci-configuration.md#authentication)
|
||||
- Git CLI version [2.7.1 or higher](docs/support/FAQ.md#why-does-semantic-release-require-git-version--271) installed in your Continuous Integration environment
|
||||
@@ -135,7 +131,7 @@ In order to use **semantic-release** you need:
|
||||
## Get help
|
||||
|
||||
- [Stack Overflow](https://stackoverflow.com/questions/tagged/semantic-release)
|
||||
- [Spectrum community](https://spectrum.chat/semantic-release)
|
||||
- [GitHub Discussions](https://github.com/semantic-release/semantic-release/discussions)
|
||||
- [Twitter](https://twitter.com/SemanticRelease)
|
||||
|
||||
## Badge
|
||||
@@ -160,7 +156,6 @@ Let people know that your package is published using **semantic-release** by inc
|
||||
| ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
||||
| [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) |
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img alt="Kill all humans" src="media/bender.png">
|
||||
</p>
|
||||
|
||||
@@ -40,6 +40,7 @@ require('../cli')()
|
||||
.then((exitCode) => {
|
||||
process.exitCode = exitCode;
|
||||
})
|
||||
.catch(() => {
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
# semantic-release documentation
|
||||
|
||||
- [Usage](usage/README.md) - **semantic-release** installation and configuration
|
||||
- [Extending](extending/README.md)- Extending **semantic-release** with plugins and shareable configurations
|
||||
- [Extending](extending/README.md) - Extending **semantic-release** with plugins and shareable configurations
|
||||
- [Recipes](recipes/README.md) - Community written recipes for common **semantic-release** use-cases
|
||||
- [Developer Guide](developer-guide/README.md) - The essentials of writing a **semantic-release** plugin or shareable configurations
|
||||
- [Support](support/README.md) - FAQ and troubleshooting
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
# Plugin Developer Guide
|
||||
|
||||
To create a plugin for `semantic-release`, you need to decide which parts of the release lifecycle are important to that plugin. For example, it is best to always have a `verify` step because you may be receiving inputs from a user and want to make sure they exist. A plugin can abide by any of the following lifecycles:
|
||||
To create a plugin for `semantic-release`, you need to decide which parts of the release lifecycle are important to that plugin. For example, it is best to always have a `verifyConditions` step because you may be receiving inputs from a user and want to make sure they exist. A plugin can abide by any of the following lifecycles:
|
||||
|
||||
- `verify`
|
||||
- `verifyConditions`
|
||||
- `analyzeCommits`
|
||||
- `verifyRelease`
|
||||
- `generateNotes`
|
||||
- `addChannel`
|
||||
- `prepare`
|
||||
- `publish`
|
||||
- `success`
|
||||
- `fail`
|
||||
|
||||
`semantic-release` will require the plugin via `node` and look through the required object for methods named like the lifecyles stated above. For example, if your plugin only had a `verify` and `success` step, the `main` file for your object would need to `export` an object with `verify` and `success` functions.
|
||||
`semantic-release` will require the plugin via `node` and look through the required object for methods named like the lifecyles stated above. For example, if your plugin only had a `verifyConditions` and `success` step, the `main` file for your object would need to `export` an object with `verifyConditions` and `success` functions.
|
||||
|
||||
In addition to the lifecycle methods, each lifecyle is passed two objects:
|
||||
|
||||
@@ -93,7 +97,131 @@ if (message.length) {
|
||||
}
|
||||
```
|
||||
|
||||
## Supporting Environment Variables
|
||||
## Context
|
||||
|
||||
### Common context keys
|
||||
|
||||
* `stdout`
|
||||
* `stderr`
|
||||
* `logger`
|
||||
|
||||
### Context object keys by lifecycle
|
||||
|
||||
#### verifyConditions
|
||||
|
||||
Initially the context object contains the following keys (`verifyConditions` lifecycle):
|
||||
* `cwd`
|
||||
* Current working directory
|
||||
* `env`
|
||||
* Environment variables
|
||||
* `envCi`
|
||||
* Information about CI environment
|
||||
* Contains (at least) the following keys:
|
||||
* `isCi`
|
||||
* Boolean, true if the environment is a CI environment
|
||||
* `commit`
|
||||
* Commit hash
|
||||
* `branch`
|
||||
* Current branch
|
||||
* `options`
|
||||
* Options passed to `semantic-release` via CLI, configuration files etc.
|
||||
* `branch`
|
||||
* Information on the current branch
|
||||
* Object keys:
|
||||
* `channel`
|
||||
* `tags`
|
||||
* `type`
|
||||
* `name`
|
||||
* `range`
|
||||
* `accept`
|
||||
* `main`
|
||||
* `branches`
|
||||
* Information on branches
|
||||
* List of branch objects (see above)
|
||||
|
||||
#### analyzeCommits
|
||||
|
||||
Compared to the verifyConditions, `analyzeCommits` lifecycle context has keys
|
||||
|
||||
* `commits` (List)
|
||||
* List of commits taken into account when determining the new version.
|
||||
* Keys:
|
||||
* `commit` (Object)
|
||||
* Keys:
|
||||
* `long` (String, Commit hash)
|
||||
* `short` (String, Commit hash)
|
||||
* `tree` (Object)
|
||||
* Keys:
|
||||
* `long` (String, Commit hash)
|
||||
* `short` (String, Commit hash)
|
||||
* `author` (Object)
|
||||
* Keys:
|
||||
* `name` (String)
|
||||
* `email` (String)
|
||||
* `date` (String, ISO 8601 timestamp)
|
||||
* `committer` (Object)
|
||||
* Keys:
|
||||
* `name` (String)
|
||||
* `email` (String)
|
||||
* `date` (String, ISO 8601 timestamp)
|
||||
* `subject` (String, Commit message subject)
|
||||
* `body` (String, Commit message body)
|
||||
* `hash` (String, Commit hash)
|
||||
* `committerDate` (String, ISO 8601 timestamp)
|
||||
* `message` (String)
|
||||
* `gitTags` (String, List of git tags)
|
||||
* `releases` (List)
|
||||
* `lastRelease` (Object)
|
||||
* Keys
|
||||
* `version` (String)
|
||||
* `gitTag` (String)
|
||||
* `channels` (List)
|
||||
* `gitHead` (String, Commit hash)
|
||||
* `name` (String)
|
||||
|
||||
#### verifyRelease
|
||||
|
||||
Additional keys:
|
||||
|
||||
* `nextRelease`
|
||||
* Similar object as `lastRelease` (see above)
|
||||
|
||||
#### generateNotes
|
||||
|
||||
No new content in the context.
|
||||
|
||||
#### addChannel
|
||||
|
||||
*This is run only if there are releases that have been merged from a higher branch but not added on the channel of the current branch.*
|
||||
|
||||
Context content is similar to lifecycle `verifyRelease`.
|
||||
|
||||
#### prepare
|
||||
|
||||
Only change is that `generateNotes` has populated `nextRelease.notes`.
|
||||
|
||||
#### publish
|
||||
|
||||
No new content in the context.
|
||||
|
||||
#### success
|
||||
|
||||
Lifecycles `success` and `fail` are mutually exclusive, only one of them will be run.
|
||||
|
||||
Additional keys:
|
||||
|
||||
* `releases`
|
||||
* Populated by `publish` lifecycle
|
||||
|
||||
#### fail
|
||||
|
||||
Lifecycles `success` and `fail` are mutually exclusive, only one of them will be run.
|
||||
|
||||
Additional keys:
|
||||
|
||||
* `errors`
|
||||
|
||||
### Supporting Environment Variables
|
||||
|
||||
Similar to `options`, environment variables exist to allow users to pass tokens and set special URLs. These are set on the `context` object instead of the `pluginConfig` object. Let's say we wanted to check for `GITHUB_TOKEN` in the environment because we want to post to GitHub on the user's behalf. To do this, we can add the following to our `verify` command:
|
||||
|
||||
@@ -101,6 +229,6 @@ Similar to `options`, environment variables exist to allow users to pass tokens
|
||||
const { env } = context;
|
||||
|
||||
if (env.GITHUB_TOKEN) {
|
||||
//...
|
||||
//...
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
- `publish`: Publish the package on the npm registry
|
||||
- [@semantic-release/gitlab](https://github.com/semantic-release/gitlab)
|
||||
- `verifyConditions`: Verify the presence and the validity of the GitLab authentication and release configuration
|
||||
- `publish`: Publish a [GitLab release](https://docs.gitlab.com/ce/workflow/releases.html)
|
||||
- `publish`: Publish a [GitLab release](https://docs.gitlab.com/ee/user/project/releases/)
|
||||
- [@semantic-release/git](https://github.com/semantic-release/git)
|
||||
- `verifyConditions`: Verify the presence and the validity of the Git authentication and release configuration
|
||||
- `prepare`: Push a release commit and tag, including configurable files
|
||||
@@ -91,6 +91,9 @@
|
||||
- [semantic-release-github-pages](https://github.com/qiwi/semantic-release-gh-pages-plugin)
|
||||
- `verifyConditions`: Verify the presence of the auth token set via environment variables.
|
||||
- `publish`: Pushes commit to the documentation branch.
|
||||
- [semantic-release-github-pullrequest](https://github.com/asbiin/semantic-release-github-pullrequest)
|
||||
- `verifyConditions`: Verify the presence and the validity of the GitHub authentication and other configuration.
|
||||
- `publish`: Create a branch to upload all assets and create the pull request on the base branch on GitHub.
|
||||
- [leiningen-semantic-release](https://github.com/NoxHarmonium/leiningen-semantic-release)
|
||||
- `verifyConditions`: Checks the project.clj is syntactically valid.
|
||||
- `prepare`: Update the project.clj version and package the output jar file.
|
||||
|
||||
@@ -97,7 +97,7 @@ The Git history of the repository is now:
|
||||
|
||||
After a period of feedback from our users using the `@next` dist-tag we feel confident to make our big feature available to all users. To do so we merge the `next` branch into `master`. There should be no conflict as `next` is strictly ahead of `master`.
|
||||
|
||||
Once the merge commit is pushed to `next`, **semantic-release** will add the version `2.1.0` to the dist-tag `@latest` so all users will receive it when installing out module with `npm install example-module`.
|
||||
Once the merge commit is pushed to `master`, **semantic-release** will add the version `2.1.0` to the dist-tag `@latest` so all users will receive it when installing out module with `npm install example-module`.
|
||||
|
||||
The Git history of the repository is now:
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ on:
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
@@ -50,7 +50,7 @@ To keep `package.json` updated in the `master` branch, [`@semantic-release/git`]
|
||||
|
||||
**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.
|
||||
|
||||
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:
|
||||
If the risk is acceptable, 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:
|
||||
|
||||
```yaml
|
||||
- name: Checkout
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ By default, only the published package will contain the version, which is the on
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
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 [the npm registry](https://www.npmjs.com).
|
||||
|
||||
## How can I use a npm build script that requires the `package.json`’s version ?
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
- ["Introduction to SemVer" - Irina Gebauer](https://blog.greenkeeper.io/introduction-to-semver-d272990c44f2)
|
||||
- ["Introduction to Semantic Release" - liv](https://blog.greenkeeper.io/introduction-to-semantic-release-33f73b117c8)
|
||||
- ["Series - Semantic Release Automation" - Abdelrahman Wahdan](https://dev.to/abdelrahmanahmed/semantic-release-and-how-to-automate-it-part-1-4pa2)
|
||||
- ["Explain semantic release and how to use it on GitLab pipeline"](https://regoo707.medium.com/auto-bump-apps-versions-and-releases-using-gitlab-pipeline-e32f1d7fa3ee)
|
||||
|
||||
## Tutorials
|
||||
|
||||
|
||||
@@ -65,5 +65,5 @@ To recover from that situation, do the following:
|
||||
|
||||
1. Delete the tag(s) for the release(s) that have been lost from the git history. You can delete each tag from remote using `git push origin :[TAG NAME]`, e.g. `git push origin :v2.0.0-beta.1`. You can delete tags locally using `git tag -d [TAG NAME]`, e.g. `git tag -d v2.0.0-beta.1`.
|
||||
2. Re-create the tags locally: `git tag [TAG NAME] [COMMIT HASH]`, where `[COMMIT HASH]` is the new commit that created the release for the lost tag. E.g. `git tag v2.0.0-beta.1 abcdef0`
|
||||
3. Re-create the git notes for each release tag, e.g. `git notes --ref semantic-release add -f -m '{"channels":["beta"]}' v3.0.0-beta.1`. If the release was also published in the default channel (usually `master`), then set the first channel to `null`, e.g. `git notes --ref semantic-release add -f -m '{"channels":[null, "beta"]}'
|
||||
3. Re-create the git notes for each release tag, e.g. `git notes --ref semantic-release add -f -m '{"channels":["beta"]}' v2.0.0-beta.1`. If the release was also published in the default channel (usually `master`), then set the first channel to `null`, e.g. `git notes --ref semantic-release add -f -m '{"channels":[null, "beta"]}'
|
||||
4. Push the local notes: `git push --force origin refs/notes/semantic-release`. The `--force` is needed after the rebase. Be careful.
|
||||
|
||||
@@ -8,7 +8,7 @@ Here is a few example of the CI services that can be used to achieve this:
|
||||
- [CircleCI Workflows](https://circleci.com/docs/2.0/workflows)
|
||||
- [GitHub Actions](https://github.com/features/actions)
|
||||
- [Codeship Deployment Pipelines](https://documentation.codeship.com/basic/builds-and-configuration/deployment-pipelines)
|
||||
- [GitLab Pipelines](https://docs.gitlab.com/ee/ci/pipelines.html#introduction-to-pipelines-and-jobs)
|
||||
- [GitLab Pipelines](https://docs.gitlab.com/ce/ci/introduction/)
|
||||
- [Codefresh Pipelines](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines)
|
||||
- [Wercker Workflows](http://devcenter.wercker.com/docs/workflows)
|
||||
- [GoCD Pipelines](https://docs.gocd.org/current/introduction/concepts_in_go.html#pipeline).
|
||||
|
||||
@@ -12,6 +12,7 @@ A plugin is a npm module that can implement one or more of the following steps:
|
||||
| `generateNotes` | No | Responsible for generating the content of the release note. If multiple plugins with a `generateNotes` step are defined, the release notes will be the result of the concatenation of each plugin output. |
|
||||
| `prepare` | No | Responsible for preparing the release, for example creating or updating files such as `package.json`, `CHANGELOG.md`, documentation or compiled assets and pushing a commit. |
|
||||
| `publish` | No | Responsible for publishing the release. |
|
||||
| `addChannel` | No | Responsible for adding a release channel (e.g. adding an npm dist-tag to a release). |
|
||||
| `success` | No | Responsible for notifying of a new release. |
|
||||
| `fail` | No | Responsible for notifying of a failed release. |
|
||||
|
||||
|
||||
+5
-13
@@ -9,27 +9,15 @@ const plugins = require('./plugins');
|
||||
const {validatePlugin, parseConfig} = require('./plugins/utils');
|
||||
|
||||
const CONFIG_NAME = 'release';
|
||||
const CONFIG_FILES = [
|
||||
'package.json',
|
||||
`.${CONFIG_NAME}rc`,
|
||||
`.${CONFIG_NAME}rc.json`,
|
||||
`.${CONFIG_NAME}rc.yaml`,
|
||||
`.${CONFIG_NAME}rc.yml`,
|
||||
`.${CONFIG_NAME}rc.js`,
|
||||
`${CONFIG_NAME}.config.js`,
|
||||
];
|
||||
|
||||
module.exports = async (context, cliOptions) => {
|
||||
const {cwd, env} = context;
|
||||
const {config, filepath} = (await cosmiconfig(CONFIG_NAME, {searchPlaces: CONFIG_FILES}).search(cwd)) || {};
|
||||
const {config, filepath} = (await cosmiconfig(CONFIG_NAME).search(cwd)) || {};
|
||||
|
||||
debug('load config from: %s', filepath);
|
||||
|
||||
// Merge config file options and CLI/API options
|
||||
let options = {...config, ...cliOptions};
|
||||
if (options.ci === false) {
|
||||
options.noCi = true;
|
||||
}
|
||||
|
||||
const pluginsPath = {};
|
||||
let extendPaths;
|
||||
@@ -87,6 +75,10 @@ module.exports = async (context, cliOptions) => {
|
||||
...(options.branches ? {branches: castArray(options.branches)} : {}),
|
||||
};
|
||||
|
||||
if (options.ci === false) {
|
||||
options.noCi = true;
|
||||
}
|
||||
|
||||
debug('options values: %O', options);
|
||||
|
||||
return {options, plugins: await plugins({...context, options}, pluginsPath)};
|
||||
|
||||
+1
-1
@@ -318,7 +318,7 @@ async function getNote(ref, execaOptions) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and parse the JSON note of a given reference.
|
||||
* Add JSON note to a given reference.
|
||||
*
|
||||
* @param {Object} note The object to save in the reference note.
|
||||
* @param {String} ref The Git reference to add the note to.
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="530px" height="500px" viewBox="0 0 530 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>semantic-release-logo</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="semantic-release-logo" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M265,300 C237.385763,300 215,277.614237 215,250 C215,222.385763 237.385763,200 265,200 C292.614237,200 315,222.385763 315,250 C315,277.614237 292.614237,300 265,300 Z M265,285 C284.329966,285 300,269.329966 300,250 C300,230.670034 284.329966,215 265,215 C245.670034,215 230,230.670034 230,250 C230,269.329966 245.670034,285 265,285 Z M189.000329,65.2403903 C188.735843,74.8097173 187.789784,91.8126705 189.063568,101.364143 C190.525406,112.325741 210.229645,156.413574 224,182.11536 C205.822021,168.897491 166.460815,138.916283 154.532196,124.016029 C144.386757,111.343179 140.471577,101.013967 138.27655,94.5257779 L67.4936491,135.392305 L67.4936491,221.416812 C75.70945,226.485387 89.6365324,235.558433 98.3968671,239.169872 C108.620808,243.384682 156.654111,248.364228 185.797688,249.289643 C165.261689,258.4233 119.616597,277.5205 100.74829,280.400861 C85.0249878,282.801118 74.2405506,281.146683 67.4936491,279.815488 L67.4936491,364.607695 L136.385575,404.382467 C144.921121,399.789873 159.526093,392.355786 166.960336,386.631446 C175.722439,379.884659 204.051503,340.77637 219.424725,316 C217.066704,338.351526 210.782819,387.429934 203.843131,405.210548 C198.129099,419.850831 191.397729,428.335995 186.871704,433.530648 L266,479.21539 L339.488885,436.786563 C339.680455,427.59622 340.80544,409.239923 339.462313,399.168483 C338.000475,388.206886 318.296236,344.119052 304.525881,318.417266 C322.70386,331.635135 362.065066,361.616344 373.993685,376.516597 C384.808925,390.026108 388.544108,400.872311 390.662883,407.241241 L464.506351,364.607695 L464.506351,280.839881 C456.814912,276.224155 441.003684,265.702718 431.400821,261.743946 C421.17688,257.529136 373.143577,252.549591 344,251.624176 C364.535999,242.490519 410.181091,223.393319 429.049398,220.512958 C446.610988,217.832076 458.01135,220.209416 464.506351,221.544989 L464.506351,135.392305 L395.40349,95.4957494 C387.052842,100.028294 371.568068,107.82975 363.837352,113.782373 C355.075249,120.52916 326.746185,159.637448 311.372963,184.413819 C313.730984,162.062293 320.014869,112.983884 326.954557,95.2032704 C332.946763,79.8502605 340.057772,71.2662505 344.570949,66.147568 L266,20.7846097 L189.000329,65.2403903 L189.000329,65.2403903 Z M266,0 L482.506351,125 L482.506351,375 L266,500 L49.4936491,375 L49.4936491,125 L266,0 Z" id="semantic-release-logo-shape" fill="#494949" fill-rule="nonzero"></path>
|
||||
</g>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="15 0 500 500" width="500px" height="500px">
|
||||
<path fill="#494949" fill-rule="nonzero" d="M265 300a50 50 0 110-100 50 50 0 010 100zm0-15a35 35 0 100-70 35 35 0 000 70zM189 65v36c2 11 21 55 35 81-18-13-58-43-69-58a92 92 0 01-17-29l-71 40v86c9 5 23 15 31 18 11 4 59 9 88 10-21 9-66 29-85 31-16 3-27 1-34 0v85l69 39c9-4 24-12 31-17 9-7 37-46 52-71-2 22-8 71-15 89-6 15-13 23-17 29l79 45 73-42c1-9 2-28 0-38-1-11-21-55-34-81 18 14 57 44 69 59 11 13 15 24 17 30l74-42v-84c-8-5-24-15-34-19s-58-9-87-10c21-10 66-29 85-31 18-3 29-1 36 1v-87l-70-40-31 19c-9 7-37 46-53 70 3-22 9-71 16-89 6-15 13-24 18-29l-79-45-77 44zm77-65l217 125v250L266 500 49 375V125L266 0z"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 715 B |
Generated
+13527
File diff suppressed because it is too large
Load Diff
+33
-27
@@ -26,19 +26,19 @@
|
||||
"@semantic-release/npm": "^7.0.0",
|
||||
"@semantic-release/release-notes-generator": "^9.0.0",
|
||||
"aggregate-error": "^3.0.0",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"cosmiconfig": "^7.0.0",
|
||||
"debug": "^4.0.0",
|
||||
"env-ci": "^5.0.0",
|
||||
"execa": "^4.0.0",
|
||||
"execa": "^5.0.0",
|
||||
"figures": "^3.0.0",
|
||||
"find-versions": "^4.0.0",
|
||||
"get-stream": "^5.0.0",
|
||||
"get-stream": "^6.0.0",
|
||||
"git-log-parser": "^1.2.0",
|
||||
"hook-std": "^2.0.0",
|
||||
"hosted-git-info": "^3.0.0",
|
||||
"lodash": "^4.17.15",
|
||||
"marked": "^1.0.0",
|
||||
"marked-terminal": "^4.0.0",
|
||||
"hosted-git-info": "^4.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"marked": "^2.0.0",
|
||||
"marked-terminal": "^4.1.1",
|
||||
"micromatch": "^4.0.2",
|
||||
"p-each-series": "^2.1.0",
|
||||
"p-reduce": "^2.0.0",
|
||||
@@ -47,27 +47,27 @@
|
||||
"semver": "^7.3.2",
|
||||
"semver-diff": "^3.1.1",
|
||||
"signale": "^1.2.1",
|
||||
"yargs": "^15.0.1"
|
||||
"yargs": "^16.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^3.1.0",
|
||||
"clear-module": "^4.0.0",
|
||||
"codecov": "^3.0.0",
|
||||
"delay": "^4.0.0",
|
||||
"dockerode": "^3.0.0",
|
||||
"file-url": "^3.0.0",
|
||||
"fs-extra": "^9.0.0",
|
||||
"got": "^11.0.0",
|
||||
"js-yaml": "^3.10.0",
|
||||
"mockserver-client": "^5.1.1",
|
||||
"nock": "^12.0.0",
|
||||
"nyc": "^15.0.0",
|
||||
"p-retry": "^4.0.0",
|
||||
"proxyquire": "^2.0.0",
|
||||
"sinon": "^9.0.0",
|
||||
"stream-buffers": "^3.0.2",
|
||||
"tempy": "^0.5.0",
|
||||
"xo": "^0.29.0"
|
||||
"ava": "3.15.0",
|
||||
"clear-module": "4.1.1",
|
||||
"codecov": "3.8.1",
|
||||
"delay": "5.0.0",
|
||||
"dockerode": "3.2.1",
|
||||
"file-url": "3.0.0",
|
||||
"fs-extra": "9.1.0",
|
||||
"got": "11.8.2",
|
||||
"js-yaml": "3.14.1",
|
||||
"mockserver-client": "5.11.2",
|
||||
"nock": "13.0.11",
|
||||
"nyc": "15.1.0",
|
||||
"p-retry": "4.5.0",
|
||||
"proxyquire": "2.1.3",
|
||||
"sinon": "9.2.4",
|
||||
"stream-buffers": "3.0.2",
|
||||
"tempy": "1.0.0",
|
||||
"xo": "0.29.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.18"
|
||||
@@ -122,7 +122,8 @@
|
||||
"lint": "xo",
|
||||
"pretest": "npm run lint",
|
||||
"semantic-release": "./bin/semantic-release.js",
|
||||
"test": "nyc ava -v"
|
||||
"test": "nyc ava -v",
|
||||
"test:ci": "nyc ava -v"
|
||||
},
|
||||
"xo": {
|
||||
"prettier": true,
|
||||
@@ -130,5 +131,10 @@
|
||||
"rules": {
|
||||
"unicorn/string-content": "off"
|
||||
}
|
||||
},
|
||||
"renovate": {
|
||||
"extends": [
|
||||
"github>semantic-release/.github"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
+63
-2
@@ -191,6 +191,28 @@ test('Read options from .releaserc.js', async (t) => {
|
||||
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
|
||||
});
|
||||
|
||||
test('Read options from .releaserc.cjs', async (t) => {
|
||||
// Create a git repository, set the current working directory at the root of the repo
|
||||
const {cwd} = await gitRepo();
|
||||
const options = {
|
||||
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
|
||||
branches: ['test_branch'],
|
||||
repositoryUrl: 'https://host.null/owner/module.git',
|
||||
tagFormat: `v\${version}`,
|
||||
plugins: false,
|
||||
};
|
||||
// Create .releaserc.cjs in repository root
|
||||
await writeFile(path.resolve(cwd, '.releaserc.cjs'), `module.exports = ${JSON.stringify(options)}`);
|
||||
|
||||
const {options: result} = await t.context.getConfig({cwd});
|
||||
|
||||
const expected = {...options, branches: ['test_branch']};
|
||||
// Verify the options contains the plugin config from .releaserc.cjs
|
||||
t.deepEqual(result, expected);
|
||||
// Verify the plugins module is called with the plugin options from .releaserc.cjs
|
||||
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
|
||||
});
|
||||
|
||||
test('Read options from release.config.js', async (t) => {
|
||||
// Create a git repository, set the current working directory at the root of the repo
|
||||
const {cwd} = await gitRepo();
|
||||
@@ -213,6 +235,28 @@ test('Read options from release.config.js', async (t) => {
|
||||
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
|
||||
});
|
||||
|
||||
test('Read options from release.config.cjs', async (t) => {
|
||||
// Create a git repository, set the current working directory at the root of the repo
|
||||
const {cwd} = await gitRepo();
|
||||
const options = {
|
||||
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
|
||||
branches: ['test_branch'],
|
||||
repositoryUrl: 'https://host.null/owner/module.git',
|
||||
tagFormat: `v\${version}`,
|
||||
plugins: false,
|
||||
};
|
||||
// Create release.config.cjs in repository root
|
||||
await writeFile(path.resolve(cwd, 'release.config.cjs'), `module.exports = ${JSON.stringify(options)}`);
|
||||
|
||||
const {options: result} = await t.context.getConfig({cwd});
|
||||
|
||||
const expected = {...options, branches: ['test_branch']};
|
||||
// Verify the options contains the plugin config from release.config.cjs
|
||||
t.deepEqual(result, expected);
|
||||
// Verify the plugins module is called with the plugin options from release.config.cjs
|
||||
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
|
||||
});
|
||||
|
||||
test('Prioritise CLI/API parameters over file configuration and git repo', async (t) => {
|
||||
// Create a git repository, set the current working directory at the root of the repo
|
||||
let {cwd, repositoryUrl} = await gitRepo();
|
||||
@@ -505,10 +549,10 @@ test('Allow to unset properties defined in shareable config with "undefined"', a
|
||||
test('Throw an Error if one of the shareable config cannot be found', async (t) => {
|
||||
// Create a git repository, set the current working directory at the root of the repo
|
||||
const {cwd} = await gitRepo();
|
||||
const pkhOptions = {extends: ['./shareable1.json', 'non-existing-path']};
|
||||
const pkgOptions = {extends: ['./shareable1.json', 'non-existing-path']};
|
||||
const options1 = {analyzeCommits: 'analyzeCommits'};
|
||||
// Create package.json and shareable.json in repository root
|
||||
await outputJson(path.resolve(cwd, 'package.json'), {release: pkhOptions});
|
||||
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});
|
||||
await outputJson(path.resolve(cwd, 'shareable1.json'), options1);
|
||||
|
||||
await t.throwsAsync(t.context.getConfig({cwd}), {
|
||||
@@ -516,3 +560,20 @@ test('Throw an Error if one of the shareable config cannot be found', async (t)
|
||||
code: 'MODULE_NOT_FOUND',
|
||||
});
|
||||
});
|
||||
|
||||
test('Convert "ci" option to "noCi" when set from extended config', async (t) => {
|
||||
// Create a git repository, set the current working directory at the root of the repo
|
||||
const {cwd} = await gitRepo();
|
||||
const pkgOptions = {extends: './no-ci.json'};
|
||||
const options = {
|
||||
ci: false,
|
||||
};
|
||||
// Create package.json and shareable.json in repository root
|
||||
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});
|
||||
await outputJson(path.resolve(cwd, 'no-ci.json'), options);
|
||||
|
||||
const {options: result} = await t.context.getConfig({cwd});
|
||||
|
||||
t.is(result.ci, false);
|
||||
t.is(result.noCi, true);
|
||||
});
|
||||
|
||||
@@ -25,8 +25,12 @@ const {GIT_NOTE_REF} = require('../../lib/definitions/constants');
|
||||
*/
|
||||
async function initGit(withRemote) {
|
||||
const cwd = tempy.directory();
|
||||
const args = withRemote ? ['--bare', '--initial-branch=master'] : ['--initial-branch=master'];
|
||||
|
||||
await execa('git', ['init', ...(withRemote ? ['--bare'] : [])], {cwd});
|
||||
await execa('git', ['init', ...args], {cwd}).catch(() => {
|
||||
const args = withRemote ? ['--bare'] : [];
|
||||
return execa('git', ['init', ...args], {cwd});
|
||||
});
|
||||
const repositoryUrl = fileUrl(cwd);
|
||||
return {cwd, repositoryUrl};
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ async function createRepo(name, branch = 'master', description = `Repository ${n
|
||||
const authUrl = `http://${gitCredential}@${SERVER_HOST}:${HOST_PORT}/git/${name}.git`;
|
||||
|
||||
// Retry as the server might take a few ms to make the repo available push
|
||||
await pRetry(() => initBareRepo(authUrl, branch), {retries: 3, minTimeout: 500, factor: 2});
|
||||
await pRetry(() => initBareRepo(authUrl, branch), {retries: 5, minTimeout: 500, factor: 2});
|
||||
const cwd = await gitShallowClone(authUrl);
|
||||
|
||||
return {cwd, repositoryUrl, authUrl};
|
||||
|
||||
+38
-31
@@ -29,17 +29,20 @@ const npmRegistry = require('./helpers/npm-registry');
|
||||
const requireNoCache = proxyquire.noPreserveCache();
|
||||
|
||||
// Environment variables used with semantic-release cli (similar to what a user would setup)
|
||||
const {GITHUB_ACTION, GITHUB_TOKEN, ...processEnvWithoutGitHubActionsVariables} = process.env;
|
||||
const env = {
|
||||
...processEnvWithoutGitHubActionsVariables,
|
||||
...npmRegistry.authEnv,
|
||||
GH_TOKEN: gitbox.gitCredential,
|
||||
GITHUB_URL: mockServer.url,
|
||||
TRAVIS: 'true',
|
||||
CI: 'true',
|
||||
GH_TOKEN: gitbox.gitCredential,
|
||||
TRAVIS: 'true',
|
||||
TRAVIS_BRANCH: 'master',
|
||||
TRAVIS_PULL_REQUEST: 'false',
|
||||
GITHUB_API_URL: mockServer.url,
|
||||
};
|
||||
|
||||
// Environment variables used only for the local npm command used to do verification
|
||||
const testEnv = {
|
||||
const npmTestEnv = {
|
||||
...process.env,
|
||||
...npmRegistry.authEnv,
|
||||
npm_config_registry: npmRegistry.url,
|
||||
@@ -74,7 +77,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
release: {branches: ['master', 'next'], success: false, fail: false},
|
||||
});
|
||||
// Create a npm-shrinkwrap.json file
|
||||
await execa('npm', ['shrinkwrap'], {env: testEnv, cwd});
|
||||
await execa('npm', ['shrinkwrap'], {env: npmTestEnv, cwd, extendEnv: false});
|
||||
|
||||
/* No release */
|
||||
let verifyMock = await mockServer.mock(
|
||||
@@ -85,7 +88,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
t.log('Commit a chore');
|
||||
await gitCommits(['chore: Init repository'], {cwd});
|
||||
t.log('$ semantic-release');
|
||||
let {stdout, exitCode} = await execa(cli, [], {env, cwd});
|
||||
let {stdout, exitCode} = await execa(cli, [], {env, cwd, extendEnv: false});
|
||||
t.regex(stdout, /There are no relevant changes, so no new version is released/);
|
||||
t.is(exitCode, 0);
|
||||
|
||||
@@ -108,7 +111,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
t.log('Commit a feature');
|
||||
await gitCommits(['feat: Initial commit'], {cwd});
|
||||
t.log('$ semantic-release');
|
||||
({stdout, exitCode} = await execa(cli, [], {env, cwd}));
|
||||
({stdout, exitCode} = await execa(cli, [], {env, cwd, extendEnv: false}));
|
||||
t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`));
|
||||
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
|
||||
t.is(exitCode, 0);
|
||||
@@ -120,7 +123,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
// Retrieve the published package from the registry and check version and gitHead
|
||||
let {
|
||||
'dist-tags': {latest: releasedVersion},
|
||||
} = await npmView(packageName, testEnv);
|
||||
} = await npmView(packageName, npmTestEnv);
|
||||
let head = await gitHead({cwd});
|
||||
t.is(releasedVersion, version);
|
||||
t.is(await gitTagHead(`v${version}`, {cwd}), head);
|
||||
@@ -149,7 +152,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
t.log('Commit a fix');
|
||||
await gitCommits(['fix: bar'], {cwd});
|
||||
t.log('$ semantic-release');
|
||||
({stdout, exitCode} = await execa(cli, [], {env, cwd}));
|
||||
({stdout, exitCode} = await execa(cli, [], {env, cwd, extendEnv: false}));
|
||||
t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`));
|
||||
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
|
||||
t.is(exitCode, 0);
|
||||
@@ -161,7 +164,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
// Retrieve the published package from the registry and check version and gitHead
|
||||
({
|
||||
'dist-tags': {latest: releasedVersion},
|
||||
} = await npmView(packageName, testEnv));
|
||||
} = await npmView(packageName, npmTestEnv));
|
||||
head = await gitHead({cwd});
|
||||
t.is(releasedVersion, version);
|
||||
t.is(await gitTagHead(`v${version}`, {cwd}), head);
|
||||
@@ -190,7 +193,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
t.log('Commit a feature');
|
||||
await gitCommits(['feat: baz'], {cwd});
|
||||
t.log('$ semantic-release');
|
||||
({stdout, exitCode} = await execa(cli, [], {env, cwd}));
|
||||
({stdout, exitCode} = await execa(cli, [], {env, cwd, extendEnv: false}));
|
||||
t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`));
|
||||
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
|
||||
t.is(exitCode, 0);
|
||||
@@ -202,7 +205,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
// Retrieve the published package from the registry and check version and gitHead
|
||||
({
|
||||
'dist-tags': {latest: releasedVersion},
|
||||
} = await npmView(packageName, testEnv));
|
||||
} = await npmView(packageName, npmTestEnv));
|
||||
head = await gitHead({cwd});
|
||||
t.is(releasedVersion, version);
|
||||
t.is(await gitTagHead(`v${version}`, {cwd}), head);
|
||||
@@ -233,7 +236,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
await gitPush('origin', 'next', {cwd});
|
||||
await gitCommits(['feat: foo\n\n BREAKING CHANGE: bar'], {cwd});
|
||||
t.log('$ semantic-release');
|
||||
({stdout, exitCode} = await execa(cli, [], {env: {...env, TRAVIS_BRANCH: 'next'}, cwd}));
|
||||
({stdout, exitCode} = await execa(cli, [], {env: {...env, TRAVIS_BRANCH: 'next'}, cwd, extendEnv: false}));
|
||||
t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`));
|
||||
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
|
||||
t.is(exitCode, 0);
|
||||
@@ -245,7 +248,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
// Retrieve the published package from the registry and check version and gitHead
|
||||
({
|
||||
'dist-tags': {next: releasedVersion},
|
||||
} = await npmView(packageName, testEnv));
|
||||
} = await npmView(packageName, npmTestEnv));
|
||||
head = await gitHead({cwd});
|
||||
t.is(releasedVersion, version);
|
||||
t.is(await gitGetNote(`v${version}`, {cwd}), '{"channels":["next"]}');
|
||||
@@ -283,7 +286,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
await merge('next', {cwd});
|
||||
await gitPush('origin', 'master', {cwd});
|
||||
t.log('$ semantic-release');
|
||||
({stdout, exitCode} = await execa(cli, [], {env, cwd}));
|
||||
({stdout, exitCode} = await execa(cli, [], {env, cwd, extendEnv: false}));
|
||||
t.regex(stdout, new RegExp(`Updated GitHub release: release-url/${version}`));
|
||||
t.regex(stdout, new RegExp(`Adding version ${version} to npm registry on dist-tag latest`));
|
||||
t.is(exitCode, 0);
|
||||
@@ -293,7 +296,7 @@ test('Release patch, minor and major versions', async (t) => {
|
||||
// Retrieve the published package from the registry and check version and gitHead
|
||||
({
|
||||
'dist-tags': {latest: releasedVersion},
|
||||
} = await npmView(packageName, testEnv));
|
||||
} = await npmView(packageName, npmTestEnv));
|
||||
t.is(releasedVersion, version);
|
||||
t.is(await gitGetNote(`v${version}`, {cwd}), '{"channels":["next",null]}');
|
||||
t.is(await gitTagHead(`v${version}`, {cwd}), await gitTagHead(`v${version}`, {cwd}));
|
||||
@@ -318,7 +321,7 @@ test('Exit with 1 if a plugin is not found', async (t) => {
|
||||
release: {analyzeCommits: 'non-existing-path', success: false, fail: false},
|
||||
});
|
||||
|
||||
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
|
||||
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd, extendEnv: false}));
|
||||
t.is(exitCode, 1);
|
||||
t.regex(stderr, /Cannot find module/);
|
||||
});
|
||||
@@ -336,7 +339,7 @@ test('Exit with 1 if a shareable config is not found', async (t) => {
|
||||
release: {extends: 'non-existing-path', success: false, fail: false},
|
||||
});
|
||||
|
||||
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
|
||||
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd, extendEnv: false}));
|
||||
t.is(exitCode, 1);
|
||||
t.regex(stderr, /Cannot find module/);
|
||||
});
|
||||
@@ -357,7 +360,7 @@ test('Exit with 1 if a shareable config reference a not found plugin', async (t)
|
||||
});
|
||||
await writeJson(path.resolve(cwd, 'shareable.json'), shareable);
|
||||
|
||||
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
|
||||
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd, extendEnv: false}));
|
||||
t.is(exitCode, 1);
|
||||
t.regex(stderr, /Cannot find module/);
|
||||
});
|
||||
@@ -387,7 +390,7 @@ test('Dry-run', async (t) => {
|
||||
t.log('Commit a feature');
|
||||
await gitCommits(['feat: Initial commit'], {cwd});
|
||||
t.log('$ semantic-release -d');
|
||||
const {stdout, exitCode} = await execa(cli, ['-d'], {env, cwd});
|
||||
const {stdout, exitCode} = await execa(cli, ['-d'], {env, cwd, extendEnv: false});
|
||||
t.regex(stdout, new RegExp(`There is no previous release, the next release version is ${version}`));
|
||||
t.regex(stdout, new RegExp(`Release note for version ${version}`));
|
||||
t.regex(stdout, /Initial commit/);
|
||||
@@ -400,7 +403,6 @@ test('Dry-run', async (t) => {
|
||||
|
||||
test('Allow local releases with "noCi" option', async (t) => {
|
||||
const envNoCi = {...env};
|
||||
delete envNoCi.TRAVIS;
|
||||
delete envNoCi.CI;
|
||||
const packageName = 'test-no-ci';
|
||||
const owner = 'git';
|
||||
@@ -435,7 +437,7 @@ test('Allow local releases with "noCi" option', async (t) => {
|
||||
t.log('Commit a feature');
|
||||
await gitCommits(['feat: Initial commit'], {cwd});
|
||||
t.log('$ semantic-release --no-ci');
|
||||
const {stdout, exitCode} = await execa(cli, ['--no-ci'], {env: envNoCi, cwd});
|
||||
const {stdout, exitCode} = await execa(cli, ['--no-ci'], {env: envNoCi, cwd, extendEnv: false});
|
||||
t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`));
|
||||
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
|
||||
t.is(exitCode, 0);
|
||||
@@ -444,7 +446,7 @@ test('Allow local releases with "noCi" option', async (t) => {
|
||||
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
|
||||
|
||||
// Retrieve the published package from the registry and check version and gitHead
|
||||
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, testEnv);
|
||||
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, npmTestEnv);
|
||||
|
||||
const head = await gitHead({cwd});
|
||||
t.is(releasedVersion, version);
|
||||
@@ -488,7 +490,7 @@ test('Pass options via CLI arguments', async (t) => {
|
||||
false,
|
||||
'--debug',
|
||||
],
|
||||
{env, cwd}
|
||||
{env, cwd, extendEnv: false}
|
||||
);
|
||||
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
|
||||
t.is(exitCode, 0);
|
||||
@@ -497,7 +499,7 @@ test('Pass options via CLI arguments', async (t) => {
|
||||
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
|
||||
|
||||
// Retrieve the published package from the registry and check version and gitHead
|
||||
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, testEnv);
|
||||
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, npmTestEnv);
|
||||
const head = await gitHead({cwd});
|
||||
t.is(releasedVersion, version);
|
||||
t.is(releasedGitHead, head);
|
||||
@@ -553,7 +555,7 @@ test('Run via JS API', async (t) => {
|
||||
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
|
||||
|
||||
// Retrieve the published package from the registry and check version and gitHead
|
||||
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, testEnv);
|
||||
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, npmTestEnv);
|
||||
const head = await gitHead({cwd});
|
||||
t.is(releasedVersion, version);
|
||||
t.is(releasedGitHead, head);
|
||||
@@ -582,7 +584,7 @@ test('Log unexpected errors from plugins and exit with 1', async (t) => {
|
||||
t.log('Commit a feature');
|
||||
await gitCommits(['feat: Initial commit'], {cwd});
|
||||
t.log('$ semantic-release');
|
||||
const {stderr, exitCode} = await execa(cli, [], {env, cwd, reject: false});
|
||||
const {stderr, exitCode} = await execa(cli, [], {env, cwd, reject: false, extendEnv: false});
|
||||
// Verify the type and message are logged
|
||||
t.regex(stderr, /Error: a/);
|
||||
// Verify the the stacktrace is logged
|
||||
@@ -609,7 +611,7 @@ test('Log errors inheriting SemanticReleaseError and exit with 1', async (t) =>
|
||||
t.log('Commit a feature');
|
||||
await gitCommits(['feat: Initial commit'], {cwd});
|
||||
t.log('$ semantic-release');
|
||||
const {stderr, exitCode} = await execa(cli, [], {env, cwd, reject: false});
|
||||
const {stderr, exitCode} = await execa(cli, [], {env, cwd, reject: false, extendEnv: false});
|
||||
// Verify the type and message are logged
|
||||
t.regex(stderr, /EINHERITED Inherited error/);
|
||||
t.is(exitCode, 1);
|
||||
@@ -630,7 +632,7 @@ test('Exit with 1 if missing permission to push to the remote repository', async
|
||||
const {stderr, exitCode} = await execa(
|
||||
cli,
|
||||
['--repository-url', 'http://user:wrong_pass@localhost:2080/git/unauthorized.git'],
|
||||
{env: {...env, GH_TOKEN: 'user:wrong_pass'}, cwd, reject: false}
|
||||
{env: {...env, GH_TOKEN: 'user:wrong_pass'}, cwd, reject: false, extendEnv: false}
|
||||
);
|
||||
// Verify the type and message are logged
|
||||
t.regex(stderr, /EGITNOPERMISSION/);
|
||||
@@ -650,7 +652,12 @@ test('Hide sensitive environment variable values from the logs', async (t) => {
|
||||
});
|
||||
|
||||
t.log('$ semantic-release');
|
||||
const {stdout, stderr} = await execa(cli, [], {env: {...env, MY_TOKEN: 'secret token'}, cwd, reject: false});
|
||||
const {stdout, stderr} = await execa(cli, [], {
|
||||
env: {...env, MY_TOKEN: 'secret token'},
|
||||
cwd,
|
||||
reject: false,
|
||||
extendEnv: false,
|
||||
});
|
||||
|
||||
t.regex(stdout, new RegExp(`Console: Exposing token ${escapeRegExp(SECRET_REPLACEMENT)}`));
|
||||
t.regex(stdout, new RegExp(`Log: Exposing token ${escapeRegExp(SECRET_REPLACEMENT)}`));
|
||||
@@ -680,7 +687,7 @@ test('Use the valid git credentials when multiple are provided', async (t) => {
|
||||
|
||||
test('Use the repository URL as is if none of the given git credentials are valid', async (t) => {
|
||||
const {cwd} = await gitbox.createRepo('test-invalid-auth');
|
||||
const dummyUrl = 'http://toto@localhost:2080/git/test-auth.git';
|
||||
const dummyUrl = 'http://toto@localhost:2080/git/test-invalid-auth.git';
|
||||
|
||||
t.is(
|
||||
await getAuthUrl({
|
||||
|
||||
Reference in New Issue
Block a user