Compare commits
55
Commits
@@ -1,8 +1,8 @@
|
|||||||
<h1 align="center" style="border-bottom: none;">📦🚀 semantic-release</h1>
|
<h1 align="center" style="border-bottom: none;">📦🚀 semantic-release</h1>
|
||||||
<h3 align="center">Fully automated version management and package publishing</h3>
|
<h3 align="center">Fully automated version management and package publishing</h3>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://gitter.im/semantic-release/semantic-release">
|
<a href="https://spectrum.chat/semantic-release">
|
||||||
<img alt="Gitter" src="https://badges.gitter.im/semantic-release/semantic-release.svg">
|
<img alt="Join the community on Spectrum" src="https://withspectrum.github.io/badge/badge.svg">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://travis-ci.org/semantic-release/semantic-release">
|
<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">
|
<img alt="Travis" src="https://img.shields.io/travis/semantic-release/semantic-release/master.svg">
|
||||||
@@ -17,11 +17,6 @@
|
|||||||
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
|
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
|
||||||
<a href="https://waffle.io/semantic-release/semantic-release">
|
|
||||||
<img alt="Waffle.io" src="https://badge.waffle.io/semantic-release/semantic-release.svg?columns=all">
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://www.npmjs.com/package/semantic-release">
|
<a href="https://www.npmjs.com/package/semantic-release">
|
||||||
<img alt="npm latest version" src="https://img.shields.io/npm/v/semantic-release/latest.svg">
|
<img alt="npm latest version" src="https://img.shields.io/npm/v/semantic-release/latest.svg">
|
||||||
@@ -57,7 +52,7 @@ This removes the immediate connection between human emotions and version numbers
|
|||||||
|
|
||||||
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.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.
|
||||||
|
|
||||||
Tools such as [commitizen](https://github.com/commitizen/cz-cli), [commitlint](https://github.com/marionebl/commitlint) or [semantic-git-commit-cli](https://github.com/JPeer264/node-semantic-git-commit-cli) can be used to help contributors and enforce valid commit messages.
|
Tools such as [commitizen](https://github.com/commitizen/cz-cli), [commitlint](https://github.com/conventional-changelog/commitlint) or [semantic-git-commit-cli](https://github.com/JPeer264/node-semantic-git-commit-cli) 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:
|
Here is an example of the release type that will be done based on a commit messages:
|
||||||
|
|
||||||
@@ -124,7 +119,7 @@ After running the tests, the command `semantic-release` will execute the followi
|
|||||||
## Get help
|
## Get help
|
||||||
|
|
||||||
- [Stack Overflow](https://stackoverflow.com/questions/tagged/semantic-release)
|
- [Stack Overflow](https://stackoverflow.com/questions/tagged/semantic-release)
|
||||||
- [Gitter chat](https://gitter.im/semantic-release/semantic-release)
|
- [Spectrum community](https://spectrum.chat/semantic-release)
|
||||||
- [Twitter](https://twitter.com/SemanticRelease)
|
- [Twitter](https://twitter.com/SemanticRelease)
|
||||||
|
|
||||||
## Badge
|
## Badge
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// Bad news: We have to write plain ES5 in this file
|
// Bad news: We have to write plain ES5 in this file
|
||||||
// Good news: It's the only file of the entire project
|
// Good news: It's the only file of the entire project
|
||||||
|
|
||||||
/* eslint-disable no-var, promise/prefer-await-to-then, prefer-destructuring */
|
/* eslint-disable no-var */
|
||||||
|
|
||||||
var semver = require('semver');
|
var semver = require('semver');
|
||||||
var execa = require('execa');
|
var execa = require('execa');
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const {argv, env, stderr} = require('process');
|
const {argv, env, stderr} = require('process'); // eslint-disable-line node/prefer-global/process
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
const hideSensitive = require('./lib/hide-sensitive');
|
const hideSensitive = require('./lib/hide-sensitive');
|
||||||
|
|
||||||
@@ -47,21 +47,18 @@ Usage:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the `noCi` options as yargs sets the `ci` options instead (because arg starts with `--no`)
|
|
||||||
if (opts.ci === false) {
|
|
||||||
opts.noCi = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.debug) {
|
if (opts.debug) {
|
||||||
// Debug must be enabled before other requires in order to work
|
// Debug must be enabled before other requires in order to work
|
||||||
require('debug').enable('semantic-release:*');
|
require('debug').enable('semantic-release:*');
|
||||||
}
|
}
|
||||||
|
|
||||||
await require('.')(opts);
|
await require('.')(opts);
|
||||||
return 0;
|
return 0;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.name !== 'YError') {
|
if (error.name !== 'YError') {
|
||||||
stderr.write(hideSensitive(env)(util.inspect(error, {colors: true})));
|
stderr.write(hideSensitive(env)(util.inspect(error, {colors: true})));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const release of releases) {
|
for (const release of releases) {
|
||||||
console.log(`The release was published with plugin "${pluginName}".`);
|
console.log(`The release was published with plugin "${release.pluginName}".`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('No release published.');
|
console.log('No release published.');
|
||||||
|
|||||||
@@ -2,15 +2,19 @@
|
|||||||
|
|
||||||
## Official plugins
|
## Official plugins
|
||||||
- [@semantic-release/commit-analyzer](https://github.com/semantic-release/commit-analyzer)
|
- [@semantic-release/commit-analyzer](https://github.com/semantic-release/commit-analyzer)
|
||||||
|
- **Note**: this is already part of semantic-release and does not have to be installed separately
|
||||||
- `analyzeCommits`: Determine the type of release by analyzing commits with [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog)
|
- `analyzeCommits`: Determine the type of release by analyzing commits with [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog)
|
||||||
- [@semantic-release/release-notes-generator](https://github.com/semantic-release/release-notes-generator)
|
- [@semantic-release/release-notes-generator](https://github.com/semantic-release/release-notes-generator)
|
||||||
|
- **Note**: this is already part of semantic-release and does not have to be installed separately
|
||||||
- `generateNotes`: Generate release notes for the commits added since the last release with [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog)
|
- `generateNotes`: Generate release notes for the commits added since the last release with [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog)
|
||||||
- [@semantic-release/github](https://github.com/semantic-release/github)
|
- [@semantic-release/github](https://github.com/semantic-release/github)
|
||||||
|
- **Note**: this is already part of semantic-release and does not have to be installed separately
|
||||||
- `verifyConditions`: Verify the presence and the validity of the GitHub authentication and release configuration
|
- `verifyConditions`: Verify the presence and the validity of the GitHub authentication and release configuration
|
||||||
- `publish`: Publish a [GitHub release](https://help.github.com/articles/about-releases)
|
- `publish`: Publish a [GitHub release](https://help.github.com/articles/about-releases)
|
||||||
- `success`: Add a comment to GitHub issues and pull requests resolved in the release
|
- `success`: Add a comment to GitHub issues and pull requests resolved in the release
|
||||||
- `fail`: Open a GitHub issue when a release fails
|
- `fail`: Open a GitHub issue when a release fails
|
||||||
- [@semantic-release/npm](https://github.com/semantic-release/npm)
|
- [@semantic-release/npm](https://github.com/semantic-release/npm)
|
||||||
|
- **Note**: this is already part of semantic-release and does not have to be installed separately
|
||||||
- `verifyConditions`: Verify the presence and the validity of the npm authentication and release configuration
|
- `verifyConditions`: Verify the presence and the validity of the npm authentication and release configuration
|
||||||
- `prepare`: Update the package.json version and create the npm package tarball
|
- `prepare`: Update the package.json version and create the npm package tarball
|
||||||
- `publish`: Publish the package on the npm registry
|
- `publish`: Publish the package on the npm registry
|
||||||
@@ -26,23 +30,31 @@
|
|||||||
- [@semantic-release/exec](https://github.com/semantic-release/exec)
|
- [@semantic-release/exec](https://github.com/semantic-release/exec)
|
||||||
- `verifyConditions`: Execute a shell command to verify if the release should happen
|
- `verifyConditions`: Execute a shell command to verify if the release should happen
|
||||||
- `analyzeCommits`: Execute a shell command to determine the type of release
|
- `analyzeCommits`: Execute a shell command to determine the type of release
|
||||||
- `verifyRelease`: Execute a shell command to verifying a release that was determined before and is about to be published.
|
- `verifyRelease`: Execute a shell command to verifying a release that was determined before and is about to be published
|
||||||
- `generateNotes`: Execute a shell command to generate the release note
|
- `generateNotes`: Execute a shell command to generate the release note
|
||||||
- `prepare`: Execute a shell command to prepare the release
|
- `prepare`: Execute a shell command to prepare the release
|
||||||
- `publish`: Execute a shell command to publish the release
|
- `publish`: Execute a shell command to publish the release
|
||||||
- `success`: Execute a shell command to notify of a new release
|
- `success`: Execute a shell command to notify of a new release
|
||||||
- `fail`: Execute a shell command to notify of a failed release
|
- `fail`: Execute a shell command to notify of a failed release
|
||||||
|
- [@semantic-release/apm](https://github.com/semantic-release/apm)
|
||||||
|
- `verifyConditions`: Verify the presence of the `ATOM_ACCESS_TOKEN` environment variable and the [`apm`](https://github.com/atom/apm) CLI
|
||||||
|
- `prepare`: Update the `package.json` version with [`npm version`](https://docs.npmjs.com/cli/version)
|
||||||
|
- `publish`: Publish the [Atom package](https://flight-manual.atom.io/hacking-atom/sections/publishing)
|
||||||
|
|
||||||
## Community plugins
|
## Community plugins
|
||||||
|
|
||||||
[Open a Pull Request](https://github.com/semantic-release/semantic-release/blob/master/CONTRIBUTING.md#submitting-a-pull-request) to add your plugin to the list.
|
[Open a Pull Request](https://github.com/semantic-release/semantic-release/blob/master/CONTRIBUTING.md#submitting-a-pull-request) to add your plugin to the list.
|
||||||
|
|
||||||
|
- [semantic-release-slack-bot](https://github.com/juliuscc/semantic-release-slack-bot)
|
||||||
|
- `verifyConditions`: Verify that the environment variable `SLACK_WEBHOOK` has been defined.
|
||||||
|
- `success`: Publish a message about the success to a slack channel.
|
||||||
|
- `fail`: Optionally publish a message about failure to a slack channel.
|
||||||
- [semantic-release-docker](https://github.com/felixfbecker/semantic-release-docker)
|
- [semantic-release-docker](https://github.com/felixfbecker/semantic-release-docker)
|
||||||
- `verifyConditions`: Verify that all needed configuration is present and login to the Docker registry.
|
- `verifyConditions`: Verify that all needed configuration is present and login to the Docker registry.
|
||||||
- `publish`: Tag the image specified by `name` with the new version, push it to Docker Hub and update the latest tag.
|
- `publish`: Tag the image specified by `name` with the new version, push it to Docker Hub and update the latest tag
|
||||||
- [semantic-release-gcr](https://github.com/carlos-cubas/semantic-release-gcr)
|
- [semantic-release-gcr](https://github.com/carlos-cubas/semantic-release-gcr)
|
||||||
- `verifyConditions`: Verify that all needed configuration is present and login to the Docker registry.
|
- `verifyConditions`: Verify that all needed configuration is present and login to the Docker registry
|
||||||
- `publish`: Tag the image specified by `name` with the new version, push it to Docker Hub and update the latest tag.
|
- `publish`: Tag the image specified by `name` with the new version, push it to Docker Hub and update the latest tag
|
||||||
- [semantic-release-vsce](https://github.com/raix/semantic-release-vsce)
|
- [semantic-release-vsce](https://github.com/raix/semantic-release-vsce)
|
||||||
- `verifyConditions`: Verify the presence and the validity of the vsce authentication and release configuration
|
- `verifyConditions`: Verify the presence and the validity of the vsce authentication and release configuration
|
||||||
- `prepare`: Create a `.vsix` for distribution
|
- `prepare`: Create a `.vsix` for distribution
|
||||||
@@ -51,14 +63,31 @@
|
|||||||
- `verifyConditions`: Check the dependencies format against a regexp before a release
|
- `verifyConditions`: Check the dependencies format against a regexp before a release
|
||||||
- [semantic-release-chrome](https://github.com/GabrielDuarteM/semantic-release-chrome)
|
- [semantic-release-chrome](https://github.com/GabrielDuarteM/semantic-release-chrome)
|
||||||
- `verifyConditions`: Verify the presence of the authentication (set via environment variables)
|
- `verifyConditions`: Verify the presence of the authentication (set via environment variables)
|
||||||
- `prepare`: Write the correct version to the manifest.json and creates a zip file of the whole dist folder
|
- `prepare`: Write the correct version to the `manifest.json` and creates a zip file of the whole dist folder
|
||||||
- `publish`: Uploads the generated zip file to the webstore, and publish the item
|
- `publish`: Uploads the generated zip file to the webstore, and publish the item
|
||||||
- [semantic-release-firefox](https://github.com/felixfbecker/semantic-release-firefox)
|
- [semantic-release-firefox](https://github.com/felixfbecker/semantic-release-firefox)
|
||||||
- `verifyConditions`: Verify the presence of the authentication (set via environment variables)
|
- `verifyConditions`: Verify the presence of the authentication (set via environment variables)
|
||||||
- `prepare`: Write the correct version to the manifest.json, creates a xpi file of the dist folder and a zip of the sources
|
- `prepare`: Write the correct version to the `manifest.json`, creates a `xpi` file of the dist folder and a zip of the sources
|
||||||
- `publish`: Submit the generated archives to the webstore for review, and publish the item including release notes
|
- `publish`: Submit the generated archives to the webstore for review, and publish the item including release notes
|
||||||
- [semantic-release-gerrit](https://github.com/pascalMN/semantic-release-gerrit)
|
- [semantic-release-gerrit](https://github.com/pascalMN/semantic-release-gerrit)
|
||||||
- `generateNotes`: Generate release notes with Gerrit reviews URL
|
- `generateNotes`: Generate release notes with Gerrit reviews URL
|
||||||
- [semantic-release-expo](https://github.com/bycedric/semantic-release-expo)
|
- [semantic-release-expo](https://github.com/bycedric/semantic-release-expo)
|
||||||
- `verifyConditions`: Verify Expo manifest(s) are readable and valid.
|
- `verifyConditions`: Verify Expo manifest(s) are readable and valid.
|
||||||
- `prepare`: Update version, ios build number and android version code in the Expo manifest(s).
|
- `prepare`: Update version, ios build number and android version code in the Expo manifest(s).
|
||||||
|
- [maven-semantic-release](https://github.com/conveyal/maven-semantic-release)
|
||||||
|
- `verifyConditions`: Verifies that the `pom.xml` file and other files exist and are setup to allow releases
|
||||||
|
- `verifyRelease`: Checks and warns (does not error by default) if the version numbers found on maven central and within the Git project differ by quite a bit
|
||||||
|
- `prepare`: Changes the version number in the `pom.xml` (or all `pom.xml` files in maven projects with multiple `pom.xml` files) and optionally creates a commit with this version number and pushes it to `master`
|
||||||
|
- `publish`: Runs `mvn deploy` to deploy to maven central and optionally will update to next snapshot version and merge changes to development branch
|
||||||
|
- [semantic-release-ado](https://github.com/lluchmk/semantic-release-ado)
|
||||||
|
- `prepare`: Stores the version number as an Azure DevOps pipeline variable availabe to downstream steps on the job
|
||||||
|
- [gradle-semantic-release](https://github.com/KengoTODA/gradle-semantic-release-plugin)
|
||||||
|
- `verifyConditions`: Verify that project has a Gradle wrapper script, and `build.gradle` contains a task to publish artifacts.
|
||||||
|
- `prepare`: Changes the version number in the `gradle.properties`
|
||||||
|
- `publish`: Triggers Gradle to publish artifacts.
|
||||||
|
- [semantic-release-circleci-orb](https://github.com/matt-oakes/semantic-release-circleci-orb)
|
||||||
|
- `verifyConditions`: Verify the presence of the `CIRCLECI_API_TOKEN` environment variable, `orbName` option, and the `circleci` CLI.
|
||||||
|
- `publish`: Publish the CircleCI orb.
|
||||||
|
- [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.
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
## CI configurations
|
## CI configurations
|
||||||
- [CircleCI 2.0 workflows](circleci-workflows.md)
|
- [CircleCI 2.0 workflows](circleci-workflows.md)
|
||||||
- [Travis CI](travis.md)
|
- [Travis CI](travis.md)
|
||||||
- [Travis CI with build stages](travis-build-stages.md)
|
|
||||||
- [GitLab CI](gitlab-ci.md)
|
- [GitLab CI](gitlab-ci.md)
|
||||||
|
|
||||||
## Git hosted services
|
## Git hosted services
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
The [Authentication](../usage/ci-configuration.md#authentication) environment variables can be configured in [CircleCi Project Settings](https://circleci.com/docs/2.0/env-vars/#adding-environment-variables-in-the-app)..
|
The [Authentication](../usage/ci-configuration.md#authentication) environment variables can be configured in [CircleCi Project Settings](https://circleci.com/docs/2.0/env-vars/#adding-environment-variables-in-the-app)..
|
||||||
|
|
||||||
Alternatively, the default `NPM_TOKEN` and `GH_TOKEN` can be easily [setup with semantic-release-cli](../usage/ci-configuration.md#automatic-setup-with-semantic-release-cli).
|
Alternatively, the default `NPM_TOKEN` and `GH_TOKEN` can be easily [setup with semantic-release-cli](../usage/getting-started.md#getting-started).
|
||||||
|
|
||||||
## Multiple Node jobs configuration
|
## Multiple Node jobs configuration
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ jobs:
|
|||||||
# Make sure only the current user can read the private key
|
# Make sure only the current user can read the private key
|
||||||
- chmod 600 /tmp/git_deploy_key
|
- chmod 600 /tmp/git_deploy_key
|
||||||
# Create a script to return the passphrase environment variable to ssh-add
|
# Create a script to return the passphrase environment variable to ssh-add
|
||||||
- echo 'echo ${SSH_PASSPHRASE}' > /tmp/askpass && chmod +x /tmp/askpass
|
- echo 'echo ${SSL_PASSPHRASE}' > /tmp/askpass && chmod +x /tmp/askpass
|
||||||
# Start the authentication agent
|
# Start the authentication agent
|
||||||
- eval "$(ssh-agent -s)"
|
- eval "$(ssh-agent -s)"
|
||||||
# Add the key to the authentication agent
|
# Add the key to the authentication agent
|
||||||
@@ -158,6 +158,6 @@ Commit the encrypted private key and the `.circleci/config.yml` file to your rep
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git add git_deploy_key.enc .circleci/config.yml
|
$ git add git_deploy_key.enc .circleci/config.yml
|
||||||
$ git commit -m "ci(cicle): Add the encrypted private ssh key"
|
$ git commit -m "ci(circle): Add the encrypted private ssh key"
|
||||||
$ git push
|
$ git push
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
# Using semantic-release with [Travis CI build stages](https://docs.travis-ci.com/user/build-stages)
|
|
||||||
|
|
||||||
## Environment variables
|
|
||||||
|
|
||||||
The [Authentication](../usage/ci-configuration.md#authentication) environment variables can be configured in [Travis Repository Settings](https://docs.travis-ci.com/user/environment-variables/#defining-variables-in-repository-Settings) or with the [travis env set CLI](https://github.com/travis-ci/travis.rb#env).
|
|
||||||
|
|
||||||
Alternatively, the default `NPM_TOKEN` and `GH_TOKEN` can be easily [setup with semantic-release-cli](../usage/ci-configuration.md#automatic-setup-with-semantic-release-cli).
|
|
||||||
|
|
||||||
## Multiple Node jobs configuration
|
|
||||||
|
|
||||||
### `.travis.yml` configuration for multiple Node jobs
|
|
||||||
|
|
||||||
This example is a minimal configuration for **semantic-release** with a build running Node 6 and 8. See [Travis - Customizing the Build](https://docs.travis-ci.com/user/customizing-the-build) for additional configuration options.
|
|
||||||
|
|
||||||
This example creates a `release` [build stage](https://docs.travis-ci.com/user/build-stages) that [runs `semantic-release` only after all test jobs are successful](../usage/ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded).
|
|
||||||
|
|
||||||
It's recommended to run the `semantic-release` command in the [Travis `deploy` step](https://docs.travis-ci.com/user/customizing-the-build/#The-Build-Lifecycle) so if an error occurs the build will fail and Travis will send a notification.
|
|
||||||
|
|
||||||
**Note**: It's not recommended to run the `semantic-release` command in the Travis `script` step as each script in this step will be executed regardless of the outcome of the previous one. See [travis-ci/travis-ci#1066](https://github.com/travis-ci/travis-ci/issues/1066).
|
|
||||||
|
|
||||||
**Advanced configuration**: Running the tests in the `script` step of the `release` stage is not necessary as the previous stage(s) already ran them. To increase speed, the `script` step of the `release` stage can be overwritten to skip the tests. Note that other commands such as build or compilation might still be required.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
language: node_js
|
|
||||||
|
|
||||||
node_js:
|
|
||||||
- 8
|
|
||||||
- 6
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
# Define the release stage that runs semantic-release
|
|
||||||
- stage: release
|
|
||||||
node_js: lts/*
|
|
||||||
# Advanced: optionally overwrite your default `script` step to skip the tests
|
|
||||||
# script: skip
|
|
||||||
deploy:
|
|
||||||
provider: script
|
|
||||||
skip_cleanup: true
|
|
||||||
script:
|
|
||||||
- npx semantic-release
|
|
||||||
```
|
|
||||||
|
|
||||||
### `package.json` configuration for multiple Node jobs
|
|
||||||
|
|
||||||
A `package.json` is required only for [local](../usage/installation.md#local-installation) **semantic-release** installation.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"devDependencies": {
|
|
||||||
"semantic-release": "^15.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Non-JavaScript projects configuration
|
|
||||||
|
|
||||||
For projects that require to be tested with one or multiple version of a Non-JavaScript [language](https://docs.travis-ci.com/user/languages), optionally on multiple [Operating Systems](https://docs.travis-ci.com/user/multi-os).
|
|
||||||
|
|
||||||
This recipe cover the Travis specifics only. See [Non JavaScript projects recipe](../support/FAQ.md#can-i-use-semantic-release-to-publish-non-javascript-packages) for more information on the **semantic-release** configuration.
|
|
||||||
|
|
||||||
### `.travis.yml` configuration for non-JavaScript projects
|
|
||||||
|
|
||||||
This example is a minimal configuration for **semantic-release** with a build running [Go 1.6 and 1.7](https://docs.travis-ci.com/user/languages/go). See [Travis - Customizing the Build](https://docs.travis-ci.com/user/customizing-the-build) for additional configuration options.
|
|
||||||
|
|
||||||
This example creates a `release` [build stage](https://docs.travis-ci.com/user/build-stages) that [runs `semantic-release` only after all test jobs are successful](../usage/ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded).
|
|
||||||
|
|
||||||
It's recommended to run the `semantic-release` command in the [Travis `deploy` step](https://docs.travis-ci.com/user/customizing-the-build/#The-Build-Lifecycle) so if an error occurs the build will fail and Travis will send a notification.
|
|
||||||
|
|
||||||
**Note**: It's not recommended to run the `semantic-release` command in the Travis `script` step as each script in this step will be executed regardless of the outcome of the previous one. See [travis-ci/travis-ci#1066](https://github.com/travis-ci/travis-ci/issues/1066).
|
|
||||||
|
|
||||||
**Advanced configuration**: Running the tests in the `script` step of the `release` stage is not necessary as the previous stage(s) already ran them. To increase speed, the `script` step of the `release` stage can be overwritten to skip the tests. Note that other commands such as build or compilation might still be required.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.6
|
|
||||||
- 1.7
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
# Define the release stage that runs semantic-release
|
|
||||||
- stage: release
|
|
||||||
# Advanced: optionally overwrite your default `script` step to skip the tests
|
|
||||||
# script:
|
|
||||||
# - make
|
|
||||||
deploy:
|
|
||||||
provider: script
|
|
||||||
skip_cleanup: true
|
|
||||||
script:
|
|
||||||
# Use nvm to install and use the Node LTS version (nvm is installed on all Travis images)
|
|
||||||
- nvm install lts/*
|
|
||||||
- npx semantic-release
|
|
||||||
```
|
|
||||||
+38
-72
@@ -4,62 +4,22 @@
|
|||||||
|
|
||||||
The [Authentication](../usage/ci-configuration.md#authentication) environment variables can be configured in [Travis Repository Settings](https://docs.travis-ci.com/user/environment-variables/#defining-variables-in-repository-Settings) or with the [travis env set CLI](https://github.com/travis-ci/travis.rb#env).
|
The [Authentication](../usage/ci-configuration.md#authentication) environment variables can be configured in [Travis Repository Settings](https://docs.travis-ci.com/user/environment-variables/#defining-variables-in-repository-Settings) or with the [travis env set CLI](https://github.com/travis-ci/travis.rb#env).
|
||||||
|
|
||||||
Alternatively, the default `NPM_TOKEN` and `GH_TOKEN` can be easily [setup with semantic-release-cli](../usage/ci-configuration.md#automatic-setup-with-semantic-release-cli).
|
Alternatively, the default `NPM_TOKEN` and `GH_TOKEN` can be easily [setup with semantic-release-cli](../usage/getting-started.md#getting-started).
|
||||||
|
|
||||||
## Single Node job configuration
|
## Node.js projects configuration
|
||||||
|
|
||||||
For projects that require to be tested only with a single [Node version](https://docs.travis-ci.com/user/getting-started/#Selecting-a-different-programming-language) on [one Operating System](https://docs.travis-ci.com/user/getting-started/#Selecting-infrastructure-(optional)).
|
### `.travis.yml` configuration for multiple Node.js jobs
|
||||||
|
|
||||||
**Note**: [Node 8 is the minimal version required](../support/FAQ.md#why-does-semantic-release-require-node-version--83).
|
|
||||||
|
|
||||||
### `.travis.yml` configuration for single Node job
|
|
||||||
|
|
||||||
This example is a minimal configuration for semantic-release with a build running Node 8 on Linux. See [Travis - Customizing the Build](https://docs.travis-ci.com/user/customizing-the-build) for additional configuration options.
|
|
||||||
|
|
||||||
It's recommended to run the `semantic-release` command in the [Travis `deploy` step](https://docs.travis-ci.com/user/customizing-the-build/#The-Build-Lifecycle) so if an error occurs the build will fail and Travis will send a notification.
|
|
||||||
|
|
||||||
**Note**: It's not recommended to run the `semantic-release` command in the Travis `script` step as each script in this step will be executed regardless of the outcome of the previous one. See [travis-ci/travis-ci#1066](https://github.com/travis-ci/travis-ci/issues/1066).
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
language: node_js
|
|
||||||
|
|
||||||
node_js: 8
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
provider: script
|
|
||||||
skip_cleanup: true
|
|
||||||
script:
|
|
||||||
- npx semantic-release
|
|
||||||
```
|
|
||||||
|
|
||||||
### `package.json` configuration for single Node job
|
|
||||||
|
|
||||||
A `package.json` is required only for [local](../usage/installation.md#local-installation) **semantic-release** installation.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"devDependencies": {
|
|
||||||
"semantic-release": "^11.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Multiple Node jobs configuration
|
|
||||||
|
|
||||||
For projects that require to be tested with multiple [Node versions](https://docs.travis-ci.com/user/languages/javascript-with-nodejs/#Specifying-Node.js-versions) and/or on multiple [Operating Systems](https://docs.travis-ci.com/user/multi-os).
|
|
||||||
|
|
||||||
**Note**: At least one job must run a [Node >= 8 version](../support/FAQ.md#why-does-semantic-release-require-node-version--83).
|
|
||||||
|
|
||||||
### `.travis.yml` configuration for multiple Node jobs
|
|
||||||
|
|
||||||
This example is a minimal configuration for **semantic-release** with a build running Node 6 and 8. See [Travis - Customizing the Build](https://docs.travis-ci.com/user/customizing-the-build) for additional configuration options.
|
This example is a minimal configuration for **semantic-release** with a build running Node 6 and 8. See [Travis - Customizing the Build](https://docs.travis-ci.com/user/customizing-the-build) for additional configuration options.
|
||||||
|
|
||||||
This example uses [`travis-deploy-once`](https://github.com/semantic-release/travis-deploy-once) in order to [Run `semantic-release` only after all tests succeeded](../usage/ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded). Alternatively you can use [Travis CI Build Stages recipe](travis-build-stages.md).
|
This example creates a `release` [build stage](https://docs.travis-ci.com/user/build-stages) that [runs `semantic-release` only after all test jobs are successful](../usage/ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded).
|
||||||
|
|
||||||
It's recommended to run the `semantic-release` command in the [Travis `deploy` step](https://docs.travis-ci.com/user/customizing-the-build/#The-Build-Lifecycle) so if an error occurs the build will fail and Travis will send a notification.
|
It's recommended to run the `semantic-release` command in the [Travis `deploy` step](https://docs.travis-ci.com/user/customizing-the-build/#The-Build-Lifecycle) so if an error occurs the build will fail and Travis will send a notification.
|
||||||
|
|
||||||
**Note**: It's not recommended to run the `semantic-release` command in the Travis `script` step as each script in this step will be executed regardless of the outcome of the previous one. See [travis-ci/travis-ci#1066](https://github.com/travis-ci/travis-ci/issues/1066).
|
**Note**: It's not recommended to run the `semantic-release` command in the Travis `script` step as each script in this step will be executed regardless of the outcome of the previous one. See [travis-ci/travis-ci#1066](https://github.com/travis-ci/travis-ci/issues/1066).
|
||||||
|
|
||||||
|
**Advanced configuration**: Running the tests in the `script` step of the `release` stage is not necessary as the previous stage(s) already ran them. To increase speed, the `script` step of the `release` stage can be overwritten to skip the tests. Note that other commands such as build or compilation might still be required.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
language: node_js
|
language: node_js
|
||||||
|
|
||||||
@@ -67,15 +27,20 @@ node_js:
|
|||||||
- 8
|
- 8
|
||||||
- 6
|
- 6
|
||||||
|
|
||||||
deploy:
|
jobs:
|
||||||
provider: script
|
include:
|
||||||
skip_cleanup: true
|
# Define the release stage that runs semantic-release
|
||||||
script:
|
- stage: release
|
||||||
- npx travis-deploy-once "npx semantic-release"
|
node_js: lts/*
|
||||||
|
# Advanced: optionally overwrite your default `script` step to skip the tests
|
||||||
|
# script: skip
|
||||||
|
deploy:
|
||||||
|
provider: script
|
||||||
|
skip_cleanup: true
|
||||||
|
script:
|
||||||
|
- npx semantic-release
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: See the `travis-deploy-once` [`pro`](https://github.com/semantic-release/travis-deploy-once#-p---pro) and [`travis-url`](https://github.com/semantic-release/travis-deploy-once#-u---travis-url) options for using with [Travis Pro](https://docs.travis-ci.com/user/travis-pro) and [Travis Enterprise](https://enterprise.travis-ci.com).
|
|
||||||
|
|
||||||
### `package.json` configuration for multiple Node jobs
|
### `package.json` configuration for multiple Node jobs
|
||||||
|
|
||||||
A `package.json` is required only for [local](../usage/installation.md#local-installation) **semantic-release** installation.
|
A `package.json` is required only for [local](../usage/installation.md#local-installation) **semantic-release** installation.
|
||||||
@@ -83,13 +48,12 @@ A `package.json` is required only for [local](../usage/installation.md#local-ins
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"semantic-release": "^15.0.0",
|
"semantic-release": "^15.0.0"
|
||||||
"travis-deploy-once": "^5.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Non-JavaScript projects configuration
|
## Non-Node.js projects configuration
|
||||||
|
|
||||||
For projects that require to be tested with one or multiple version of a Non-JavaScript [language](https://docs.travis-ci.com/user/languages), optionally on multiple [Operating Systems](https://docs.travis-ci.com/user/multi-os).
|
For projects that require to be tested with one or multiple version of a Non-JavaScript [language](https://docs.travis-ci.com/user/languages), optionally on multiple [Operating Systems](https://docs.travis-ci.com/user/multi-os).
|
||||||
|
|
||||||
@@ -97,14 +61,16 @@ This recipe cover the Travis specifics only. See [Non JavaScript projects recipe
|
|||||||
|
|
||||||
### `.travis.yml` configuration for non-JavaScript projects
|
### `.travis.yml` configuration for non-JavaScript projects
|
||||||
|
|
||||||
This example is a minimal configuration for **semantic-release** with a build running [Go 1.6 and 1.7](https://docs.travis-ci.com/user/languages/go) on Linux and OSX. See [Travis - Customizing the Build](https://docs.travis-ci.com/user/customizing-the-build) for additional configuration options.
|
This example is a minimal configuration for **semantic-release** with a build running [Go 1.6 and 1.7](https://docs.travis-ci.com/user/languages/go). See [Travis - Customizing the Build](https://docs.travis-ci.com/user/customizing-the-build) for additional configuration options.
|
||||||
|
|
||||||
This example uses [`travis-deploy-once`](https://github.com/semantic-release/travis-deploy-once) in order to [run `semantic-release` only after all tests succeeded](../usage/ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded). Alternatively you can use [Travis CI Build Stages recipe](travis-build-stages.md).
|
This example creates a `release` [build stage](https://docs.travis-ci.com/user/build-stages) that [runs `semantic-release` only after all test jobs are successful](../usage/ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded).
|
||||||
|
|
||||||
It's recommended to run the `semantic-release` command in the [Travis `deploy` step](https://docs.travis-ci.com/user/customizing-the-build/#The-Build-Lifecycle) so if an error occurs the build will fail and Travis will send a notification.
|
It's recommended to run the `semantic-release` command in the [Travis `deploy` step](https://docs.travis-ci.com/user/customizing-the-build/#The-Build-Lifecycle) so if an error occurs the build will fail and Travis will send a notification.
|
||||||
|
|
||||||
**Note**: It's not recommended to run the `semantic-release` command in the Travis `script` step as each script in this step will be executed regardless of the outcome of the previous one. See [travis-ci/travis-ci#1066](https://github.com/travis-ci/travis-ci/issues/1066).
|
**Note**: It's not recommended to run the `semantic-release` command in the Travis `script` step as each script in this step will be executed regardless of the outcome of the previous one. See [travis-ci/travis-ci#1066](https://github.com/travis-ci/travis-ci/issues/1066).
|
||||||
|
|
||||||
|
**Advanced configuration**: Running the tests in the `script` step of the `release` stage is not necessary as the previous stage(s) already ran them. To increase speed, the `script` step of the `release` stage can be overwritten to skip the tests. Note that other commands such as build or compilation might still be required.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
@@ -112,18 +78,18 @@ go:
|
|||||||
- 1.6
|
- 1.6
|
||||||
- 1.7
|
- 1.7
|
||||||
|
|
||||||
os:
|
jobs:
|
||||||
- linux
|
include:
|
||||||
- osx
|
# Define the release stage that runs semantic-release
|
||||||
|
- stage: release
|
||||||
deploy:
|
# Advanced: optionally overwrite your default `script` step to skip the tests
|
||||||
provider: script
|
# script:
|
||||||
skip_cleanup: true
|
# - make
|
||||||
script:
|
deploy:
|
||||||
# Use nvm to install and use the Node LTS version (nvm is installed on all Travis images)
|
provider: script
|
||||||
- nvm install lts/*
|
skip_cleanup: true
|
||||||
# Run semantic-release only on one job, after all other are successful
|
script:
|
||||||
- npx travis-deploy-once "npx semantic-release"
|
# Use nvm to install and use the Node LTS version (nvm is installed on all Travis images)
|
||||||
|
- nvm install lts/*
|
||||||
|
- npx semantic-release
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: See the `travis-deploy-once` [`pro`](https://github.com/semantic-release/travis-deploy-once#-p---pro) and [`travis-url`](https://github.com/semantic-release/travis-deploy-once#-u---travis-url) options for using with [Travis Pro](https://docs.travis-ci.com/user/travis-pro) and [Travis Enterprise](https://enterprise.travis-ci.com).
|
|
||||||
|
|||||||
+1
-1
@@ -145,7 +145,7 @@ If you have introduced a breaking bug in a release you have 2 options:
|
|||||||
|
|
||||||
In both cases **semantic-release** will publish a new release, so your package users' will get the fixed/reverted version.
|
In both cases **semantic-release** will publish a new release, so your package users' will get the fixed/reverted version.
|
||||||
|
|
||||||
Depending on the package manager you are using, you might be able to un-publish or deprecate a release, in order to prevent users to download it by accident. For example npm allows you to [un-publish](https://docs.npmjs.com/cli/unpublish) in [next 72 hours](https://www.npmjs.com/policies/unpublish) after releasing or to [deprecate](https://docs.npmjs.com/cli/deprecate) a release.
|
Depending on the package manager you are using, you might be able to un-publish or deprecate a release, in order to prevent users from downloading it by accident. For example npm allows you to [un-publish](https://docs.npmjs.com/cli/unpublish) [within 72 hours](https://www.npmjs.com/policies/unpublish) after releasing. You may also [deprecate](https://docs.npmjs.com/cli/deprecate) a release if you would rather avoid un-publishing.
|
||||||
|
|
||||||
In any case **do not remove the Git tag associated with the buggy version**, otherwise **semantic-release** will later try to republish that version. Publishing a version after un-publishing is not supported by most package managers.
|
In any case **do not remove the Git tag associated with the buggy version**, otherwise **semantic-release** will later try to republish that version. Publishing a version after un-publishing is not supported by most package managers.
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ npm ERR! You do not have permission to publish "<package-name>". Are you logged
|
|||||||
|
|
||||||
This is most likely related to a misconfiguration of the [npm registry authentication](https://github.com/semantic-release/npm#npm-registry-authentication) or to your user [missing permission](https://docs.npmjs.com/cli/team) for publishing.
|
This is most likely related to a misconfiguration of the [npm registry authentication](https://github.com/semantic-release/npm#npm-registry-authentication) or to your user [missing permission](https://docs.npmjs.com/cli/team) for publishing.
|
||||||
|
|
||||||
It might also happen if the package name you are trying to publish already exists (in such case npm consider you are trying to publish a new version of a package that is not yours, hence the permission error).
|
It might also happen if the package name you are trying to publish already exists (in the case of npm, you may be trying to publish a new version of a package that is not yours, hence the permission error).
|
||||||
|
|
||||||
To verify if your package name is available you can use [npm-name-cli](https://github.com/sindresorhus/npm-name-cli):
|
To verify if your package name is available you can use [npm-name-cli](https://github.com/sindresorhus/npm-name-cli):
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Run `semantic-release` only after all tests succeeded
|
## Run `semantic-release` only after all tests succeeded
|
||||||
|
|
||||||
The `semantic-release` command must be executed only after all the tests in the CI build pass. If the build runs multiple jobs (for example to test on multiple Operating Systems or Node versions) the CI has to be configured to guarantee that the `semantic-release` command is executed only after all jobs are successful. This can be achieved with [Travis Build Stages](https://docs.travis-ci.com/user/build-stages), [CircleCI Workflows](https://circleci.com/docs/2.0/workflows), [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), [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) or specific tools like [`travis-deploy-once`](https://github.com/semantic-release/travis-deploy-once).
|
The `semantic-release` command must be executed only after all the tests in the CI build pass. If the build runs multiple jobs (for example to test on multiple Operating Systems or Node versions) the CI has to be configured to guarantee that the `semantic-release` command is executed only after all jobs are successful. This can be achieved with [Travis Build Stages](https://docs.travis-ci.com/user/build-stages), [CircleCI Workflows](https://circleci.com/docs/2.0/workflows), [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), [Codefresh Pipelines](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines), [Wercker Workflows](http://devcenter.wercker.com/docs/workflows) or [GoCD Pipelines](https://docs.gocd.org/current/introduction/concepts_in_go.html#pipeline).
|
||||||
|
|
||||||
See [CI configuration recipes](../recipes/README.md#ci-configurations) for more details.
|
See [CI configuration recipes](../recipes/README.md#ci-configurations) for more details.
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ Most **semantic-release** [plugins](plugins.md) require setting up authenticatio
|
|||||||
| `NPM_TOKEN` | npm token created via [npm token create](https://docs.npmjs.com/getting-started/working_with_tokens#how-to-create-new-tokens).<br/>**Note**: Only the `auth-only` [level of npm two-factor authentication](https://docs.npmjs.com/getting-started/using-two-factor-authentication#levels-of-authentication) is supported. |
|
| `NPM_TOKEN` | npm token created via [npm token create](https://docs.npmjs.com/getting-started/working_with_tokens#how-to-create-new-tokens).<br/>**Note**: Only the `auth-only` [level of npm two-factor authentication](https://docs.npmjs.com/getting-started/using-two-factor-authentication#levels-of-authentication) is supported. |
|
||||||
| `GH_TOKEN` | GitHub authentication token.<br/>**Note**: Only the [personal token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line) authentication is supported. |
|
| `GH_TOKEN` | GitHub authentication token.<br/>**Note**: Only the [personal token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line) authentication is supported. |
|
||||||
|
|
||||||
See each plugin documentation for the environment variables to set up.
|
See each plugin's documentation for the environment variables required.
|
||||||
|
|
||||||
The authentication token/credentials have to be made available in the CI service via environment variables.
|
The authentication token/credentials have to be made available in the CI service via environment variables.
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ CLI argument: `--debug`
|
|||||||
|
|
||||||
Output debugging information. This can also be enabled by setting the `DEBUG` environment variable to `semantic-release:*`.
|
Output debugging information. This can also be enabled by setting the `DEBUG` environment variable to `semantic-release:*`.
|
||||||
|
|
||||||
|
**Note**: The `debug` is used only supported via CLI argument. To enable debug mode from the [JS API](../developer-guide/js-api.md#javascript-api) use `require('debug').enable('semantic-release:*')`.
|
||||||
|
|
||||||
## Git environment variables
|
## Git environment variables
|
||||||
|
|
||||||
| Variable | Description | Default |
|
| Variable | Description | Default |
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Getting started
|
# Getting started
|
||||||
|
|
||||||
In order to use **semantic-release** you must follows this steps:
|
In order to use **semantic-release** you must follow these steps:
|
||||||
- [Install](./installation.md#installation) **semantic-release** in your project
|
- [Install](./installation.md#installation) **semantic-release** in your project
|
||||||
- Configure your Continuous Integration service to [run **semantic-release**](./ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded)
|
- Configure your Continuous Integration service to [run **semantic-release**](./ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded)
|
||||||
- Configure your Git repository and package manager repository [authentication](ci-configuration.md#authentication) in your Continuous Integration service
|
- Configure your Git repository and package manager repository [authentication](ci-configuration.md#authentication) in your Continuous Integration service
|
||||||
@@ -19,4 +19,4 @@ semantic-release-cli setup
|
|||||||
|
|
||||||
See the [semantic-release-cli](https://github.com/semantic-release/cli#what-it-does) documentation for more details.
|
See the [semantic-release-cli](https://github.com/semantic-release/cli#what-it-does) documentation for more details.
|
||||||
|
|
||||||
**Note**: only a limited number of options, CI services and plugins is currently supported by `semantic-release-cli`.
|
**Note**: only a limited number of options, CI services and plugins are currently supported by `semantic-release-cli`.
|
||||||
|
|||||||
+17
-6
@@ -17,15 +17,26 @@ A plugin is a npm module that can implement one or more of the following steps:
|
|||||||
|
|
||||||
**Note:** If no plugin with a `analyzeCommits` step is defined `@semantic-release/commit-analyzer` will be used.
|
**Note:** If no plugin with a `analyzeCommits` step is defined `@semantic-release/commit-analyzer` will be used.
|
||||||
|
|
||||||
See [available plugins](../extending/plugins-list.md).
|
## Plugins installation
|
||||||
|
|
||||||
|
These five plugins are already part of **semantic-release** and don't have to be installed separately:
|
||||||
|
```
|
||||||
|
"@semantic-release/commit-analyzer"
|
||||||
|
"@semantic-release/error"
|
||||||
|
"@semantic-release/github"
|
||||||
|
"@semantic-release/npm"
|
||||||
|
"@semantic-release/release-notes-generator"
|
||||||
|
```
|
||||||
|
|
||||||
|
[Additional plugins](../extending/plugins-list.md) have to be installed via npm:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install @semantic-release/git @semantic-release/changelog -D
|
||||||
|
```
|
||||||
|
|
||||||
## Plugins configuration
|
## Plugins configuration
|
||||||
|
|
||||||
Each plugin must be installed and configured with the [`plugins` options](./configuration.md#plugins) by specifying the list of plugins by npm module name.
|
Each plugin must be configured with the [`plugins` options](./configuration.md#plugins) by specifying the list of plugins by npm module name.
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm install @semantic-release/commit-analyzer @semantic-release/release-notes-generator @semantic-release/npm -D
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Shareable configurations
|
# Shareable configurations
|
||||||
|
|
||||||
A sharable configuration is an [npm](https://www.npmjs.com/) package that exports a **semantic-release** configuration object. It allows for use of the same configuration across several projects.
|
A shareable configuration is an [npm](https://www.npmjs.com/) package that exports a **semantic-release** configuration object. It allows for use of the same configuration across several projects.
|
||||||
|
|
||||||
The shareable configurations to use can be set with the [extends](configuration.md#extends) option.
|
The shareable configurations to use can be set with the [extends](configuration.md#extends) option.
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ async function run(context, plugins) {
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger[options.dryRun ? 'warn' : 'success'](
|
logger[options.dryRun ? 'warn' : 'success'](
|
||||||
`Run automated release from branch ${ciBranch}${options.dryRun ? ' in dry-run mode' : ''}`
|
`Run automated release from branch ${ciBranch}${options.dryRun ? ' in dry-run mode' : ''}`
|
||||||
);
|
);
|
||||||
@@ -70,6 +71,7 @@ async function run(context, plugins) {
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -92,6 +94,7 @@ async function run(context, plugins) {
|
|||||||
logger.log('There are no relevant changes, so no new version is released.');
|
logger.log('There are no relevant changes, so no new version is released.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.nextRelease = nextRelease;
|
context.nextRelease = nextRelease;
|
||||||
nextRelease.version = getNextVersion(context);
|
nextRelease.version = getNextVersion(context);
|
||||||
nextRelease.gitTag = template(options.tagFormat)({version: nextRelease.version});
|
nextRelease.gitTag = template(options.tagFormat)({version: nextRelease.version});
|
||||||
@@ -107,7 +110,7 @@ async function run(context, plugins) {
|
|||||||
} else {
|
} else {
|
||||||
// Create the tag before calling the publish plugins as some require the tag to exists
|
// Create the tag before calling the publish plugins as some require the tag to exists
|
||||||
await tag(nextRelease.gitTag, {cwd, env});
|
await tag(nextRelease.gitTag, {cwd, env});
|
||||||
await push(options.repositoryUrl, options.branch, {cwd, env});
|
await push(options.repositoryUrl, {cwd, env});
|
||||||
logger.success(`Created tag ${nextRelease.gitTag}`);
|
logger.success(`Created tag ${nextRelease.gitTag}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
const url = require('url');
|
|
||||||
const {inspect} = require('util');
|
const {inspect} = require('util');
|
||||||
const {toLower, isString} = require('lodash');
|
const {toLower, isString} = require('lodash');
|
||||||
const pkg = require('../../package.json');
|
const pkg = require('../../package.json');
|
||||||
const {RELEASE_TYPE} = require('./constants');
|
const {RELEASE_TYPE} = require('./constants');
|
||||||
|
|
||||||
const homepage = url.format({...url.parse(pkg.homepage), hash: null});
|
const [homepage] = pkg.homepage.split('#');
|
||||||
const stringify = obj => (isString(obj) ? obj : inspect(obj, {breakLength: Infinity, depth: 2, maxArrayLength: 5}));
|
const stringify = obj => (isString(obj) ? obj : inspect(obj, {breakLength: Infinity, depth: 2, maxArrayLength: 5}));
|
||||||
const linkify = file => `${homepage}/blob/master/${file}`;
|
const linkify = file => `${homepage}/blob/master/${file}`;
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ module.exports = {
|
|||||||
// Regenerate the release notes
|
// Regenerate the release notes
|
||||||
context.nextRelease.notes = await generateNotes(context);
|
context.nextRelease.notes = await generateNotes(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the next prepare plugin with the updated `nextRelease`
|
// Call the next prepare plugin with the updated `nextRelease`
|
||||||
return context;
|
return context;
|
||||||
},
|
},
|
||||||
@@ -71,8 +72,8 @@ module.exports = {
|
|||||||
pipelineConfig: () => ({
|
pipelineConfig: () => ({
|
||||||
// Add `nextRelease` and plugin properties to published release
|
// Add `nextRelease` and plugin properties to published release
|
||||||
transform: (release, step, {nextRelease}) => ({
|
transform: (release, step, {nextRelease}) => ({
|
||||||
...(isPlainObject(release) ? release : {}),
|
...(release === false ? {} : nextRelease),
|
||||||
...nextRelease,
|
...release,
|
||||||
...step,
|
...step,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
|||||||
+5
-1
@@ -27,6 +27,10 @@ module.exports = async (context, opts) => {
|
|||||||
|
|
||||||
// Merge config file options and CLI/API options
|
// Merge config file options and CLI/API options
|
||||||
let options = {...config, ...opts};
|
let options = {...config, ...opts};
|
||||||
|
if (options.ci === false) {
|
||||||
|
options.noCi = true;
|
||||||
|
}
|
||||||
|
|
||||||
const pluginsPath = {};
|
const pluginsPath = {};
|
||||||
let extendPaths;
|
let extendPaths;
|
||||||
({extends: extendPaths, ...options} = options);
|
({extends: extendPaths, ...options} = options);
|
||||||
@@ -81,6 +85,6 @@ module.exports = async (context, opts) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function pkgRepoUrl(opts) {
|
async function pkgRepoUrl(opts) {
|
||||||
const {pkg} = await readPkgUp(opts);
|
const {package: pkg} = (await readPkgUp(opts)) || {};
|
||||||
return pkg && (isPlainObject(pkg.repository) ? pkg.repository.url : pkg.repository);
|
return pkg && (isPlainObject(pkg.repository) ? pkg.repository.url : pkg.repository);
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-12
@@ -1,18 +1,8 @@
|
|||||||
const {parse, format} = require('url');
|
const {parse, format} = require('url'); // eslint-disable-line node/no-deprecated-api
|
||||||
const {isNil} = require('lodash');
|
const {isNil} = require('lodash');
|
||||||
const hostedGitInfo = require('hosted-git-info');
|
const hostedGitInfo = require('hosted-git-info');
|
||||||
const {verifyAuth} = require('./git');
|
const {verifyAuth} = require('./git');
|
||||||
|
|
||||||
const GIT_TOKENS = {
|
|
||||||
GIT_CREDENTIALS: undefined,
|
|
||||||
GH_TOKEN: undefined,
|
|
||||||
GITHUB_TOKEN: undefined,
|
|
||||||
GL_TOKEN: 'gitlab-ci-token:',
|
|
||||||
GITLAB_TOKEN: 'gitlab-ci-token:',
|
|
||||||
BB_TOKEN: 'x-token-auth:',
|
|
||||||
BITBUCKET_TOKEN: 'x-token-auth:',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the the git repository URL to use to push, either:
|
* Determine the the git repository URL to use to push, either:
|
||||||
* - The `repositoryUrl` as is if allowed to push
|
* - The `repositoryUrl` as is if allowed to push
|
||||||
@@ -25,6 +15,18 @@ const GIT_TOKENS = {
|
|||||||
* @return {String} The formatted Git repository URL.
|
* @return {String} The formatted Git repository URL.
|
||||||
*/
|
*/
|
||||||
module.exports = async ({cwd, env, options: {repositoryUrl, branch}}) => {
|
module.exports = async ({cwd, env, options: {repositoryUrl, branch}}) => {
|
||||||
|
const GIT_TOKENS = {
|
||||||
|
GIT_CREDENTIALS: undefined,
|
||||||
|
GH_TOKEN: undefined,
|
||||||
|
// GitHub Actions require the "x-access-token:" prefix for git access
|
||||||
|
// https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#http-based-git-access-by-an-installation
|
||||||
|
GITHUB_TOKEN: isNil(env.GITHUB_ACTION) ? undefined : 'x-access-token:',
|
||||||
|
GL_TOKEN: 'gitlab-ci-token:',
|
||||||
|
GITLAB_TOKEN: 'gitlab-ci-token:',
|
||||||
|
BB_TOKEN: 'x-token-auth:',
|
||||||
|
BITBUCKET_TOKEN: 'x-token-auth:',
|
||||||
|
};
|
||||||
|
|
||||||
const info = hostedGitInfo.fromUrl(repositoryUrl, {noGitPlus: true});
|
const info = hostedGitInfo.fromUrl(repositoryUrl, {noGitPlus: true});
|
||||||
const {protocol, ...parsed} = parse(repositoryUrl);
|
const {protocol, ...parsed} = parse(repositoryUrl);
|
||||||
|
|
||||||
@@ -43,8 +45,15 @@ module.exports = async ({cwd, env, options: {repositoryUrl, branch}}) => {
|
|||||||
const envVar = Object.keys(GIT_TOKENS).find(envVar => !isNil(env[envVar]));
|
const envVar = Object.keys(GIT_TOKENS).find(envVar => !isNil(env[envVar]));
|
||||||
const gitCredentials = `${GIT_TOKENS[envVar] || ''}${env[envVar] || ''}`;
|
const gitCredentials = `${GIT_TOKENS[envVar] || ''}${env[envVar] || ''}`;
|
||||||
|
|
||||||
|
console.log(`-------- envVar -------- `);
|
||||||
|
console.log(envVar);
|
||||||
|
console.log(`-------- GIT_TOKENS[envVar] -------- `);
|
||||||
|
console.log(GIT_TOKENS[envVar]);
|
||||||
|
console.log(`-------- env[envVar].substr(5) -------- `);
|
||||||
|
console.log((env[envVar] || '').substr(5));
|
||||||
|
|
||||||
if (gitCredentials) {
|
if (gitCredentials) {
|
||||||
// If credentials are set via anvironment variables, convert the URL to http/https and add basic auth, otherwise return `repositoryUrl` as is
|
// If credentials are set via environment variables, convert the URL to http/https and add basic auth, otherwise return `repositoryUrl` as is
|
||||||
const [match, auth, host, path] = /^(?!.+:\/\/)(?:(.*)@)?(.*?):(.*)$/.exec(repositoryUrl) || [];
|
const [match, auth, host, path] = /^(?!.+:\/\/)(?:(.*)@)?(.*?):(.*)$/.exec(repositoryUrl) || [];
|
||||||
return format({
|
return format({
|
||||||
...parse(match ? `ssh://${auth ? `${auth}@` : ''}${host}/${path}` : repositoryUrl),
|
...parse(match ? `ssh://${auth ? `${auth}@` : ''}${host}/${path}` : repositoryUrl),
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ module.exports = async ({cwd, env, options: {tagFormat}, logger}) => {
|
|||||||
// Generate a regex to parse tags formatted with `tagFormat`
|
// Generate a regex to parse tags formatted with `tagFormat`
|
||||||
// by replacing the `version` variable in the template by `(.+)`.
|
// by replacing the `version` variable in the template by `(.+)`.
|
||||||
// The `tagFormat` is compiled with space as the `version` as it's an invalid tag character,
|
// The `tagFormat` is compiled with space as the `version` as it's an invalid tag character,
|
||||||
// so it's guaranteed to no be present in the `tagFormat`.
|
// so it's guaranteed to not be present in the `tagFormat`.
|
||||||
const tagRegexp = `^${escapeRegExp(template(tagFormat)({version: ' '})).replace(' ', '(.+)')}`;
|
const tagRegexp = `^${escapeRegExp(template(tagFormat)({version: ' '})).replace(' ', '(.+)')}`;
|
||||||
const tags = (await getTags({cwd, env}))
|
const tags = (await getTags({cwd, env}))
|
||||||
.map(tag => ({gitTag: tag, version: (tag.match(tagRegexp) || new Array(2))[1]}))
|
.map(tag => ({gitTag: tag, version: (tag.match(tagRegexp) || new Array(2))[1]}))
|
||||||
|
|||||||
+1
-2
@@ -143,12 +143,11 @@ async function tag(tagName, execaOpts) {
|
|||||||
* Push to the remote repository.
|
* Push to the remote repository.
|
||||||
*
|
*
|
||||||
* @param {String} repositoryUrl The remote repository URL.
|
* @param {String} repositoryUrl The remote repository URL.
|
||||||
* @param {String} branch The branch to push.
|
|
||||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||||
*
|
*
|
||||||
* @throws {Error} if the push failed.
|
* @throws {Error} if the push failed.
|
||||||
*/
|
*/
|
||||||
async function push(repositoryUrl, branch, execaOpts) {
|
async function push(repositoryUrl, execaOpts) {
|
||||||
await execa('git', ['push', '--tags', repositoryUrl], execaOpts);
|
await execa('git', ['push', '--tags', repositoryUrl], execaOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,10 +57,12 @@ module.exports = (context, pluginsPath) => {
|
|||||||
plugin ? [plugin[0], Object.assign(plugin[1], options[type])] : plugin
|
plugin ? [plugin[0], Object.assign(plugin[1], options[type])] : plugin
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validateStep({required}, options[type])) {
|
if (!validateStep({required}, options[type])) {
|
||||||
errors.push(getError('EPLUGINCONF', {type, required, pluginConf: options[type]}));
|
errors.push(getError('EPLUGINCONF', {type, required, pluginConf: options[type]}));
|
||||||
return pluginsConf;
|
return pluginsConf;
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginOpts = options[type];
|
pluginOpts = options[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,11 @@ module.exports = (context, type, pluginOpt, pluginsPath) => {
|
|||||||
if (outputValidator && !outputValidator(result)) {
|
if (outputValidator && !outputValidator(result)) {
|
||||||
throw getError(`E${type.toUpperCase()}OUTPUT`, {result, pluginName});
|
throw getError(`E${type.toUpperCase()}OUTPUT`, {result, pluginName});
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.success(`Completed step "${type}" of plugin "${pluginName}"`);
|
logger.success(`Completed step "${type}" of plugin "${pluginName}"`);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.warn(`Skip step "${type}" of plugin "${pluginName}" in dry-run mode`);
|
logger.warn(`Skip step "${type}" of plugin "${pluginName}" in dry-run mode`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`Failed step "${type}" of plugin "${pluginName}"`);
|
logger.error(`Failed step "${type}" of plugin "${pluginName}"`);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const AggregateError = require('aggregate-error');
|
|||||||
const {extractErrors} = require('../utils');
|
const {extractErrors} = require('../utils');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Function that execute a list of function sequencially. If at least one Function ins the pipeline throw an Error or rejects, the pipeline function rejects as well.
|
* A Function that execute a list of function sequencially. If at least one Function ins the pipeline throws an Error or rejects, the pipeline function rejects as well.
|
||||||
*
|
*
|
||||||
* @typedef {Function} Pipeline
|
* @typedef {Function} Pipeline
|
||||||
* @param {Any} input Argument to pass to the first step in the pipeline.
|
* @param {Any} input Argument to pass to the first step in the pipeline.
|
||||||
@@ -44,6 +44,7 @@ module.exports = (steps, {settleAll = false, getNextInput = identity, transform
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare input for the next step, passing the input of the last iteration (or initial parameter for the first iteration) and the result of the current one
|
// Prepare input for the next step, passing the input of the last iteration (or initial parameter for the first iteration) and the result of the current one
|
||||||
return getNextInput(lastInput, result);
|
return getNextInput(lastInput, result);
|
||||||
},
|
},
|
||||||
@@ -52,5 +53,6 @@ module.exports = (steps, {settleAll = false, getNextInput = identity, transform
|
|||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
throw new AggregateError(errors);
|
throw new AggregateError(errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ const validateSteps = conf => {
|
|||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
conf = castArray(conf);
|
conf = castArray(conf);
|
||||||
|
|
||||||
if (conf.length !== 1) {
|
if (conf.length !== 1) {
|
||||||
@@ -39,6 +40,7 @@ function validateStep({required}, conf) {
|
|||||||
if (required) {
|
if (required) {
|
||||||
return conf.length >= 1 && validateSteps(conf);
|
return conf.length >= 1 && validateSteps(conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return conf.length === 0 || validateSteps(conf);
|
return conf.length === 0 || validateSteps(conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +61,7 @@ function parseConfig(plugin) {
|
|||||||
} else {
|
} else {
|
||||||
path = plugin;
|
path = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [path, config || {}];
|
return [path, config || {}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 117 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 65 KiB |
+20
-20
@@ -24,49 +24,49 @@
|
|||||||
"@semantic-release/github": "^5.1.0",
|
"@semantic-release/github": "^5.1.0",
|
||||||
"@semantic-release/npm": "^5.0.5",
|
"@semantic-release/npm": "^5.0.5",
|
||||||
"@semantic-release/release-notes-generator": "^7.1.2",
|
"@semantic-release/release-notes-generator": "^7.1.2",
|
||||||
"aggregate-error": "^1.0.0",
|
"aggregate-error": "^3.0.0",
|
||||||
"cosmiconfig": "^5.0.1",
|
"cosmiconfig": "^5.0.1",
|
||||||
"debug": "^4.0.0",
|
"debug": "^4.0.0",
|
||||||
"env-ci": "^3.0.0",
|
"env-ci": "^3.0.0",
|
||||||
"execa": "^1.0.0",
|
"execa": "^1.0.0",
|
||||||
"figures": "^2.0.0",
|
"figures": "^3.0.0",
|
||||||
"find-versions": "^3.0.0",
|
"find-versions": "^3.0.0",
|
||||||
"get-stream": "^4.0.0",
|
"get-stream": "^5.0.0",
|
||||||
"git-log-parser": "^1.2.0",
|
"git-log-parser": "^1.2.0",
|
||||||
"hook-std": "^1.1.0",
|
"hook-std": "^2.0.0",
|
||||||
"hosted-git-info": "^2.7.1",
|
"hosted-git-info": "^2.7.1",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"marked": "^0.5.0",
|
"marked": "^0.6.0",
|
||||||
"marked-terminal": "^3.0.0",
|
"marked-terminal": "^3.2.0",
|
||||||
"p-locate": "^3.0.0",
|
"p-locate": "^4.0.0",
|
||||||
"p-reduce": "^1.0.0",
|
"p-reduce": "^2.0.0",
|
||||||
"read-pkg-up": "^4.0.0",
|
"read-pkg-up": "^6.0.0",
|
||||||
"resolve-from": "^4.0.0",
|
"resolve-from": "^5.0.0",
|
||||||
"semver": "^5.4.1",
|
"semver": "^6.0.0",
|
||||||
"signale": "^1.2.1",
|
"signale": "^1.2.1",
|
||||||
"yargs": "^12.0.0"
|
"yargs": "^13.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ava": "^0.25.0",
|
"ava": "^1.3.1",
|
||||||
"clear-module": "^3.0.0",
|
"clear-module": "^3.0.0",
|
||||||
"codecov": "^3.0.0",
|
"codecov": "^3.0.0",
|
||||||
"commitizen": "^3.0.0",
|
"commitizen": "^3.0.0",
|
||||||
"cz-conventional-changelog": "^2.0.0",
|
"cz-conventional-changelog": "^2.0.0",
|
||||||
"delay": "^4.0.0",
|
"delay": "^4.0.0",
|
||||||
"dockerode": "^2.5.2",
|
"dockerode": "^2.5.2",
|
||||||
"file-url": "^2.0.2",
|
"file-url": "^3.0.0",
|
||||||
"fs-extra": "^7.0.0",
|
"fs-extra": "^8.0.0",
|
||||||
"got": "^9.0.0",
|
"got": "^9.0.0",
|
||||||
"js-yaml": "^3.10.0",
|
"js-yaml": "^3.10.0",
|
||||||
"mockserver-client": "^5.1.1",
|
"mockserver-client": "^5.1.1",
|
||||||
"nock": "^10.0.0",
|
"nock": "^10.0.0",
|
||||||
"nyc": "^12.0.1",
|
"nyc": "^14.0.0",
|
||||||
"p-retry": "^2.0.0",
|
"p-retry": "^4.0.0",
|
||||||
"proxyquire": "^2.0.0",
|
"proxyquire": "^2.0.0",
|
||||||
"sinon": "^6.0.0",
|
"sinon": "^7.2.7",
|
||||||
"stream-buffers": "^3.0.2",
|
"stream-buffers": "^3.0.2",
|
||||||
"tempy": "^0.2.1",
|
"tempy": "^0.3.0",
|
||||||
"xo": "^0.23.0"
|
"xo": "^0.24.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.3"
|
"node": ">=8.3"
|
||||||
|
|||||||
@@ -163,18 +163,6 @@ test.serial('Do not set properties in option for which arg is not in command lin
|
|||||||
t.false('e' in run.args[0][0]);
|
t.false('e' in run.args[0][0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.serial('Set "noCi" options to "true" with "--no-ci"', async t => {
|
|
||||||
const run = stub().resolves(true);
|
|
||||||
const argv = ['', '', '--no-ci'];
|
|
||||||
const cli = requireNoCache('../cli', {'.': run, process: {...process, argv}});
|
|
||||||
|
|
||||||
const exitCode = await cli();
|
|
||||||
|
|
||||||
t.is(run.args[0][0].noCi, true);
|
|
||||||
|
|
||||||
t.is(exitCode, 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('Display help', async t => {
|
test.serial('Display help', async t => {
|
||||||
const run = stub().resolves(true);
|
const run = stub().resolves(true);
|
||||||
const argv = ['', '', '--help'];
|
const argv = ['', '', '--help'];
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ test('The "generateNotes" plugin output, if defined, must be a string', t => {
|
|||||||
t.true(plugins.generateNotes.outputValidator('string'));
|
t.true(plugins.generateNotes.outputValidator('string'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('The "publish" plugin output, if defined, must be an object', t => {
|
test('The "publish" plugin output, if defined, must be an object or "false"', t => {
|
||||||
t.false(plugins.publish.outputValidator(1));
|
t.false(plugins.publish.outputValidator(1));
|
||||||
t.false(plugins.publish.outputValidator('string'));
|
t.false(plugins.publish.outputValidator('string'));
|
||||||
|
|
||||||
@@ -30,6 +30,7 @@ test('The "publish" plugin output, if defined, must be an object', t => {
|
|||||||
t.true(plugins.publish.outputValidator());
|
t.true(plugins.publish.outputValidator());
|
||||||
t.true(plugins.publish.outputValidator(null));
|
t.true(plugins.publish.outputValidator(null));
|
||||||
t.true(plugins.publish.outputValidator(''));
|
t.true(plugins.publish.outputValidator(''));
|
||||||
|
t.true(plugins.publish.outputValidator(false));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('The "generateNotes" plugins output are concatenated with separator and sensitive data is hidden', t => {
|
test('The "generateNotes" plugins output are concatenated with separator and sensitive data is hidden', t => {
|
||||||
|
|||||||
+13
-1
@@ -67,6 +67,18 @@ test('Default values, reading repositoryUrl (http url) from package.json if not
|
|||||||
t.is(result.tagFormat, `v\${version}`);
|
t.is(result.tagFormat, `v\${version}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Convert "ci" option to "noCi"', async t => {
|
||||||
|
const pkg = {repository: 'https://host.null/owner/module.git', release: {ci: false}};
|
||||||
|
// Create a git repository, set the current working directory at the root of the repo
|
||||||
|
const {cwd} = await gitRepo();
|
||||||
|
// Create package.json in repository root
|
||||||
|
await outputJson(path.resolve(cwd, 'package.json'), pkg);
|
||||||
|
|
||||||
|
const {options: result} = await t.context.getConfig({cwd});
|
||||||
|
|
||||||
|
t.is(result.noCi, true);
|
||||||
|
});
|
||||||
|
|
||||||
test('Read options from package.json', async t => {
|
test('Read options from package.json', async t => {
|
||||||
// Create a git repository, set the current working directory at the root of the repo
|
// Create a git repository, set the current working directory at the root of the repo
|
||||||
const {cwd} = await gitRepo();
|
const {cwd} = await gitRepo();
|
||||||
@@ -468,7 +480,7 @@ test('Throw an Error if one of the shareable config cannot be found', async t =>
|
|||||||
await outputJson(path.resolve(cwd, 'package.json'), {release: pkhOptions});
|
await outputJson(path.resolve(cwd, 'package.json'), {release: pkhOptions});
|
||||||
await outputJson(path.resolve(cwd, 'shareable1.json'), options1);
|
await outputJson(path.resolve(cwd, 'shareable1.json'), options1);
|
||||||
|
|
||||||
const error = await t.throws(t.context.getConfig({cwd}), Error);
|
const error = await t.throwsAsync(t.context.getConfig({cwd}), Error);
|
||||||
|
|
||||||
t.is(error.message, "Cannot find module 'non-existing-path'");
|
t.is(error.message, "Cannot find module 'non-existing-path'");
|
||||||
t.is(error.code, 'MODULE_NOT_FOUND');
|
t.is(error.code, 'MODULE_NOT_FOUND');
|
||||||
|
|||||||
@@ -244,6 +244,19 @@ test('Return the "https" formatted URL if "gitCredentials" is defined with "BITB
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Return the "https" formatted URL if "GITHUB_ACTION" is set', async t => {
|
||||||
|
const {cwd} = await gitRepo();
|
||||||
|
|
||||||
|
t.is(
|
||||||
|
await getAuthUrl({
|
||||||
|
cwd,
|
||||||
|
env: {...env, GITHUB_ACTION: 'foo', GITHUB_TOKEN: 'token'},
|
||||||
|
options: {branch: 'master', repositoryUrl: 'git@host.null:owner/repo.git'},
|
||||||
|
}),
|
||||||
|
'https://x-access-token:token@host.null/owner/repo.git'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('Handle "https" URL with group and subgroup, with "GIT_CREDENTIALS"', async t => {
|
test('Handle "https" URL with group and subgroup, with "GIT_CREDENTIALS"', async t => {
|
||||||
const {cwd} = await gitRepo();
|
const {cwd} = await gitRepo();
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -42,7 +42,7 @@ test('Throw error if the last commit sha cannot be found', async t => {
|
|||||||
// Create a git repository, set the current working directory at the root of the repo
|
// Create a git repository, set the current working directory at the root of the repo
|
||||||
const {cwd} = await gitRepo();
|
const {cwd} = await gitRepo();
|
||||||
|
|
||||||
await t.throws(getGitHead({cwd}), Error);
|
await t.throwsAsync(getGitHead({cwd}), Error);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Unshallow and fetch repository', async t => {
|
test('Unshallow and fetch repository', async t => {
|
||||||
@@ -67,7 +67,7 @@ test('Do not throw error when unshallow a complete repository', async t => {
|
|||||||
const {cwd, repositoryUrl} = await gitRepo();
|
const {cwd, repositoryUrl} = await gitRepo();
|
||||||
// Add commits to the master branch
|
// Add commits to the master branch
|
||||||
await gitCommits(['First'], {cwd});
|
await gitCommits(['First'], {cwd});
|
||||||
await t.notThrows(fetch(repositoryUrl, {cwd}));
|
await t.notThrowsAsync(fetch(repositoryUrl, {cwd}));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Fetch all tags on a detached head repository', async t => {
|
test('Fetch all tags on a detached head repository', async t => {
|
||||||
@@ -100,7 +100,7 @@ test('Verify if the commit `sha` is in the direct history of the current branch'
|
|||||||
|
|
||||||
t.true(await isRefInHistory(commits[0].hash, {cwd}));
|
t.true(await isRefInHistory(commits[0].hash, {cwd}));
|
||||||
t.falsy(await isRefInHistory(otherCommits[0].hash, {cwd}));
|
t.falsy(await isRefInHistory(otherCommits[0].hash, {cwd}));
|
||||||
await t.throws(isRefInHistory('non-existant-sha', {cwd}));
|
await t.throwsAsync(isRefInHistory('non-existant-sha', {cwd}));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Get the commit sha for a given tag or falsy if the tag does not exists', async t => {
|
test('Get the commit sha for a given tag or falsy if the tag does not exists', async t => {
|
||||||
@@ -157,7 +157,7 @@ test('Push tag to remote repository', async t => {
|
|||||||
const commits = await gitCommits(['Test commit'], {cwd});
|
const commits = await gitCommits(['Test commit'], {cwd});
|
||||||
|
|
||||||
await tag('tag_name', {cwd});
|
await tag('tag_name', {cwd});
|
||||||
await push(repositoryUrl, 'master', {cwd});
|
await push(repositoryUrl, {cwd});
|
||||||
|
|
||||||
t.is(await gitRemoteTagHead(repositoryUrl, 'tag_name', {cwd}), commits[0].hash);
|
t.is(await gitRemoteTagHead(repositoryUrl, 'tag_name', {cwd}), commits[0].hash);
|
||||||
});
|
});
|
||||||
@@ -171,7 +171,7 @@ test('Push tag to remote repository with remote branch ahaed', async t => {
|
|||||||
await gitPush('origin', 'master', {cwd: tmpRepo});
|
await gitPush('origin', 'master', {cwd: tmpRepo});
|
||||||
|
|
||||||
await tag('tag_name', {cwd});
|
await tag('tag_name', {cwd});
|
||||||
await push(repositoryUrl, 'master', {cwd});
|
await push(repositoryUrl, {cwd});
|
||||||
|
|
||||||
t.is(await gitRemoteTagHead(repositoryUrl, 'tag_name', {cwd}), commits[0].hash);
|
t.is(await gitRemoteTagHead(repositoryUrl, 'tag_name', {cwd}), commits[0].hash);
|
||||||
});
|
});
|
||||||
@@ -206,7 +206,7 @@ test('Return falsy for invalid tag names', async t => {
|
|||||||
test('Throws error if obtaining the tags fails', async t => {
|
test('Throws error if obtaining the tags fails', async t => {
|
||||||
const cwd = tempy.directory();
|
const cwd = tempy.directory();
|
||||||
|
|
||||||
await t.throws(getTags({cwd}));
|
await t.throwsAsync(getTags({cwd}));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Return "true" if repository is up to date', async t => {
|
test('Return "true" if repository is up to date', async t => {
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
import nock from 'nock';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retun a `nock` object setup to respond to a github authentication request. Other expectation and responses can be chained.
|
|
||||||
*
|
|
||||||
* @param {String} [githubToken='GH_TOKEN'] The github token to return in the authentication response.
|
|
||||||
* @param {String} [githubUrl='https://api.github.com'] The url on which to intercept http requests.
|
|
||||||
* @return {Object} A `nock` object ready to respond to a github authentication request.
|
|
||||||
*/
|
|
||||||
export default function authenticate({
|
|
||||||
githubToken = 'GH_TOKEN',
|
|
||||||
githubUrl = 'https://api.github.com',
|
|
||||||
githubApiPathPrefix = '',
|
|
||||||
} = {}) {
|
|
||||||
return nock(`${githubUrl}/${githubApiPathPrefix}`, {reqheaders: {Authorization: `token ${githubToken}`}});
|
|
||||||
}
|
|
||||||
+29
-16
@@ -169,7 +169,7 @@ test('Plugins are called with expected values', async t => {
|
|||||||
t.deepEqual(success.args[0][1].commits[0].message, commits[0].message);
|
t.deepEqual(success.args[0][1].commits[0].message, commits[0].message);
|
||||||
t.deepEqual(success.args[0][1].nextRelease, {...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`});
|
t.deepEqual(success.args[0][1].nextRelease, {...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`});
|
||||||
t.deepEqual(success.args[0][1].releases, [
|
t.deepEqual(success.args[0][1].releases, [
|
||||||
{...release1, ...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: '[Function: proxy]'},
|
{...release1, ...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: '[Function: functionStub]'},
|
||||||
{...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: pluginNoop},
|
{...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: pluginNoop},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -178,7 +178,12 @@ test('Plugins are called with expected values', async t => {
|
|||||||
commits: [commits[0]],
|
commits: [commits[0]],
|
||||||
nextRelease: {...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`},
|
nextRelease: {...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`},
|
||||||
releases: [
|
releases: [
|
||||||
{...release1, ...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: '[Function: proxy]'},
|
{
|
||||||
|
...release1,
|
||||||
|
...nextRelease,
|
||||||
|
notes: `${notes1}\n\n${notes2}\n\n${notes3}`,
|
||||||
|
pluginName: '[Function: functionStub]',
|
||||||
|
},
|
||||||
{...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: pluginNoop},
|
{...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: pluginNoop},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -337,15 +342,19 @@ test('Call all "success" plugins even if one errors out', async t => {
|
|||||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||||
});
|
});
|
||||||
|
|
||||||
await t.throws(
|
await t.throwsAsync(
|
||||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||||
);
|
);
|
||||||
|
|
||||||
t.is(success1.callCount, 1);
|
t.is(success1.callCount, 1);
|
||||||
t.deepEqual(success1.args[0][1].releases, [{...release, ...nextRelease, notes, pluginName: '[Function: proxy]'}]);
|
t.deepEqual(success1.args[0][1].releases, [
|
||||||
|
{...release, ...nextRelease, notes, pluginName: '[Function: functionStub]'},
|
||||||
|
]);
|
||||||
|
|
||||||
t.is(success2.callCount, 1);
|
t.is(success2.callCount, 1);
|
||||||
t.deepEqual(success2.args[0][1].releases, [{...release, ...nextRelease, notes, pluginName: '[Function: proxy]'}]);
|
t.deepEqual(success2.args[0][1].releases, [
|
||||||
|
{...release, ...nextRelease, notes, pluginName: '[Function: functionStub]'},
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Log all "verifyConditions" errors', async t => {
|
test('Log all "verifyConditions" errors', async t => {
|
||||||
@@ -372,7 +381,7 @@ test('Log all "verifyConditions" errors', async t => {
|
|||||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||||
});
|
});
|
||||||
const errors = [
|
const errors = [
|
||||||
...(await t.throws(
|
...(await t.throwsAsync(
|
||||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||||
)),
|
)),
|
||||||
];
|
];
|
||||||
@@ -417,7 +426,7 @@ test('Log all "verifyRelease" errors', async t => {
|
|||||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||||
});
|
});
|
||||||
const errors = [
|
const errors = [
|
||||||
...(await t.throws(
|
...(await t.throwsAsync(
|
||||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||||
)),
|
)),
|
||||||
];
|
];
|
||||||
@@ -519,7 +528,7 @@ test('Dry-run skips fail', async t => {
|
|||||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||||
});
|
});
|
||||||
const errors = [
|
const errors = [
|
||||||
...(await t.throws(
|
...(await t.throwsAsync(
|
||||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||||
)),
|
)),
|
||||||
];
|
];
|
||||||
@@ -693,7 +702,7 @@ test('Allow local releases with "noCi" option', async t => {
|
|||||||
t.is(success.callCount, 1);
|
t.is(success.callCount, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Accept "undefined" value returned by the "generateNotes" plugins', async t => {
|
test('Accept "undefined" value returned by "generateNotes" and "false" by "publish"', async t => {
|
||||||
// Create a git repository, set the current working directory at the root of the repo
|
// Create a git repository, set the current working directory at the root of the repo
|
||||||
const {cwd, repositoryUrl} = await gitRepo(true);
|
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||||
// Add commits to the master branch
|
// Add commits to the master branch
|
||||||
@@ -711,7 +720,8 @@ test('Accept "undefined" value returned by the "generateNotes" plugins', async t
|
|||||||
const generateNotes1 = stub().resolves();
|
const generateNotes1 = stub().resolves();
|
||||||
const notes2 = 'Release notes 2';
|
const notes2 = 'Release notes 2';
|
||||||
const generateNotes2 = stub().resolves(notes2);
|
const generateNotes2 = stub().resolves(notes2);
|
||||||
const publish = stub().resolves();
|
const publish = stub().resolves(false);
|
||||||
|
const success = stub().resolves();
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
branch: 'master',
|
branch: 'master',
|
||||||
@@ -722,7 +732,7 @@ test('Accept "undefined" value returned by the "generateNotes" plugins', async t
|
|||||||
generateNotes: [generateNotes1, generateNotes2],
|
generateNotes: [generateNotes1, generateNotes2],
|
||||||
prepare: stub().resolves(),
|
prepare: stub().resolves(),
|
||||||
publish,
|
publish,
|
||||||
success: stub().resolves(),
|
success,
|
||||||
fail: stub().resolves(),
|
fail: stub().resolves(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -754,6 +764,9 @@ test('Accept "undefined" value returned by the "generateNotes" plugins', async t
|
|||||||
t.is(publish.callCount, 1);
|
t.is(publish.callCount, 1);
|
||||||
t.deepEqual(publish.args[0][1].lastRelease, lastRelease);
|
t.deepEqual(publish.args[0][1].lastRelease, lastRelease);
|
||||||
t.is(publish.args[0][1].nextRelease.notes, notes2);
|
t.is(publish.args[0][1].nextRelease.notes, notes2);
|
||||||
|
|
||||||
|
t.is(success.callCount, 1);
|
||||||
|
t.deepEqual(success.args[0][1].releases, [{pluginName: '[Function: functionStub]'}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Returns false if triggered by a PR', async t => {
|
test('Returns false if triggered by a PR', async t => {
|
||||||
@@ -953,7 +966,7 @@ test('Log both plugins errors and errors thrown by "fail" plugin', async t => {
|
|||||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||||
});
|
});
|
||||||
|
|
||||||
await t.throws(
|
await t.throwsAsync(
|
||||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -978,7 +991,7 @@ test('Call "fail" only if a plugin returns a SemanticReleaseError', async t => {
|
|||||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||||
});
|
});
|
||||||
|
|
||||||
await t.throws(
|
await t.throwsAsync(
|
||||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -995,7 +1008,7 @@ test('Throw SemanticReleaseError if repositoryUrl is not set and cannot be found
|
|||||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||||
});
|
});
|
||||||
const errors = [
|
const errors = [
|
||||||
...(await t.throws(
|
...(await t.throwsAsync(
|
||||||
semanticRelease({}, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
semanticRelease({}, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||||
)),
|
)),
|
||||||
];
|
];
|
||||||
@@ -1032,7 +1045,7 @@ test('Throw an Error if plugin returns an unexpected value', async t => {
|
|||||||
'./lib/get-logger': () => t.context.logger,
|
'./lib/get-logger': () => t.context.logger,
|
||||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||||
});
|
});
|
||||||
const error = await t.throws(
|
const error = await t.throwsAsync(
|
||||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()}),
|
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()}),
|
||||||
Error
|
Error
|
||||||
);
|
);
|
||||||
@@ -1062,7 +1075,7 @@ test('Hide sensitive information passed to "fail" plugin', async t => {
|
|||||||
'./lib/get-logger': () => t.context.logger,
|
'./lib/get-logger': () => t.context.logger,
|
||||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||||
});
|
});
|
||||||
await t.throws(
|
await t.throwsAsync(
|
||||||
semanticRelease(options, {cwd, env, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()}),
|
semanticRelease(options, {cwd, env, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()}),
|
||||||
Error
|
Error
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ test('Exit with 1 if a plugin is not found', async t => {
|
|||||||
release: {analyzeCommits: 'non-existing-path', success: false, fail: false},
|
release: {analyzeCommits: 'non-existing-path', success: false, fail: false},
|
||||||
});
|
});
|
||||||
|
|
||||||
const {code, stderr} = await t.throws(execa(cli, [], {env, cwd}));
|
const {code, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
|
||||||
t.is(code, 1);
|
t.is(code, 1);
|
||||||
t.regex(stderr, /Cannot find module/);
|
t.regex(stderr, /Cannot find module/);
|
||||||
});
|
});
|
||||||
@@ -276,7 +276,7 @@ test('Exit with 1 if a shareable config is not found', async t => {
|
|||||||
release: {extends: 'non-existing-path', success: false, fail: false},
|
release: {extends: 'non-existing-path', success: false, fail: false},
|
||||||
});
|
});
|
||||||
|
|
||||||
const {code, stderr} = await t.throws(execa(cli, [], {env, cwd}));
|
const {code, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
|
||||||
t.is(code, 1);
|
t.is(code, 1);
|
||||||
t.regex(stderr, /Cannot find module/);
|
t.regex(stderr, /Cannot find module/);
|
||||||
});
|
});
|
||||||
@@ -297,7 +297,7 @@ test('Exit with 1 if a shareable config reference a not found plugin', async t =
|
|||||||
});
|
});
|
||||||
await writeJson(path.resolve(cwd, 'shareable.json'), shareable);
|
await writeJson(path.resolve(cwd, 'shareable.json'), shareable);
|
||||||
|
|
||||||
const {code, stderr} = await t.throws(execa(cli, [], {env, cwd}));
|
const {code, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
|
||||||
t.is(code, 1);
|
t.is(code, 1);
|
||||||
t.regex(stderr, /Cannot find module/);
|
t.regex(stderr, /Cannot find module/);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ test('Wrap plugin in a function that add the "pluginName" to the error"', async
|
|||||||
'./plugin-error': './test/fixtures',
|
'./plugin-error': './test/fixtures',
|
||||||
});
|
});
|
||||||
|
|
||||||
const error = await t.throws(plugin({options: {}}));
|
const error = await t.throwsAsync(plugin({options: {}}));
|
||||||
|
|
||||||
t.is(error.pluginName, './plugin-error');
|
t.is(error.pluginName, './plugin-error');
|
||||||
});
|
});
|
||||||
@@ -72,7 +72,7 @@ test('Wrap plugin in a function that add the "pluginName" to multiple errors"',
|
|||||||
'./plugin-errors': './test/fixtures',
|
'./plugin-errors': './test/fixtures',
|
||||||
});
|
});
|
||||||
|
|
||||||
const errors = [...(await t.throws(plugin({options: {}})))];
|
const errors = [...(await t.throwsAsync(plugin({options: {}})))];
|
||||||
for (const error of errors) {
|
for (const error of errors) {
|
||||||
t.is(error.pluginName, './plugin-errors');
|
t.is(error.pluginName, './plugin-errors');
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ test('Wrap "analyzeCommits" plugin in a function that validate the output of the
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
const error = await t.throws(plugin({options: {}}));
|
const error = await t.throwsAsync(plugin({options: {}}));
|
||||||
|
|
||||||
t.is(error.code, 'EANALYZECOMMITSOUTPUT');
|
t.is(error.code, 'EANALYZECOMMITSOUTPUT');
|
||||||
t.is(error.name, 'SemanticReleaseError');
|
t.is(error.name, 'SemanticReleaseError');
|
||||||
@@ -125,7 +125,7 @@ test('Wrap "generateNotes" plugin in a function that validate the output of the
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
const error = await t.throws(plugin({options: {}}));
|
const error = await t.throwsAsync(plugin({options: {}}));
|
||||||
|
|
||||||
t.is(error.code, 'EGENERATENOTESOUTPUT');
|
t.is(error.code, 'EGENERATENOTESOUTPUT');
|
||||||
t.is(error.name, 'SemanticReleaseError');
|
t.is(error.name, 'SemanticReleaseError');
|
||||||
@@ -143,7 +143,7 @@ test('Wrap "publish" plugin in a function that validate the output of the plugin
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
const error = await t.throws(plugin({options: {}}));
|
const error = await t.throwsAsync(plugin({options: {}}));
|
||||||
|
|
||||||
t.is(error.code, 'EPUBLISHOUTPUT');
|
t.is(error.code, 'EPUBLISHOUTPUT');
|
||||||
t.is(error.name, 'SemanticReleaseError');
|
t.is(error.name, 'SemanticReleaseError');
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ test('Stop execution and throw error if a step rejects', async t => {
|
|||||||
const step2 = stub().rejects(new Error('test error'));
|
const step2 = stub().rejects(new Error('test error'));
|
||||||
const step3 = stub().resolves(3);
|
const step3 = stub().resolves(3);
|
||||||
|
|
||||||
const error = await t.throws(pipeline([step1, step2, step3])(0), Error);
|
const error = await t.throwsAsync(pipeline([step1, step2, step3])(0), Error);
|
||||||
t.is(error.message, 'test error');
|
t.is(error.message, 'test error');
|
||||||
t.true(step1.calledWith(0));
|
t.true(step1.calledWith(0));
|
||||||
t.true(step2.calledWith(0));
|
t.true(step2.calledWith(0));
|
||||||
@@ -98,7 +98,7 @@ test('Throw all errors from the first step throwing an AggregateError', async t
|
|||||||
const step2 = stub().rejects(new AggregateError([error1, error2]));
|
const step2 = stub().rejects(new AggregateError([error1, error2]));
|
||||||
const step3 = stub().resolves(3);
|
const step3 = stub().resolves(3);
|
||||||
|
|
||||||
const errors = await t.throws(pipeline([step1, step2, step3])(0));
|
const errors = await t.throwsAsync(pipeline([step1, step2, step3])(0));
|
||||||
|
|
||||||
t.deepEqual([...errors], [error1, error2]);
|
t.deepEqual([...errors], [error1, error2]);
|
||||||
t.true(step1.calledWith(0));
|
t.true(step1.calledWith(0));
|
||||||
@@ -113,7 +113,7 @@ test('Execute all even if a Promise rejects', async t => {
|
|||||||
const step2 = stub().rejects(error1);
|
const step2 = stub().rejects(error1);
|
||||||
const step3 = stub().rejects(error2);
|
const step3 = stub().rejects(error2);
|
||||||
|
|
||||||
const errors = await t.throws(pipeline([step1, step2, step3], {settleAll: true})(0));
|
const errors = await t.throwsAsync(pipeline([step1, step2, step3], {settleAll: true})(0));
|
||||||
|
|
||||||
t.deepEqual([...errors], [error1, error2]);
|
t.deepEqual([...errors], [error1, error2]);
|
||||||
t.true(step1.calledWith(0));
|
t.true(step1.calledWith(0));
|
||||||
@@ -129,7 +129,7 @@ test('Throw all errors from all steps throwing an AggregateError', async t => {
|
|||||||
const step1 = stub().rejects(new AggregateError([error1, error2]));
|
const step1 = stub().rejects(new AggregateError([error1, error2]));
|
||||||
const step2 = stub().rejects(new AggregateError([error3, error4]));
|
const step2 = stub().rejects(new AggregateError([error3, error4]));
|
||||||
|
|
||||||
const errors = await t.throws(pipeline([step1, step2], {settleAll: true})(0));
|
const errors = await t.throwsAsync(pipeline([step1, step2], {settleAll: true})(0));
|
||||||
|
|
||||||
t.deepEqual([...errors], [error1, error2, error3, error4]);
|
t.deepEqual([...errors], [error1, error2, error3, error4]);
|
||||||
t.true(step1.calledWith(0));
|
t.true(step1.calledWith(0));
|
||||||
@@ -145,7 +145,7 @@ test('Execute each function in series passing a transformed input even if a step
|
|||||||
const step4 = stub().resolves(4);
|
const step4 = stub().resolves(4);
|
||||||
const getNextInput = (prevResult, result) => prevResult + result;
|
const getNextInput = (prevResult, result) => prevResult + result;
|
||||||
|
|
||||||
const errors = await t.throws(pipeline([step1, step2, step3, step4], {settleAll: true, getNextInput})(0));
|
const errors = await t.throwsAsync(pipeline([step1, step2, step3, step4], {settleAll: true, getNextInput})(0));
|
||||||
|
|
||||||
t.deepEqual([...errors], [error2, error3]);
|
t.deepEqual([...errors], [error2, error3]);
|
||||||
t.true(step1.calledWith(0));
|
t.true(step1.calledWith(0));
|
||||||
|
|||||||
+6
-6
@@ -7,7 +7,7 @@ test('Throw a AggregateError', async t => {
|
|||||||
const {cwd} = await gitRepo();
|
const {cwd} = await gitRepo();
|
||||||
const options = {};
|
const options = {};
|
||||||
|
|
||||||
const errors = [...(await t.throws(verify({cwd, options})))];
|
const errors = [...(await t.throwsAsync(verify({cwd, options})))];
|
||||||
|
|
||||||
t.is(errors[0].name, 'SemanticReleaseError');
|
t.is(errors[0].name, 'SemanticReleaseError');
|
||||||
t.is(errors[0].code, 'ENOREPOURL');
|
t.is(errors[0].code, 'ENOREPOURL');
|
||||||
@@ -27,7 +27,7 @@ test('Throw a SemanticReleaseError if does not run on a git repository', async t
|
|||||||
const cwd = tempy.directory();
|
const cwd = tempy.directory();
|
||||||
const options = {};
|
const options = {};
|
||||||
|
|
||||||
const errors = [...(await t.throws(verify({cwd, options})))];
|
const errors = [...(await t.throwsAsync(verify({cwd, options})))];
|
||||||
|
|
||||||
t.is(errors[0].name, 'SemanticReleaseError');
|
t.is(errors[0].name, 'SemanticReleaseError');
|
||||||
t.is(errors[0].code, 'ENOGITREPO');
|
t.is(errors[0].code, 'ENOGITREPO');
|
||||||
@@ -39,7 +39,7 @@ test('Throw a SemanticReleaseError if the "tagFormat" is not valid', async t =>
|
|||||||
const {cwd, repositoryUrl} = await gitRepo(true);
|
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||||
const options = {repositoryUrl, tagFormat: `?\${version}`};
|
const options = {repositoryUrl, tagFormat: `?\${version}`};
|
||||||
|
|
||||||
const errors = [...(await t.throws(verify({cwd, options})))];
|
const errors = [...(await t.throwsAsync(verify({cwd, options})))];
|
||||||
|
|
||||||
t.is(errors[0].name, 'SemanticReleaseError');
|
t.is(errors[0].name, 'SemanticReleaseError');
|
||||||
t.is(errors[0].code, 'EINVALIDTAGFORMAT');
|
t.is(errors[0].code, 'EINVALIDTAGFORMAT');
|
||||||
@@ -51,7 +51,7 @@ test('Throw a SemanticReleaseError if the "tagFormat" does not contains the "ver
|
|||||||
const {cwd, repositoryUrl} = await gitRepo(true);
|
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||||
const options = {repositoryUrl, tagFormat: 'test'};
|
const options = {repositoryUrl, tagFormat: 'test'};
|
||||||
|
|
||||||
const errors = [...(await t.throws(verify({cwd, options})))];
|
const errors = [...(await t.throwsAsync(verify({cwd, options})))];
|
||||||
|
|
||||||
t.is(errors[0].name, 'SemanticReleaseError');
|
t.is(errors[0].name, 'SemanticReleaseError');
|
||||||
t.is(errors[0].code, 'ETAGNOVERSION');
|
t.is(errors[0].code, 'ETAGNOVERSION');
|
||||||
@@ -63,7 +63,7 @@ test('Throw a SemanticReleaseError if the "tagFormat" contains multiple "version
|
|||||||
const {cwd, repositoryUrl} = await gitRepo(true);
|
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||||
const options = {repositoryUrl, tagFormat: `\${version}v\${version}`};
|
const options = {repositoryUrl, tagFormat: `\${version}v\${version}`};
|
||||||
|
|
||||||
const errors = [...(await t.throws(verify({cwd, options})))];
|
const errors = [...(await t.throwsAsync(verify({cwd, options})))];
|
||||||
|
|
||||||
t.is(errors[0].name, 'SemanticReleaseError');
|
t.is(errors[0].name, 'SemanticReleaseError');
|
||||||
t.is(errors[0].code, 'ETAGNOVERSION');
|
t.is(errors[0].code, 'ETAGNOVERSION');
|
||||||
@@ -75,5 +75,5 @@ test('Return "true" if all verification pass', async t => {
|
|||||||
const {cwd, repositoryUrl} = await gitRepo(true);
|
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||||
const options = {repositoryUrl, tagFormat: `v\${version}`};
|
const options = {repositoryUrl, tagFormat: `v\${version}`};
|
||||||
|
|
||||||
await t.notThrows(verify({cwd, options}));
|
await t.notThrowsAsync(verify({cwd, options}));
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user