Compare commits

..
Author SHA1 Message Date
Pierre Vanduynslager 390e966341 fix(package): update @semantic-release/npm to version 5.2.0-beta.3 2018-12-17 15:23:04 -05:00
Pierre Vanduynslager c1c96a87a3 fix(package): update @semantic-release/github to version 5.3.0-beta.5 2018-12-17 15:23:04 -05:00
Pierre Vanduynslager 725780bf0a fix(package): update @semantic-release/commit-analyzer to version 7.0.0-beta.2 2018-12-17 15:23:04 -05:00
Pierre Vanduynslager 9a023b4088 fix: call success plugin only once for releases added to a channel 2018-12-17 15:23:04 -05:00
Pierre Vanduynslager c22ae17a9b fix: on maintenance branch add to channel only version >= to start range 2018-12-17 15:23:04 -05:00
Pierre Vanduynslager 162b4b9e3b fix: remove confusing logs when searching for releases to add to a channel 2018-12-17 15:23:04 -05:00
Pierre Vanduynslager 9a04e64fab fix: fix range regexp to handle version with multiple digits 2018-12-16 19:05:08 -05:00
Pierre Vanduynslager 89663d3fcf fix: correctly handle skipped releases 2018-12-16 16:15:48 -05:00
Pierre Vanduynslager e1b418d0b5 build: fix Travis maintenance branch regexp 2018-12-14 23:40:59 -05:00
Pierre Vanduynslager 9a30f3542c fix(package): update @semantic-release/github 2018-12-14 22:29:26 -05:00
Pierre Vanduynslager d6731b9b27 fix(package): update @semantic-release/npm and @semantic-release/github 2018-12-14 19:26:25 -05:00
Pierre Vanduynslager e1c7269cb3 feat: allow addChannel plugins to return false in order to signify no release was done 2018-12-14 18:37:02 -05:00
Pierre Vanduynslager aa48514f85 refactor: remove unnecessary default of addChannel plugin 2018-12-14 18:37:02 -05:00
Pierre Vanduynslager 47484f5eb2 feat: allow publish plugins to return false in order to signify no release was done 2018-12-14 16:46:32 -05:00
Pierre Vanduynslager 2aa65ad668 docs: fix broken link in CircleCI recipe 2018-12-14 16:45:48 -05:00
Pierre Vanduynslager 0bfc7a974e docs: remove mentions of travis-deploy-once 2018-12-14 16:45:48 -05:00
greenkeeper[bot]andPierre Vanduynslager 28c21fbc93 chore(package): update p-retry to version 3.0.0 2018-12-14 16:45:48 -05:00
Pierre Vanduynslager 52ca0b391c fix: fix branch type regexp to handle version with multiple digits 2018-12-13 15:32:07 -05:00
Gregor Martynus 5d99e02254 docs(workflow-configuration): typo 2018-12-13 09:28:49 -08:00
18 changed files with 159 additions and 280 deletions
+1 -1
View File
@@ -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
-1
View File
@@ -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
+1 -1
View File
@@ -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
-95
View File
@@ -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
View File
@@ -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).
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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.
+13 -2
View File
@@ -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}`);
+4 -5
View File
@@ -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,
}),
}),
+1 -3
View File
@@ -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 {};
};
+9 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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",
+2 -1
View File
@@ -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 => {
-13
View File
@@ -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');
});
+28 -36
View File
@@ -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
View File
@@ -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 => {
+25
View File
@@ -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);
});