Compare commits
19
Commits
+1
-1
@@ -14,7 +14,7 @@ branches:
|
||||
- master
|
||||
- next
|
||||
- beta
|
||||
- /^\d+(.\d+)?.x$/
|
||||
- /^\d+\.(\d+|x)(\.x)?$/
|
||||
- /^greenkeeper.*$/
|
||||
|
||||
# Retry install on fail to avoid failing a build on network/disk/external errors
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
## CI configurations
|
||||
- [CircleCI 2.0 workflows](circleci-workflows.md)
|
||||
- [Travis CI](travis.md)
|
||||
- [Travis CI with build stages](travis-build-stages.md)
|
||||
- [GitLab CI](gitlab-ci.md)
|
||||
|
||||
## 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)..
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
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)).
|
||||
|
||||
**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
|
||||
### `.travis.yml` configuration for multiple Node.js 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 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.
|
||||
|
||||
**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
|
||||
|
||||
@@ -67,15 +27,20 @@ node_js:
|
||||
- 8
|
||||
- 6
|
||||
|
||||
deploy:
|
||||
provider: script
|
||||
skip_cleanup: true
|
||||
script:
|
||||
- npx travis-deploy-once "npx semantic-release"
|
||||
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
|
||||
```
|
||||
|
||||
**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
|
||||
|
||||
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
|
||||
{
|
||||
"devDependencies": {
|
||||
"semantic-release": "^15.0.0",
|
||||
"travis-deploy-once": "^5.0.0"
|
||||
"semantic-release": "^15.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).
|
||||
|
||||
@@ -97,14 +61,16 @@ This recipe cover the Travis specifics only. See [Non JavaScript projects recipe
|
||||
|
||||
### `.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.
|
||||
|
||||
**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
|
||||
|
||||
@@ -112,18 +78,18 @@ go:
|
||||
- 1.6
|
||||
- 1.7
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
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/*
|
||||
# Run semantic-release only on one job, after all other are successful
|
||||
- npx travis-deploy-once "npx semantic-release"
|
||||
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
|
||||
```
|
||||
|
||||
**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).
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
**semantic-release** allow to manage and automate complex release workflow, based on multiple Git branches and distribution channels. This allow to:
|
||||
- Distributes certain releases to a particular group of users via distribution channels
|
||||
- Manage the availability of releases on distribution channels via branches merge
|
||||
- Maintain multiple lines of releases in parrallel
|
||||
- Maintain multiple lines of releases in parallel
|
||||
- Work on large future releases outside the normal flow of one version increment per Git push
|
||||
|
||||
See [Release workflow recipes](../recipes/README.md#release-workflow) for detailed examples.
|
||||
|
||||
@@ -127,6 +127,16 @@ async function run(context, plugins) {
|
||||
|
||||
context.lastRelease = await getLastRelease(context);
|
||||
|
||||
if (context.lastRelease.gitTag) {
|
||||
logger.log(
|
||||
`Found git tag ${context.lastRelease.gitTag} associated with version ${context.lastRelease.version} on branch ${
|
||||
context.branch.name
|
||||
}`
|
||||
);
|
||||
} else {
|
||||
logger.log(`No git tag version found on branch ${context.branch.name}`);
|
||||
}
|
||||
|
||||
context.commits = await getCommits(context);
|
||||
|
||||
const nextRelease = {
|
||||
@@ -168,9 +178,10 @@ async function run(context, plugins) {
|
||||
logger.success(`Created tag ${nextRelease.gitTag}`);
|
||||
}
|
||||
|
||||
context.releases.push(...(await plugins.publish(context)));
|
||||
const releases = await plugins.publish(context);
|
||||
context.releases.push(...releases);
|
||||
|
||||
await plugins.success(context);
|
||||
await plugins.success({...context, releases});
|
||||
|
||||
logger.success(`Published release ${nextRelease.version}`);
|
||||
|
||||
|
||||
@@ -71,22 +71,21 @@ module.exports = {
|
||||
pipelineConfig: () => ({
|
||||
// Add `nextRelease` and plugin properties to published release
|
||||
transform: (release, step, {nextRelease}) => ({
|
||||
...nextRelease,
|
||||
...(release || {}),
|
||||
...(release === false ? {} : nextRelease),
|
||||
...release,
|
||||
...step,
|
||||
}),
|
||||
}),
|
||||
},
|
||||
addChannel: {
|
||||
default: ['@semantic-release/npm', '@semantic-release/github'],
|
||||
required: false,
|
||||
dryRun: false,
|
||||
outputValidator: output => !output || isPlainObject(output),
|
||||
pipelineConfig: () => ({
|
||||
// Add `nextRelease` and plugin properties to published release
|
||||
transform: (release, step, {nextRelease}) => ({
|
||||
...nextRelease,
|
||||
...(release || {}),
|
||||
...(release === false ? {} : nextRelease),
|
||||
...release,
|
||||
...step,
|
||||
}),
|
||||
}),
|
||||
|
||||
@@ -23,17 +23,15 @@ const {makeTag} = require('./utils');
|
||||
*
|
||||
* @return {LastRelease} The last tagged release or empty object if none is found.
|
||||
*/
|
||||
module.exports = ({branch: {name, tags, type}, options: {tagFormat}, logger}, {before} = {}) => {
|
||||
module.exports = ({branch: {tags, type}, options: {tagFormat}}, {before} = {}) => {
|
||||
const [{version, gitTag, gitHead, channel} = {}] = tags
|
||||
.filter(tag => type === 'prerelease' || !semver.prerelease(tag.version))
|
||||
.filter(tag => isUndefined(before) || semver.lt(tag.version, before))
|
||||
.sort((a, b) => semver.rcompare(a.version, b.version));
|
||||
|
||||
if (gitTag) {
|
||||
logger.log(`Found git tag ${gitTag} associated with version ${version} on branch ${name}`);
|
||||
return {version, gitTag, gitHead, channel, name: makeTag(tagFormat, version)};
|
||||
}
|
||||
|
||||
logger.log(`No git tag version found on branch ${name}`);
|
||||
return {};
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ const {uniq} = require('lodash');
|
||||
const semver = require('semver');
|
||||
const semverDiff = require('semver-diff');
|
||||
const getLastRelease = require('./get-last-release');
|
||||
const {makeTag} = require('./utils');
|
||||
const {makeTag, getLowerBound} = require('./utils');
|
||||
|
||||
/**
|
||||
* Find releases that have been merged from from a higher branch but not added on the channel of the current branch.
|
||||
@@ -28,8 +28,14 @@ module.exports = context => {
|
||||
.reduce(
|
||||
(releases, higherBranch) => [
|
||||
...releases,
|
||||
// For all unique release version of the higher branch merged on current branch
|
||||
...uniq(branch.tags.filter(({channel}) => channel === higherBranch.channel))
|
||||
// For all unique release version of the higher branch merged on current branch, excluding lower than start range version for maintenance branches
|
||||
...uniq(
|
||||
branch.tags.filter(
|
||||
({channel, version}) =>
|
||||
channel === higherBranch.channel &&
|
||||
(branch.type !== 'maintenance' || semver.gte(version, getLowerBound(branch['merge-range'])))
|
||||
)
|
||||
)
|
||||
// Find ones that are not released on the building branch channel
|
||||
.filter(tag =>
|
||||
branch.tags.every(
|
||||
|
||||
+4
-4
@@ -23,19 +23,19 @@ function tagsToVersions(tags) {
|
||||
}
|
||||
|
||||
function isMajorRange(range) {
|
||||
return /^\d\.x(?:\.x)?$/i.test(range);
|
||||
return /^\d+\.x(?:\.x)?$/i.test(range);
|
||||
}
|
||||
|
||||
function isMaintenanceRange(range) {
|
||||
return /^\d\.[\dx](?:\.x)?$/i.test(range);
|
||||
return /^\d+\.(?:\d+|x)(?:\.x)?$/i.test(range);
|
||||
}
|
||||
|
||||
function getUpperBound(range) {
|
||||
return semver.valid(range) ? range : ((semver.validRange(range) || '').match(/<(\d\.\d\.\d)$/) || [])[1];
|
||||
return semver.valid(range) ? range : ((semver.validRange(range) || '').match(/<(\d+\.\d+\.\d+)$/) || [])[1];
|
||||
}
|
||||
|
||||
function getLowerBound(range) {
|
||||
return ((semver.validRange(range) || '').match(/(\d\.\d\.\d)/) || [])[1];
|
||||
return ((semver.validRange(range) || '').match(/(\d+\.\d+\.\d+)/) || [])[1];
|
||||
}
|
||||
|
||||
function highest(version1, version2) {
|
||||
|
||||
+4
-4
@@ -19,10 +19,10 @@
|
||||
"Pierre Vanduynslager (https://twitter.com/@pvdlg_)"
|
||||
],
|
||||
"dependencies": {
|
||||
"@semantic-release/commit-analyzer": "^7.0.0-beta.2",
|
||||
"@semantic-release/commit-analyzer": "^7.0.0-beta.1",
|
||||
"@semantic-release/error": "^2.2.0",
|
||||
"@semantic-release/github": "^5.3.0-beta.1",
|
||||
"@semantic-release/npm": "^5.2.0-beta.1",
|
||||
"@semantic-release/github": "^5.3.0-beta.5",
|
||||
"@semantic-release/npm": "^5.2.0-beta.4",
|
||||
"@semantic-release/release-notes-generator": "^7.1.2",
|
||||
"aggregate-error": "^1.0.0",
|
||||
"cosmiconfig": "^5.0.1",
|
||||
@@ -63,7 +63,7 @@
|
||||
"mockserver-client": "^5.1.1",
|
||||
"nock": "^10.0.0",
|
||||
"nyc": "^13.1.0",
|
||||
"p-retry": "^2.0.0",
|
||||
"p-retry": "^3.0.0",
|
||||
"proxyquire": "^2.0.0",
|
||||
"sinon": "^7.1.1",
|
||||
"stream-buffers": "^3.0.2",
|
||||
|
||||
@@ -22,7 +22,7 @@ test('The "generateNotes" plugin output, if defined, must be a string', t => {
|
||||
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('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(null));
|
||||
t.true(plugins.publish.outputValidator(''));
|
||||
t.true(plugins.publish.outputValidator(false));
|
||||
});
|
||||
|
||||
test('The "addChannel" plugin output, if defined, must be an object', t => {
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
import test from 'ava';
|
||||
import {stub} from 'sinon';
|
||||
import getLastRelease from '../lib/get-last-release';
|
||||
|
||||
test.beforeEach(t => {
|
||||
// Stub the logger functions
|
||||
t.context.log = stub();
|
||||
t.context.logger = {log: t.context.log};
|
||||
});
|
||||
|
||||
test('Get the highest non-prerelease valid tag', t => {
|
||||
const result = getLastRelease({
|
||||
branch: {
|
||||
@@ -20,11 +13,9 @@ test('Get the highest non-prerelease valid tag', t => {
|
||||
type: 'release',
|
||||
},
|
||||
options: {tagFormat: `v\${version}`},
|
||||
logger: t.context.logger,
|
||||
});
|
||||
|
||||
t.deepEqual(result, {version: '2.0.0', gitTag: 'v2.0.0', name: 'v2.0.0', gitHead: '222', channel: undefined});
|
||||
t.deepEqual(t.context.log.args[0][0], 'Found git tag v2.0.0 associated with version 2.0.0 on branch master');
|
||||
});
|
||||
|
||||
test('Return empty object if no valid tag is found', t => {
|
||||
@@ -35,11 +26,9 @@ test('Return empty object if no valid tag is found', t => {
|
||||
type: 'release',
|
||||
},
|
||||
options: {tagFormat: `v\${version}`},
|
||||
logger: t.context.logger,
|
||||
});
|
||||
|
||||
t.deepEqual(result, {});
|
||||
t.deepEqual(t.context.log.args[0][0], 'No git tag version found on branch master');
|
||||
});
|
||||
|
||||
test('Get the highest non-prerelease valid tag before a certain version', t => {
|
||||
@@ -58,11 +47,9 @@ test('Get the highest non-prerelease valid tag before a certain version', t => {
|
||||
type: 'release',
|
||||
},
|
||||
options: {tagFormat: `v\${version}`},
|
||||
logger: t.context.logger,
|
||||
},
|
||||
{before: '2.1.0'}
|
||||
);
|
||||
|
||||
t.deepEqual(result, {version: '2.0.0', gitTag: 'v2.0.0', name: 'v2.0.0', gitHead: '333', channel: undefined});
|
||||
t.deepEqual(t.context.log.args[0][0], 'Found git tag v2.0.0 associated with version 2.0.0 on branch master');
|
||||
});
|
||||
|
||||
@@ -1,66 +1,62 @@
|
||||
import test from 'ava';
|
||||
import {stub} from 'sinon';
|
||||
import getReleasesToAdd from '../lib/get-releases-to-add';
|
||||
|
||||
test.beforeEach(t => {
|
||||
// Stub the logger functions
|
||||
t.context.log = stub();
|
||||
t.context.logger = {log: t.context.log};
|
||||
});
|
||||
|
||||
test('Return versions merged from release to maintenance branch', t => {
|
||||
test('Return versions merged from release to maintenance branch, excluding lower than branch start range', t => {
|
||||
const result = getReleasesToAdd({
|
||||
branch: {
|
||||
name: '1.x',
|
||||
channel: '1.x',
|
||||
name: '2.x',
|
||||
channel: '2.x',
|
||||
type: 'maintenance',
|
||||
'merge-range': '>=2.0.0 <3.0.0',
|
||||
tags: [
|
||||
{gitTag: 'v1.0.0@1.x', version: '1.0.0', channel: '1.x', gitHead: '111'},
|
||||
{gitTag: 'v1.0.0', version: '1.0.0', gitHead: '111'},
|
||||
{gitTag: 'v1.1.0', version: '1.1.0', gitHead: '222'},
|
||||
{gitTag: 'v1.1.1', version: '1.1.1', gitHead: '333'},
|
||||
{gitTag: 'v2.0.0@2.x', version: '2.0.0', channel: '2.x', gitHead: '111'},
|
||||
{gitTag: 'v2.0.0', version: '2.0.0', gitHead: '111'},
|
||||
{gitTag: 'v2.1.0', version: '2.1.0', gitHead: '222'},
|
||||
{gitTag: 'v2.1.1', version: '2.1.1', gitHead: '333'},
|
||||
{gitTag: 'v1.0.0', version: '1.0.0', gitHead: '444'},
|
||||
{gitTag: 'v1.1.0', version: '1.1.0', gitHead: '555'},
|
||||
],
|
||||
},
|
||||
branches: [{name: '1.x', channel: '1.x'}, {name: 'master'}],
|
||||
branches: [{name: '2.x', channel: '2.x'}, {name: 'master'}],
|
||||
options: {tagFormat: `v\${version}`},
|
||||
logger: t.context.logger,
|
||||
});
|
||||
|
||||
t.deepEqual(result, [
|
||||
{
|
||||
lastRelease: {version: '1.0.0', channel: '1.x', gitTag: 'v1.0.0@1.x', name: 'v1.0.0', gitHead: '111'},
|
||||
lastRelease: {version: '2.0.0', channel: '2.x', gitTag: 'v2.0.0@2.x', name: 'v2.0.0', gitHead: '111'},
|
||||
currentRelease: {
|
||||
type: 'minor',
|
||||
version: '1.1.0',
|
||||
version: '2.1.0',
|
||||
channel: undefined,
|
||||
gitTag: 'v1.1.0',
|
||||
name: 'v1.1.0',
|
||||
gitTag: 'v2.1.0',
|
||||
name: 'v2.1.0',
|
||||
gitHead: '222',
|
||||
},
|
||||
nextRelease: {
|
||||
type: 'minor',
|
||||
version: '1.1.0',
|
||||
channel: '1.x',
|
||||
gitTag: 'v1.1.0@1.x',
|
||||
name: 'v1.1.0',
|
||||
version: '2.1.0',
|
||||
channel: '2.x',
|
||||
gitTag: 'v2.1.0@2.x',
|
||||
name: 'v2.1.0',
|
||||
gitHead: '222',
|
||||
},
|
||||
},
|
||||
{
|
||||
lastRelease: {version: '1.1.0', channel: undefined, gitTag: 'v1.1.0', name: 'v1.1.0', gitHead: '222'},
|
||||
lastRelease: {version: '2.1.0', channel: undefined, gitTag: 'v2.1.0', name: 'v2.1.0', gitHead: '222'},
|
||||
currentRelease: {
|
||||
type: 'patch',
|
||||
version: '1.1.1',
|
||||
version: '2.1.1',
|
||||
channel: undefined,
|
||||
gitTag: 'v1.1.1',
|
||||
name: 'v1.1.1',
|
||||
gitTag: 'v2.1.1',
|
||||
name: 'v2.1.1',
|
||||
gitHead: '333',
|
||||
},
|
||||
nextRelease: {
|
||||
type: 'patch',
|
||||
version: '1.1.1',
|
||||
channel: '1.x',
|
||||
gitTag: 'v1.1.1@1.x',
|
||||
name: 'v1.1.1',
|
||||
version: '2.1.1',
|
||||
channel: '2.x',
|
||||
gitTag: 'v2.1.1@2.x',
|
||||
name: 'v2.1.1',
|
||||
gitHead: '333',
|
||||
},
|
||||
},
|
||||
@@ -80,7 +76,6 @@ test('Return versions merged from future branch to release branch', t => {
|
||||
},
|
||||
branches: [{name: 'master'}, {name: 'next', channel: 'next'}, {name: 'next-major', channel: 'next-major'}],
|
||||
options: {tagFormat: `v\${version}`},
|
||||
logger: t.context.logger,
|
||||
});
|
||||
|
||||
t.deepEqual(result, [
|
||||
@@ -138,7 +133,6 @@ test('Return releases sorted by ascending order', t => {
|
||||
},
|
||||
branches: [{name: 'master'}, {name: 'next', channel: 'next'}, {name: 'next-major', channel: 'next-major'}],
|
||||
options: {tagFormat: `v\${version}`},
|
||||
logger: t.context.logger,
|
||||
});
|
||||
|
||||
t.deepEqual(result, [
|
||||
@@ -188,7 +182,6 @@ test('no lastRelease', t => {
|
||||
branch: {name: 'master', tags: [{gitTag: 'v1.0.0@next', version: '1.0.0', channel: 'next', gitHead: '111'}]},
|
||||
branches: [{name: 'master'}, {name: 'next', channel: 'next'}],
|
||||
options: {tagFormat: `v\${version}`},
|
||||
logger: t.context.logger,
|
||||
});
|
||||
|
||||
t.deepEqual(result, [
|
||||
@@ -231,7 +224,6 @@ test('Ignore pre-release versions', t => {
|
||||
{name: 'alpha', type: 'prerelease', channel: 'alpha'},
|
||||
],
|
||||
options: {tagFormat: `v\${version}`},
|
||||
logger: t.context.logger,
|
||||
});
|
||||
|
||||
t.deepEqual(result, [
|
||||
|
||||
+27
-37
@@ -342,14 +342,14 @@ test('Plugins are called with expected values', async t => {
|
||||
|
||||
t.deepEqual(success.args[1][0], config);
|
||||
t.deepEqual(success.args[1][1].options, options);
|
||||
t.deepEqual(success.args[0][1].branch, branch);
|
||||
t.deepEqual(success.args[0][1].branches, branches);
|
||||
t.deepEqual(success.args[1][1].branch, branch);
|
||||
t.deepEqual(success.args[1][1].branches, branches);
|
||||
t.deepEqual(success.args[1][1].logger, t.context.logger);
|
||||
t.deepEqual(success.args[1][1].lastRelease, lastRelease);
|
||||
t.deepEqual(success.args[1][1].commits[0].hash, commits[0].hash);
|
||||
t.deepEqual(success.args[1][1].commits[0].message, commits[0].message);
|
||||
t.deepEqual(success.args[1][1].nextRelease, {...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`});
|
||||
t.deepEqual(success.args[1][1].releases, releases);
|
||||
t.deepEqual(success.args[1][1].releases, [releases[1], releases[2]]);
|
||||
|
||||
t.deepEqual(result, {
|
||||
lastRelease,
|
||||
@@ -1139,30 +1139,23 @@ test('Allow local releases with "noCi" option', async t => {
|
||||
t.is(success.callCount, 1);
|
||||
});
|
||||
|
||||
test('Accept "undefined" value returned by the "generateNotes" plugins', async t => {
|
||||
// Create a git repository, set the current working directory at the root of the repo
|
||||
test('Accept "undefined" value returned by "generateNotes" and "false" by "publish" and "addChannel"', async t => {
|
||||
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||
// Add commits to the master branch
|
||||
let commits = await gitCommits(['First'], {cwd});
|
||||
// Create the tag corresponding to version 1.0.0
|
||||
await gitCommits(['First'], {cwd});
|
||||
await gitTagVersion('v1.0.0', undefined, {cwd});
|
||||
// Add new commits to the master branch
|
||||
commits = (await gitCommits(['Second'], {cwd})).concat(commits);
|
||||
await gitTagVersion('v1.0.0@next', undefined, {cwd});
|
||||
await gitTagVersion('v1.1.0@next', undefined, {cwd});
|
||||
await gitPush(repositoryUrl, 'master', {cwd});
|
||||
await gitCheckout('next', true, {cwd});
|
||||
await gitPush('origin', 'next', {cwd});
|
||||
await gitCheckout('master', false, {cwd});
|
||||
|
||||
const lastRelease = {
|
||||
name: 'v1.0.0',
|
||||
version: '1.0.0',
|
||||
gitHead: commits[commits.length - 1].hash,
|
||||
gitTag: 'v1.0.0',
|
||||
channel: undefined,
|
||||
};
|
||||
const nextRelease = {
|
||||
name: 'v2.0.0',
|
||||
type: 'major',
|
||||
version: '2.0.0',
|
||||
name: 'v1.2.0',
|
||||
type: 'minor',
|
||||
version: '1.2.0',
|
||||
gitHead: await getGitHead({cwd}),
|
||||
gitTag: 'v2.0.0',
|
||||
gitTag: 'v1.2.0',
|
||||
channel: undefined,
|
||||
};
|
||||
const analyzeCommits = stub().resolves(nextRelease.type);
|
||||
@@ -1170,19 +1163,21 @@ test('Accept "undefined" value returned by the "generateNotes" plugins', async t
|
||||
const generateNotes1 = stub().resolves();
|
||||
const notes2 = 'Release notes 2';
|
||||
const generateNotes2 = stub().resolves(notes2);
|
||||
const publish = stub().resolves();
|
||||
const publish = stub().resolves(false);
|
||||
const addChannel = stub().resolves(false);
|
||||
const success = stub().resolves();
|
||||
|
||||
const options = {
|
||||
branches: ['master'],
|
||||
branches: ['master', 'next'],
|
||||
repositoryUrl,
|
||||
verifyConditions: stub().resolves(),
|
||||
analyzeCommits,
|
||||
verifyRelease,
|
||||
generateNotes: [generateNotes1, generateNotes2],
|
||||
addChannel: stub().resolves(),
|
||||
addChannel,
|
||||
prepare: stub().resolves(),
|
||||
publish,
|
||||
success: stub().resolves(),
|
||||
success,
|
||||
fail: stub().resolves(),
|
||||
};
|
||||
|
||||
@@ -1200,20 +1195,15 @@ test('Accept "undefined" value returned by the "generateNotes" plugins', async t
|
||||
);
|
||||
|
||||
t.is(analyzeCommits.callCount, 1);
|
||||
t.deepEqual(analyzeCommits.args[0][1].lastRelease, lastRelease);
|
||||
|
||||
t.is(verifyRelease.callCount, 1);
|
||||
t.deepEqual(verifyRelease.args[0][1].lastRelease, lastRelease);
|
||||
|
||||
t.is(generateNotes1.callCount, 1);
|
||||
t.deepEqual(generateNotes1.args[0][1].lastRelease, lastRelease);
|
||||
|
||||
t.is(generateNotes2.callCount, 1);
|
||||
t.deepEqual(generateNotes2.args[0][1].lastRelease, lastRelease);
|
||||
|
||||
t.is(generateNotes1.callCount, 2);
|
||||
t.is(generateNotes2.callCount, 2);
|
||||
t.is(addChannel.callCount, 1);
|
||||
t.is(publish.callCount, 1);
|
||||
t.deepEqual(publish.args[0][1].lastRelease, lastRelease);
|
||||
t.is(publish.args[0][1].nextRelease.notes, notes2);
|
||||
t.is(success.callCount, 2);
|
||||
t.deepEqual(publish.args[0][1].nextRelease, {...nextRelease, notes: notes2});
|
||||
t.deepEqual(success.args[0][1].releases, [{pluginName: '[Function: proxy]'}]);
|
||||
t.deepEqual(success.args[1][1].releases, [{pluginName: '[Function: proxy]'}]);
|
||||
});
|
||||
|
||||
test('Returns false if triggered by a PR', async t => {
|
||||
|
||||
@@ -33,42 +33,67 @@ test('tagsToVersions', t => {
|
||||
|
||||
test('isMajorRange', t => {
|
||||
t.false(isMajorRange('1.1.x'));
|
||||
t.false(isMajorRange('1.11.x'));
|
||||
t.false(isMajorRange('11.1.x'));
|
||||
t.false(isMajorRange('11.11.x'));
|
||||
t.false(isMajorRange('1.1.X'));
|
||||
t.false(isMajorRange('1.1.0'));
|
||||
|
||||
t.true(isMajorRange('1.x.x'));
|
||||
t.true(isMajorRange('11.x.x'));
|
||||
t.true(isMajorRange('1.X.X'));
|
||||
t.true(isMajorRange('1.x'));
|
||||
t.true(isMajorRange('11.x'));
|
||||
t.true(isMajorRange('1.X'));
|
||||
});
|
||||
|
||||
test('isMaintenanceRange', t => {
|
||||
t.true(isMaintenanceRange('1.1.x'));
|
||||
t.true(isMaintenanceRange('11.1.x'));
|
||||
t.true(isMaintenanceRange('11.11.x'));
|
||||
t.true(isMaintenanceRange('1.11.x'));
|
||||
t.true(isMaintenanceRange('1.x.x'));
|
||||
t.true(isMaintenanceRange('11.x.x'));
|
||||
t.true(isMaintenanceRange('1.x'));
|
||||
t.true(isMaintenanceRange('11.x'));
|
||||
t.true(isMaintenanceRange('1.1.X'));
|
||||
t.true(isMaintenanceRange('1.X.X'));
|
||||
t.true(isMaintenanceRange('1.X'));
|
||||
|
||||
t.false(isMaintenanceRange('1.1.0'));
|
||||
t.false(isMaintenanceRange('11.1.0'));
|
||||
t.false(isMaintenanceRange('1.11.0'));
|
||||
t.false(isMaintenanceRange('11.11.0'));
|
||||
t.false(isMaintenanceRange('~1.0.0'));
|
||||
t.false(isMaintenanceRange('^1.0.0'));
|
||||
});
|
||||
|
||||
test('getUpperBound', t => {
|
||||
t.is(getUpperBound('1.x.x'), '2.0.0');
|
||||
t.is(getUpperBound('1.X.X'), '2.0.0');
|
||||
t.is(getUpperBound('10.x.x'), '11.0.0');
|
||||
t.is(getUpperBound('1.x'), '2.0.0');
|
||||
t.is(getUpperBound('10.x'), '11.0.0');
|
||||
t.is(getUpperBound('1.0.x'), '1.1.0');
|
||||
t.is(getUpperBound('10.0.x'), '10.1.0');
|
||||
t.is(getUpperBound('10.10.x'), '10.11.0');
|
||||
t.is(getUpperBound('1.0.0'), '1.0.0');
|
||||
t.is(getUpperBound('10.0.0'), '10.0.0');
|
||||
|
||||
t.is(getUpperBound('foo'), undefined);
|
||||
});
|
||||
|
||||
test('getLowerBound', t => {
|
||||
t.is(getLowerBound('1.x.x'), '1.0.0');
|
||||
t.is(getLowerBound('1.X.X'), '1.0.0');
|
||||
t.is(getLowerBound('10.x.x'), '10.0.0');
|
||||
t.is(getLowerBound('1.x'), '1.0.0');
|
||||
t.is(getLowerBound('10.x'), '10.0.0');
|
||||
t.is(getLowerBound('1.0.x'), '1.0.0');
|
||||
t.is(getLowerBound('10.0.x'), '10.0.0');
|
||||
t.is(getLowerBound('1.10.x'), '1.10.0');
|
||||
t.is(getLowerBound('1.0.0'), '1.0.0');
|
||||
t.is(getLowerBound('10.0.0'), '10.0.0');
|
||||
|
||||
t.is(getLowerBound('foo'), undefined);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user