From c86045ca49999569081f8d53c0c746b4006be9f9 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2019 18:41:36 +0000 Subject: [PATCH 01/12] chore(package): update dockerode to version 3.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dcc36921..e31737af 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "clear-module": "^4.0.0", "codecov": "^3.0.0", "delay": "^4.0.0", - "dockerode": "^2.5.2", + "dockerode": "^3.0.0", "file-url": "^3.0.0", "fs-extra": "^8.0.0", "got": "^9.0.0", From 5986bf920ef84d03fe9fd3efd00cc28a3a42d30b Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2019 04:24:40 +0000 Subject: [PATCH 02/12] chore(package): update xo to version 0.25.0 --- index.js | 2 ++ lib/definitions/plugins.js | 2 ++ lib/get-git-auth-url.js | 2 +- lib/git.js | 2 +- package.json | 2 +- test/helpers/git-utils.js | 6 +++--- test/helpers/mockserver.js | 2 +- test/helpers/npm-registry.js | 2 +- 8 files changed, 12 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 8e37936f..66fc877c 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,5 @@ +/* eslint require-atomic-updates: off */ + const {template, pick} = require('lodash'); const marked = require('marked'); const TerminalRenderer = require('marked-terminal'); diff --git a/lib/definitions/plugins.js b/lib/definitions/plugins.js index 3d4478a9..31bae73b 100644 --- a/lib/definitions/plugins.js +++ b/lib/definitions/plugins.js @@ -1,3 +1,5 @@ +/* eslint require-atomic-updates: off */ + const {isString, isPlainObject} = require('lodash'); const {getGitHead} = require('../git'); const hideSensitive = require('../hide-sensitive'); diff --git a/lib/get-git-auth-url.js b/lib/get-git-auth-url.js index 4495d95d..cc7a3548 100644 --- a/lib/get-git-auth-url.js +++ b/lib/get-git-auth-url.js @@ -41,7 +41,7 @@ module.exports = async ({cwd, env, options: {repositoryUrl, branch}}) => { // Test if push is allowed without transforming the URL (e.g. is ssh keys are set up) try { await verifyAuth(repositoryUrl, branch, {cwd, env}); - } catch (error) { + } catch (_) { const envVar = Object.keys(GIT_TOKENS).find(envVar => !isNil(env[envVar])); const gitCredentials = `${GIT_TOKENS[envVar] || ''}${env[envVar] || ''}`; diff --git a/lib/git.js b/lib/git.js index 95a0f7a2..faba17ca 100644 --- a/lib/git.js +++ b/lib/git.js @@ -63,7 +63,7 @@ async function isRefInHistory(ref, execaOpts) { async function fetch(repositoryUrl, execaOpts) { try { await execa('git', ['fetch', '--unshallow', '--tags', repositoryUrl], execaOpts); - } catch (error) { + } catch (_) { await execa('git', ['fetch', '--tags', repositoryUrl], execaOpts); } } diff --git a/package.json b/package.json index e31737af..38adbc1a 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "sinon": "^7.2.7", "stream-buffers": "^3.0.2", "tempy": "^0.3.0", - "xo": "^0.24.0" + "xo": "^0.25.0" }, "engines": { "node": ">=8.3" diff --git a/test/helpers/git-utils.js b/test/helpers/git-utils.js index 8d39c161..9dd4b897 100644 --- a/test/helpers/git-utils.js +++ b/test/helpers/git-utils.js @@ -100,10 +100,10 @@ export async function gitGetCommits(from, execaOpts) { * Checkout a branch on the current git repository. * * @param {String} branch Branch name. - * @param {Boolean} create `true` to create the branch, `false` to checkout an existing branch. + * @param {Boolean} create to create the branch, `false` to checkout an existing branch. * @param {Object} [execaOpts] Options to pass to `execa`. */ -export async function gitCheckout(branch, create = true, execaOpts) { +export async function gitCheckout(branch, create, execaOpts) { await execa('git', create ? ['checkout', '-b', branch] : ['checkout', branch], execaOpts); } @@ -224,6 +224,6 @@ export async function gitCommitTag(gitHead, execaOpts) { * * @throws {Error} if the push failed. */ -export async function gitPush(repositoryUrl = 'origin', branch = 'master', execaOpts) { +export async function gitPush(repositoryUrl, branch, execaOpts) { await execa('git', ['push', '--tags', repositoryUrl, `HEAD:${branch}`], execaOpts); } diff --git a/test/helpers/mockserver.js b/test/helpers/mockserver.js index f7a6aaca..72ee155f 100644 --- a/test/helpers/mockserver.js +++ b/test/helpers/mockserver.js @@ -30,7 +30,7 @@ async function start() { minTimeout: 1000, factor: 2, }); - } catch (error) { + } catch (_) { throw new Error(`Couldn't start mock-server after 2 min`); } } diff --git a/test/helpers/npm-registry.js b/test/helpers/npm-registry.js index e01fcc3e..ee80bfbc 100644 --- a/test/helpers/npm-registry.js +++ b/test/helpers/npm-registry.js @@ -39,7 +39,7 @@ async function start() { minTimeout: 1000, factor: 2, }); - } catch (error) { + } catch (_) { throw new Error(`Couldn't start npm-registry-docker after 2 min`); } From 0e24022608ff3387a1f8459d3738376442e877aa Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Fri, 27 Sep 2019 06:06:46 +0000 Subject: [PATCH 03/12] fix(package): update read-pkg-up to version 7.0.0 --- lib/get-config.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/get-config.js b/lib/get-config.js index 45073bcd..3423ad6c 100644 --- a/lib/get-config.js +++ b/lib/get-config.js @@ -85,6 +85,6 @@ module.exports = async (context, opts) => { }; async function pkgRepoUrl(opts) { - const {package: pkg} = (await readPkgUp(opts)) || {}; - return pkg && (isPlainObject(pkg.repository) ? pkg.repository.url : pkg.repository); + const {packageJson} = (await readPkgUp(opts)) || {}; + return packageJson && (isPlainObject(packageJson.repository) ? packageJson.repository.url : packageJson.repository); } diff --git a/package.json b/package.json index 38adbc1a..88d3aaae 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "marked-terminal": "^3.2.0", "p-locate": "^4.0.0", "p-reduce": "^2.0.0", - "read-pkg-up": "^6.0.0", + "read-pkg-up": "^7.0.0", "resolve-from": "^5.0.0", "semver": "^6.0.0", "signale": "^1.2.1", From 9f2ec79d67be41211f2f110ddc2e3e45bca8c6db Mon Sep 17 00:00:00 2001 From: Pierre Vanduynslager Date: Wed, 9 Oct 2019 16:31:00 -0400 Subject: [PATCH 04/12] docs: limit list of suggested tools for commit linting --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9220f12f..a5a1049d 100644 --- a/README.md +++ b/README.md @@ -52,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. -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. +Tools such as [commitizen](https://github.com/commitizen/cz-cli) or [commitlint](https://github.com/conventional-changelog/commitlint) can be used to help contributors and enforce valid commit messages. Here is an example of the release type that will be done based on a commit messages: From 79d22a2556dc6263440c4a2652768fedda6cc064 Mon Sep 17 00:00:00 2001 From: knidarkness Date: Wed, 9 Oct 2019 23:29:49 +0300 Subject: [PATCH 05/12] fix: clarify message for EGITNOPERMISSION error --- lib/definitions/errors.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/definitions/errors.js b/lib/definitions/errors.js index 69c2fb22..31268e1d 100644 --- a/lib/definitions/errors.js +++ b/lib/definitions/errors.js @@ -27,16 +27,17 @@ Please make sure to add the \`repositoryUrl\` to the [semantic-release configura )}).`, }), EGITNOPERMISSION: ({options}) => ({ - message: 'The push permission to the Git repository is required.', + message: 'Cannot push to the Git repository.', details: `**semantic-release** cannot push the version tag to the branch \`${ options.branch - }\` on remote Git repository with URL \`${options.repositoryUrl}\`. + }\` on the remote Git repository with URL \`${options.repositoryUrl}\`. -Please refer to the [authentication configuration documentation](${linkify( - 'docs/usage/ci-configuration.md#authentication' - )}) to configure the Git credentials on your CI environment and make sure the [repositoryUrl](${linkify( - 'docs/usage/configuration.md#repositoryurl' - )}) is configured with a [valid Git URL](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols).`, +This can be caused by: + - a misconfiguration of the [repositoryUrl](${linkify('docs/usage/configuration.md#repositoryurl')}) option + - the repository being unavailable + - or missing push permission for the user configured via the [Git credentials on your CI environment](${linkify( + 'docs/usage/ci-configuration.md#authentication' + )})`, }), EINVALIDTAGFORMAT: ({tagFormat}) => ({ message: 'Invalid `tagFormat` option.', From dc19dfa2e912ab3b60fa1bef017fac5af685d909 Mon Sep 17 00:00:00 2001 From: Alexander G Date: Thu, 10 Oct 2019 16:09:27 +0200 Subject: [PATCH 06/12] docs: remove unnecessarily apostrophe - improve punctuation of the how-to revert a release section --- docs/support/FAQ.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/support/FAQ.md b/docs/support/FAQ.md index 444d1528..81833cf9 100644 --- a/docs/support/FAQ.md +++ b/docs/support/FAQ.md @@ -141,11 +141,11 @@ See the [`@semantic-release/npm`](https://github.com/semantic-release/npm#semant If you have introduced a breaking bug in a release you have 2 options: - If you have a fix immediately ready, commit and push it (or merge it via a pull request) to the release branch -- Otherwise [revert the commit](https://git-scm.com/docs/git-revert) that introduced the bug and push the revert commit (or merge it via a pull request) to the release branch +- Otherwise, [revert the commit](https://git-scm.com/docs/git-revert) that introduced the bug and push the revert commit (or merge it via a pull request) to the release branch -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 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. +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 release. 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. From 4af854836668f5cfea9a176b006f416b965ee84c Mon Sep 17 00:00:00 2001 From: Pierre Vanduynslager Date: Fri, 18 Oct 2019 14:26:13 -0400 Subject: [PATCH 07/12] fix: ignore custom port when converting ssh repo URL to https --- lib/get-git-auth-url.js | 7 ++++++- test/get-git-auth-url.test.js | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/lib/get-git-auth-url.js b/lib/get-git-auth-url.js index cc7a3548..c0374f7c 100644 --- a/lib/get-git-auth-url.js +++ b/lib/get-git-auth-url.js @@ -48,9 +48,14 @@ module.exports = async ({cwd, env, options: {repositoryUrl, branch}}) => { if (gitCredentials) { // 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 {port, hostname, ...parsed} = parse( + match ? `ssh://${auth ? `${auth}@` : ''}${host}/${path}` : repositoryUrl + ); + return format({ - ...parse(match ? `ssh://${auth ? `${auth}@` : ''}${host}/${path}` : repositoryUrl), + ...parsed, auth: gitCredentials, + host: `${hostname}${protocol === 'ssh:' ? '' : port ? `:${port}` : ''}`, protocol: protocol && /http[^s]/.test(protocol) ? 'http' : 'https', }); } diff --git a/test/get-git-auth-url.test.js b/test/get-git-auth-url.test.js index 8312d2a0..b0db1cd1 100644 --- a/test/get-git-auth-url.test.js +++ b/test/get-git-auth-url.test.js @@ -140,6 +140,19 @@ test('Return the "http" formatted URL if "gitCredentials" is defined and reposit ); }); +test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "http" URL with custom port', async t => { + const {cwd} = await gitRepo(); + + t.is( + await getAuthUrl({ + cwd, + env: {...env, GIT_CREDENTIALS: 'user:pass'}, + options: {branch: 'master', repositoryUrl: 'http://host.null:8080/owner/repo.git'}, + }), + 'http://user:pass@host.null:8080/owner/repo.git' + ); +}); + test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git+https" URL', async t => { const {cwd} = await gitRepo(); @@ -166,6 +179,19 @@ test('Return the "http" formatted URL if "gitCredentials" is defined and reposit ); }); +test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "ssh" URL', async t => { + const {cwd} = await gitRepo(); + + t.is( + await getAuthUrl({ + cwd, + env: {...env, GIT_CREDENTIALS: 'user:pass'}, + options: {branch: 'master', repositoryUrl: 'ssh://git@host.null:2222/owner/repo.git'}, + }), + 'https://user:pass@host.null/owner/repo.git' + ); +}); + test('Return the "https" formatted URL if "gitCredentials" is defined with "GH_TOKEN"', async t => { const {cwd} = await gitRepo(); From 3438ec5c791776b32dc303dd11187a9c30e0f08a Mon Sep 17 00:00:00 2001 From: Pierre Vanduynslager Date: Fri, 18 Oct 2019 14:26:29 -0400 Subject: [PATCH 08/12] test: fix typo in test examples --- test/get-git-auth-url.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/get-git-auth-url.test.js b/test/get-git-auth-url.test.js index b0db1cd1..4401e34b 100644 --- a/test/get-git-auth-url.test.js +++ b/test/get-git-auth-url.test.js @@ -70,8 +70,8 @@ test('Convert shorthand URL', async t => { const {cwd} = await gitRepo(); t.is( - await getAuthUrl({cwd, env, options: {repositoryUrl: 'semanitc-release/semanitc-release'}}), - 'https://github.com/semanitc-release/semanitc-release.git' + await getAuthUrl({cwd, env, options: {repositoryUrl: 'semantic-release/semantic-release'}}), + 'https://github.com/semantic-release/semantic-release.git' ); }); @@ -82,9 +82,9 @@ test('Convert GitLab shorthand URL', async t => { await getAuthUrl({ cwd, env, - options: {branch: 'master', repositoryUrl: 'gitlab:semanitc-release/semanitc-release'}, + options: {branch: 'master', repositoryUrl: 'gitlab:semantic-release/semantic-release'}, }), - 'https://gitlab.com/semanitc-release/semanitc-release.git' + 'https://gitlab.com/semantic-release/semantic-release.git' ); }); From f645547f2f30eb59179f1d22da13612ba5090f38 Mon Sep 17 00:00:00 2001 From: "Alisson R. Perez" Date: Wed, 23 Oct 2019 14:47:24 -0300 Subject: [PATCH 09/12] docs(recipes): GitHub actions (#1317) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Natan Sągol --- docs/recipes/README.md | 1 + docs/recipes/github-actions.md | 68 ++++++++++++++++++++++++++++++++++ docs/usage/ci-configuration.md | 1 + 3 files changed, 70 insertions(+) create mode 100644 docs/recipes/github-actions.md diff --git a/docs/recipes/README.md b/docs/recipes/README.md index d839f0d5..000ddd7a 100644 --- a/docs/recipes/README.md +++ b/docs/recipes/README.md @@ -4,6 +4,7 @@ - [CircleCI 2.0 workflows](circleci-workflows.md) - [Travis CI](travis.md) - [GitLab CI](gitlab-ci.md) +- [GitHub Actions](github-actions.md) ## Git hosted services - [Git authentication with SSH keys](git-auth-ssh-keys.md) diff --git a/docs/recipes/github-actions.md b/docs/recipes/github-actions.md new file mode 100644 index 00000000..a92c2470 --- /dev/null +++ b/docs/recipes/github-actions.md @@ -0,0 +1,68 @@ +# Using semantic-release with [GitHub Actions](https://help.github.com/en/categories/automating-your-workflow-with-github-actions) + +## Environment variables + +The [Authentication](../usage/ci-configuration.md#authentication) environment variables can be configured with [Secret Variables](https://help.github.com/en/articles/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables). + +In this example an [`NPM_TOKEN`](https://docs.npmjs.com/creating-and-viewing-authentication-tokens) is required to publish a package to the npm registry. GitHub Actions [automatically populate](https://help.github.com/en/articles/virtual-environments-for-github-actions#github_token-secret) a [`GITHUB_TOKEN`](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) environment variable which can be used in Workflows. + +## Node project configuration + +[GitHub Actions](https://github.com/features/actions) support [Workflows](https://help.github.com/en/articles/configuring-workflows), allowing to run tests on multiple Node versions and publish a release only when all test pass. + +**Note**: The publish pipeline must run on [Node version >= 8.3](../support/FAQ.md#why-does-semantic-release-require-node-version--83). + +### `.github/workflows/release.yml` configuration for Node projects + +The following is a minimal configuration for [`semantic-release`](https://github.com/semantic-release/semantic-release) with a build running on Node 12 when a new commit is pushed to a `master` branch. See [Configuring a Workflow](https://help.github.com/en/articles/configuring-a-workflow) for additional configuration options. + +```yaml +name: Release +on: + push: + branches: + - master +jobs: + release: + name: Release + runs-on: ubuntu-18.04 + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 12 + - name: Install dependencies + run: npm ci + - name: Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npx semantic-release +``` + +## Pushing `package.json` changes to a `master` branch + +To keep `package.json` updated in the `master` branch, [`@semantic-release/git`](https://github.com/semantic-release/git) plugin can be used. + +**Note**: Automatically populated `GITHUB_TOKEN` cannot be used if branch protection is enabled for the target branch. It is **not** advised to mitigate this limitation by overriding an automatically populated `GITHUB_TOKEN` variable with a [Personal Access Tokens](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line), as it poses a security risk. Since Secret Variables are available for Workflows triggered by any branch, it becomes a potential vector of attack, where a Workflow triggered from a non-protected branch can expose and use a token with elevated permissions, yielding branch protection insignificant. One can use Personal Access Tokens in trusted environments, where all developers should have the ability to perform administrative actions in the given repository and branch protection is enabled solely for convenience purposes, to remind about required reviews or CI checks. + +## Trigger semantic-release on demand + +There is a way to trigger semantic-relase on demand. Use [`repository_dispatch`](https://help.github.com/en/articles/events-that-trigger-workflows#external-events-repository_dispatch) event to have control on when to generate a release by making an HTTP request, e.g.: + +```yaml +name: Release +on: + repository_dispatch: + types: [semantic-release] +jobs: +# ... +``` + +To trigger a release, call (with a [Personal Access Tokens](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) stored in `GITHUB_TOKEN` environment variable): + +``` +$ curl -v -H "Accept: application/vnd.github.everest-preview+json" -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/[org-name-or-username]/[repository]/dispatches -d '{ "event_type": "semantic-release" }' +``` diff --git a/docs/usage/ci-configuration.md b/docs/usage/ci-configuration.md index 486fc027..ae134af8 100644 --- a/docs/usage/ci-configuration.md +++ b/docs/usage/ci-configuration.md @@ -6,6 +6,7 @@ The `semantic-release` command must be executed only after all the tests in the Here is a few example of the CI services that can be used to achieve this: - [Travis Build Stages](https://docs.travis-ci.com/user/build-stages) - [CircleCI Workflows](https://circleci.com/docs/2.0/workflows) +- [GitHub Actions](https://github.com/features/actions) - [Codeship Deployment Pipelines](https://documentation.codeship.com/basic/builds-and-configuration/deployment-pipelines) - [GitLab Pipelines](https://docs.gitlab.com/ee/ci/pipelines.html#introduction-to-pipelines-and-jobs) - [Codefresh Pipelines](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines) From 2f3d93406991639d2497fb764be26d5ab2038ac5 Mon Sep 17 00:00:00 2001 From: Pierre Vanduynslager Date: Sat, 26 Oct 2019 00:11:30 -0400 Subject: [PATCH 10/12] fix: require Node.js >=8.16 --- .travis.yml | 2 +- docs/recipes/github-actions.md | 2 +- docs/recipes/gitlab-ci.md | 2 +- docs/support/FAQ.md | 10 +++++----- docs/support/node-version.md | 6 +++--- package.json | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 06f50217..59362c5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ services: node_js: - 12 - 10 - - 8.3 + - 8.16 # Trigger a push build on master and greenkeeper branches + PRs build on every branches # Avoid double build on PRs (See https://github.com/travis-ci/travis-ci/issues/1147) diff --git a/docs/recipes/github-actions.md b/docs/recipes/github-actions.md index a92c2470..c448a6d9 100644 --- a/docs/recipes/github-actions.md +++ b/docs/recipes/github-actions.md @@ -10,7 +10,7 @@ In this example an [`NPM_TOKEN`](https://docs.npmjs.com/creating-and-viewing-aut [GitHub Actions](https://github.com/features/actions) support [Workflows](https://help.github.com/en/articles/configuring-workflows), allowing to run tests on multiple Node versions and publish a release only when all test pass. -**Note**: The publish pipeline must run on [Node version >= 8.3](../support/FAQ.md#why-does-semantic-release-require-node-version--83). +**Note**: The publish pipeline must run on [Node version >= 8.16](../support/FAQ.md#why-does-semantic-release-require-node-version--816). ### `.github/workflows/release.yml` configuration for Node projects diff --git a/docs/recipes/gitlab-ci.md b/docs/recipes/gitlab-ci.md index 6671ecef..024e50c1 100644 --- a/docs/recipes/gitlab-ci.md +++ b/docs/recipes/gitlab-ci.md @@ -8,7 +8,7 @@ The [Authentication](../usage/ci-configuration.md#authentication) environment va GitLab CI supports [Pipelines](https://docs.gitlab.com/ee/ci/pipelines.html) allowing to test on multiple Node versions and publishing a release only when all test pass. -**Note**: The publish pipeline must run a [Node >= 8 version](../support/FAQ.md#why-does-semantic-release-require-node-version--83). +**Note**: The publish pipeline must run a [Node >= 8.16 version](../support/FAQ.md#why-does-semantic-release-require-node-version--816). ### `.gitlab-ci.yml` configuration for Node projects diff --git a/docs/support/FAQ.md b/docs/support/FAQ.md index 81833cf9..5ce9fdfe 100644 --- a/docs/support/FAQ.md +++ b/docs/support/FAQ.md @@ -38,7 +38,7 @@ Yes with the [dry-run options](../usage/configuration.md#dryrun) which prints to ## Can I use semantic-release with Yarn? -If you are using a [local](../usage/installation.md#local-installation) **semantic-release** installation and run multiple CI jobs with different versions, the `yarn install` command will fail on jobs running with Node < 8 as **semantic-release** requires [Node >= 8.3](#why-does-semantic-release-require-node-version--83) and specifies it in its `package.json`s [`engines`](https://docs.npmjs.com/files/package.json#engines) key. +If you are using a [local](../usage/installation.md#local-installation) **semantic-release** installation and run multiple CI jobs with different versions, the `yarn install` command will fail on jobs running with Node < 8 as **semantic-release** requires [Node >= 8.16](#why-does-semantic-release-require-node-version--816) and specifies it in its `package.json`s [`engines`](https://docs.npmjs.com/files/package.json#engines) key. The recommended solution is to use the [Yarn](https://yarnpkg.com) [--ignore-engines](https://yarnpkg.com/en/docs/cli/install#toc-yarn-install-ignore-engines) option to install the project dependencies on the CI environment, so Yarn will ignore the **semantic-release**'s `engines` key: @@ -48,7 +48,7 @@ $ yarn install --ignore-engines **Note**: Several CI services use Yarn by default if your repository contains a `yarn.lock` file. So you should override the install step to specify `yarn install --ignore-engines`. -Alternatively you can use a [global](../usage/installation.md#global-installation) **semantic-release** installation and make sure to install and run the `semantic-release` command only in a CI jobs running with Node >= 8.3. +Alternatively you can use a [global](../usage/installation.md#global-installation) **semantic-release** installation and make sure to install and run the `semantic-release` command only in a CI jobs running with Node >= 8.16. If your CI environment provides [nvm](https://github.com/creationix/nvm) you can switch to Node 8 before installing and running the `semantic-release` command: @@ -73,7 +73,7 @@ Yes, **semantic-release** is a Node CLI application but it can be used to publis To publish a non-Node package (without a `package.json`) you would need to: - Use a [global](../usage/installation.md#global-installation) **semantic-release** installation - Set **semantic-release** [options](../usage/configuration.md#options) via [CLI arguments or rc file](../usage/configuration.md#configuration) -- Make sure your CI job executing the `semantic-release` command has access to [Node >= 8](#why-does-semantic-release-require-node-version--83) to execute the `semantic-release` command +- Make sure your CI job executing the `semantic-release` command has access to [Node >= 8.16](#why-does-semantic-release-require-node-version--816) to execute the `semantic-release` command See the [CI configuration recipes](../recipes/README.md#ci-configurations) for more details on specific CI environments. @@ -232,9 +232,9 @@ See [“Introduction to SemVer” - Irina Gebauer](https://blog.greenkeeper.io/i In addition the [verify conditions step](../../README.md#release-steps) verifies that all necessary conditions for proceeding with a release are met, and a new release will be performed [only if all your tests pass](../usage/ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded). -## Why does semantic-release require Node version >= 8.3? +## Why does semantic-release require Node version >= 8.16? -**semantic-release** is written using the latest [ECMAScript 2017](https://www.ecma-international.org/publications/standards/Ecma-262.htm) features, without transpilation which **requires Node version 8.3 or higher**. +**semantic-release** is written using the latest [ECMAScript 2017](https://www.ecma-international.org/publications/standards/Ecma-262.htm) features, without transpilation which **requires Node version 8.16 or higher**. See [Node version requirement](./node-version.md#node-version-requirement) for more details and solutions. diff --git a/docs/support/node-version.md b/docs/support/node-version.md index 542af90b..633a8c72 100644 --- a/docs/support/node-version.md +++ b/docs/support/node-version.md @@ -1,6 +1,6 @@ # Node version requirement -**semantic-release** is written using the latest [ECMAScript 2017](https://www.ecma-international.org/publications/standards/Ecma-262.htm) features, without transpilation which requires **requires Node version 8.3 or higher**. +**semantic-release** is written using the latest [ECMAScript 2017](https://www.ecma-international.org/publications/standards/Ecma-262.htm) features, without transpilation which requires **requires Node version 8.16 or higher**. **semantic-release** is meant to be used in a CI environment as a development support tool, not as a production dependency. Therefore the only constraint is to run the `semantic-release` in a CI environment providing Node 8 or higher. @@ -8,9 +8,9 @@ See our [Node Support Policy](node-support-policy.md) for our long-term promise ## Recommended solution -### Run at least one CI job with Node >= 8.3 +### Run at least one CI job with Node >= 8.16 -The recommended approach is to run the `semantic-release` command from a CI job running on Node 8.3 or higher. This can either be a job used by your project to test on Node >= 8.3 or a dedicated job for the release steps. +The recommended approach is to run the `semantic-release` command from a CI job running on Node 8.16 or higher. This can either be a job used by your project to test on Node >= 8.16 or a dedicated job for the release steps. See [CI configuration](../usage/ci-configuration.md) and [CI configuration recipes](../recipes/README.md#ci-configurations) for more details. diff --git a/package.json b/package.json index 88d3aaae..c2827295 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "xo": "^0.25.0" }, "engines": { - "node": ">=8.3" + "node": ">=8.16" }, "files": [ "bin", From 1693073814c617cb7ddb44044bc2242de0ae76f8 Mon Sep 17 00:00:00 2001 From: Pierre Vanduynslager Date: Sat, 26 Oct 2019 00:21:22 -0400 Subject: [PATCH 11/12] fix(package): update execa to version 3.2.0 --- lib/git.js | 6 ++--- package.json | 2 +- test/cli.test.js | 42 +++++++++++++++--------------- test/integration.test.js | 56 ++++++++++++++++++++-------------------- 4 files changed, 53 insertions(+), 53 deletions(-) diff --git a/lib/git.js b/lib/git.js index faba17ca..88ef0e41 100644 --- a/lib/git.js +++ b/lib/git.js @@ -45,7 +45,7 @@ async function isRefInHistory(ref, execaOpts) { await execa('git', ['merge-base', '--is-ancestor', ref, 'HEAD'], execaOpts); return true; } catch (error) { - if (error.code === 1) { + if (error.exitCode === 1) { return false; } @@ -103,7 +103,7 @@ async function repoUrl(execaOpts) { */ async function isGitRepo(execaOpts) { try { - return (await execa('git', ['rev-parse', '--git-dir'], execaOpts)).code === 0; + return (await execa('git', ['rev-parse', '--git-dir'], execaOpts)).exitCode === 0; } catch (error) { debug(error); } @@ -161,7 +161,7 @@ async function push(repositoryUrl, execaOpts) { */ async function verifyTagName(tagName, execaOpts) { try { - return (await execa('git', ['check-ref-format', `refs/tags/${tagName}`], execaOpts)).code === 0; + return (await execa('git', ['check-ref-format', `refs/tags/${tagName}`], execaOpts)).exitCode === 0; } catch (error) { debug(error); } diff --git a/package.json b/package.json index c2827295..a90405ed 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "cosmiconfig": "^5.0.1", "debug": "^4.0.0", "env-ci": "^4.0.0", - "execa": "^1.0.0", + "execa": "^3.2.0", "figures": "^3.0.0", "find-versions": "^3.0.0", "get-stream": "^5.0.0", diff --git a/test/cli.test.js b/test/cli.test.js index 2ef1b128..216db79d 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -66,7 +66,7 @@ test.serial('Pass options to semantic-release API', async t => { ]; const cli = requireNoCache('../cli', {'.': run, process: {...process, argv}}); - const code = await cli(); + const exitCode = await cli(); t.is(run.args[0][0].branch, 'master'); t.is(run.args[0][0].repositoryUrl, 'https://github/com/owner/repo.git'); @@ -84,7 +84,7 @@ test.serial('Pass options to semantic-release API', async t => { t.is(run.args[0][0].debug, true); t.is(run.args[0][0].dryRun, true); - t.is(code, 0); + t.is(exitCode, 0); }); test.serial('Pass options to semantic-release API with alias arguments', async t => { @@ -108,7 +108,7 @@ test.serial('Pass options to semantic-release API with alias arguments', async t ]; const cli = requireNoCache('../cli', {'.': run, process: {...process, argv}}); - const code = await cli(); + const exitCode = await cli(); t.is(run.args[0][0].branch, 'master'); t.is(run.args[0][0].repositoryUrl, 'https://github/com/owner/repo.git'); @@ -117,7 +117,7 @@ test.serial('Pass options to semantic-release API with alias arguments', async t t.deepEqual(run.args[0][0].extends, ['config1', 'config2']); t.is(run.args[0][0].dryRun, true); - t.is(code, 0); + t.is(exitCode, 0); }); test.serial('Pass unknown options to semantic-release API', async t => { @@ -125,13 +125,13 @@ test.serial('Pass unknown options to semantic-release API', async t => { const argv = ['', '', '--bool', '--first-option', 'value1', '--second-option', 'value2', '--second-option', 'value3']; const cli = requireNoCache('../cli', {'.': run, process: {...process, argv}}); - const code = await cli(); + const exitCode = await cli(); t.is(run.args[0][0].bool, true); t.is(run.args[0][0].firstOption, 'value1'); t.deepEqual(run.args[0][0].secondOption, ['value2', 'value3']); - t.is(code, 0); + t.is(exitCode, 0); }); test.serial('Pass empty Array to semantic-release API for list option set to "false"', async t => { @@ -139,11 +139,11 @@ test.serial('Pass empty Array to semantic-release API for list option set to "fa const argv = ['', '', '--publish', 'false']; const cli = requireNoCache('../cli', {'.': run, process: {...process, argv}}); - const code = await cli(); + const exitCode = await cli(); t.deepEqual(run.args[0][0].publish, []); - t.is(code, 0); + t.is(exitCode, 0); }); test.serial('Do not set properties in option for which arg is not in command line', async t => { @@ -168,45 +168,45 @@ test.serial('Display help', async t => { const argv = ['', '', '--help']; const cli = requireNoCache('../cli', {'.': run, process: {...process, argv}}); - const code = await cli(); + const exitCode = await cli(); t.regex(t.context.logs, /Run automated package publishing/); - t.is(code, 0); + t.is(exitCode, 0); }); -test.serial('Return error code and prints help if called with a command', async t => { +test.serial('Return error exitCode and prints help if called with a command', async t => { const run = stub().resolves(true); const argv = ['', '', 'pre']; const cli = requireNoCache('../cli', {'.': run, process: {...process, argv}}); - const code = await cli(); + const exitCode = await cli(); t.regex(t.context.errors, /Run automated package publishing/); t.regex(t.context.errors, /Too many non-option arguments/); - t.is(code, 1); + t.is(exitCode, 1); }); -test.serial('Return error code if multiple plugin are set for single plugin', async t => { +test.serial('Return error exitCode if multiple plugin are set for single plugin', async t => { const run = stub().resolves(true); const argv = ['', '', '--analyze-commits', 'analyze1', 'analyze2']; const cli = requireNoCache('../cli', {'.': run, process: {...process, argv}}); - const code = await cli(); + const exitCode = await cli(); t.regex(t.context.errors, /Run automated package publishing/); t.regex(t.context.errors, /Too many non-option arguments/); - t.is(code, 1); + t.is(exitCode, 1); }); -test.serial('Return error code if semantic-release throw error', async t => { +test.serial('Return error exitCode if semantic-release throw error', async t => { const run = stub().rejects(new Error('semantic-release error')); const argv = ['', '']; const cli = requireNoCache('../cli', {'.': run, process: {...process, argv}}); - const code = await cli(); + const exitCode = await cli(); t.regex(t.context.errors, /semantic-release error/); - t.is(code, 1); + t.is(exitCode, 1); }); test.serial('Hide sensitive environment variable values from the logs', async t => { @@ -215,8 +215,8 @@ test.serial('Hide sensitive environment variable values from the logs', async t const argv = ['', '']; const cli = requireNoCache('../cli', {'.': run, process: {...process, argv, env: {...process.env, ...env}}}); - const code = await cli(); + const exitCode = await cli(); t.regex(t.context.errors, new RegExp(`Throw error: Exposing token ${escapeRegExp(SECRET_REPLACEMENT)}`)); - t.is(code, 1); + t.is(exitCode, 1); }); diff --git a/test/integration.test.js b/test/integration.test.js index e0d8f082..2a0daab8 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -72,9 +72,9 @@ test('Release patch, minor and major versions', async t => { t.log('Commit a chore'); await gitCommits(['chore: Init repository'], {cwd}); t.log('$ semantic-release'); - let {stdout, code} = await execa(cli, [], {env, cwd}); + let {stdout, exitCode} = await execa(cli, [], {env, cwd}); t.regex(stdout, /There are no relevant changes, so no new version is released/); - t.is(code, 0); + t.is(exitCode, 0); /* Initial release */ let version = '1.0.0'; @@ -95,10 +95,10 @@ test('Release patch, minor and major versions', async t => { t.log('Commit a feature'); await gitCommits(['feat: Initial commit'], {cwd}); t.log('$ semantic-release'); - ({stdout, code} = await execa(cli, [], {env, cwd})); + ({stdout, exitCode} = await execa(cli, [], {env, cwd})); t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`)); t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`)); - t.is(code, 0); + t.is(exitCode, 0); // Verify package.json and npm-shrinkwrap.json have been updated t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version); @@ -137,10 +137,10 @@ test('Release patch, minor and major versions', async t => { t.log('Commit a fix'); await gitCommits(['fix: bar'], {cwd}); t.log('$ semantic-release'); - ({stdout, code} = await execa(cli, [], {env, cwd})); + ({stdout, exitCode} = await execa(cli, [], {env, cwd})); t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`)); t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`)); - t.is(code, 0); + t.is(exitCode, 0); // Verify package.json and npm-shrinkwrap.json have been updated t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version); @@ -179,10 +179,10 @@ test('Release patch, minor and major versions', async t => { t.log('Commit a feature'); await gitCommits(['feat: baz'], {cwd}); t.log('$ semantic-release'); - ({stdout, code} = await execa(cli, [], {env, cwd})); + ({stdout, exitCode} = await execa(cli, [], {env, cwd})); t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`)); t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`)); - t.is(code, 0); + t.is(exitCode, 0); // Verify package.json and npm-shrinkwrap.json have been updated t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version); @@ -221,10 +221,10 @@ test('Release patch, minor and major versions', async t => { t.log('Commit a breaking change'); await gitCommits(['feat: foo\n\n BREAKING CHANGE: bar'], {cwd}); t.log('$ semantic-release'); - ({stdout, code} = await execa(cli, [], {env, cwd})); + ({stdout, exitCode} = await execa(cli, [], {env, cwd})); t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`)); t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`)); - t.is(code, 0); + t.is(exitCode, 0); // Verify package.json and npm-shrinkwrap.json have been updated t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version); @@ -258,8 +258,8 @@ test('Exit with 1 if a plugin is not found', async t => { release: {analyzeCommits: 'non-existing-path', success: false, fail: false}, }); - const {code, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd})); - t.is(code, 1); + const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd})); + t.is(exitCode, 1); t.regex(stderr, /Cannot find module/); }); @@ -276,8 +276,8 @@ test('Exit with 1 if a shareable config is not found', async t => { release: {extends: 'non-existing-path', success: false, fail: false}, }); - const {code, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd})); - t.is(code, 1); + const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd})); + t.is(exitCode, 1); t.regex(stderr, /Cannot find module/); }); @@ -297,8 +297,8 @@ test('Exit with 1 if a shareable config reference a not found plugin', async t = }); await writeJson(path.resolve(cwd, 'shareable.json'), shareable); - const {code, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd})); - t.is(code, 1); + const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd})); + t.is(exitCode, 1); t.regex(stderr, /Cannot find module/); }); @@ -327,11 +327,11 @@ test('Dry-run', async t => { t.log('Commit a feature'); await gitCommits(['feat: Initial commit'], {cwd}); t.log('$ semantic-release -d'); - const {stdout, code} = await execa(cli, ['-d'], {env, cwd}); + const {stdout, exitCode} = await execa(cli, ['-d'], {env, cwd}); t.regex(stdout, new RegExp(`There is no previous release, the next release version is ${version}`)); t.regex(stdout, new RegExp(`Release note for version ${version}`)); t.regex(stdout, /Initial commit/); - t.is(code, 0); + t.is(exitCode, 0); // Verify package.json and has not been modified t.is((await readJson(path.resolve(cwd, 'package.json'))).version, '0.0.0-dev'); @@ -375,10 +375,10 @@ test('Allow local releases with "noCi" option', async t => { t.log('Commit a feature'); await gitCommits(['feat: Initial commit'], {cwd}); t.log('$ semantic-release --no-ci'); - const {stdout, code} = await execa(cli, ['--no-ci'], {env: envNoCi, cwd}); + const {stdout, exitCode} = await execa(cli, ['--no-ci'], {env: envNoCi, cwd}); t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`)); t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`)); - t.is(code, 0); + t.is(exitCode, 0); // Verify package.json and has been updated t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version); @@ -417,7 +417,7 @@ test('Pass options via CLI arguments', async t => { t.log('Commit a feature'); await gitCommits(['feat: Initial commit'], {cwd}); t.log('$ semantic-release'); - const {stdout, code} = await execa( + const {stdout, exitCode} = await execa( cli, [ '--verify-conditions', @@ -433,7 +433,7 @@ test('Pass options via CLI arguments', async t => { {env, cwd} ); t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`)); - t.is(code, 0); + t.is(exitCode, 0); // Verify package.json and has been updated t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version); @@ -528,14 +528,14 @@ test('Log unexpected errors from plugins and exit with 1', async t => { t.log('Commit a feature'); await gitCommits(['feat: Initial commit'], {cwd}); t.log('$ semantic-release'); - const {stderr, code} = await execa(cli, [], {env, cwd, reject: false}); + const {stderr, exitCode} = await execa(cli, [], {env, cwd, reject: false}); // Verify the type and message are logged t.regex(stderr, /Error: a/); // Verify the the stacktrace is logged t.regex(stderr, new RegExp(pluginError)); // Verify the Error properties are logged t.regex(stderr, /errorProperty: 'errorProperty'/); - t.is(code, 1); + t.is(exitCode, 1); }); test('Log errors inheriting SemanticReleaseError and exit with 1', async t => { @@ -555,10 +555,10 @@ test('Log errors inheriting SemanticReleaseError and exit with 1', async t => { t.log('Commit a feature'); await gitCommits(['feat: Initial commit'], {cwd}); t.log('$ semantic-release'); - const {stderr, code} = await execa(cli, [], {env, cwd, reject: false}); + const {stderr, exitCode} = await execa(cli, [], {env, cwd, reject: false}); // Verify the type and message are logged t.regex(stderr, /EINHERITED Inherited error/); - t.is(code, 1); + t.is(exitCode, 1); }); test('Exit with 1 if missing permission to push to the remote repository', async t => { @@ -573,14 +573,14 @@ test('Exit with 1 if missing permission to push to the remote repository', async await gitCommits(['feat: Initial commit'], {cwd}); await gitPush('origin', 'master', {cwd}); t.log('$ semantic-release'); - const {stderr, code} = await execa( + const {stderr, exitCode} = await execa( cli, ['--repository-url', 'http://user:wrong_pass@localhost:2080/git/unauthorized.git'], {env: {...env, GH_TOKEN: 'user:wrong_pass'}, cwd, reject: false} ); // Verify the type and message are logged t.regex(stderr, /EGITNOPERMISSION/); - t.is(code, 1); + t.is(exitCode, 1); }); test('Hide sensitive environment variable values from the logs', async t => { From 9eaf9552c1f730caaa6eaffdc80c2d4b888bee2d Mon Sep 17 00:00:00 2001 From: Justin Dietz Date: Thu, 24 Oct 2019 10:02:46 -0700 Subject: [PATCH 12/12] docs(contributing): correct lint fix command --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5b560f37..8802ead5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -224,7 +224,7 @@ All the [semantic-release](https://github.com/semantic-release) repositories use Before pushing your code changes make sure there are no linting errors with `npm run lint`. **Tips**: -- Most linting errors can be automatically fixed with `npm run lint --fix`. +- Most linting errors can be automatically fixed with `npm run lint -- --fix`. - Install the [XO plugin](https://github.com/sindresorhus/xo#editor-plugins) for your editor to see linting errors directly in your editor and automatically fix them on save. ### Tests