Compare commits

...

13 Commits

Author SHA1 Message Date
Gregor Martynus
f66aa27dd7 WIP set extendEnv: false execa option 2021-01-20 13:52:15 -08:00
Gregor Martynus
daa25abccf WIP 2021-01-20 13:27:01 -08:00
Gregor Martynus
699875cedd wip 2021-01-20 13:19:47 -08:00
Gregor Martynus
2cc7d517b1 WIP 2021-01-20 13:19:08 -08:00
Gregor Martynus
7beb13af45 WIP reverting to simulating Travis CI test environment and setting GITHUB_API_URL 2021-01-20 13:11:06 -08:00
Gregor Martynus
1c85b88c9f WIP oops actually use processEnv 2021-01-20 12:46:26 -08:00
Gregor Martynus
fd5b64a99a WIP run integration tests sequentially 2021-01-20 12:42:41 -08:00
Gregor Martynus
9e83fa020d WIP ignore GitHub Action related environment variables, and fix "Use the repository URL as is if none of the given git credentials are valid" which should never have passed before but well here we are 2021-01-20 12:31:28 -08:00
Gregor Martynus
0ae2f632ff WIP trying to mock unset environment variables by setting them to empty strings 2021-01-20 12:08:33 -08:00
Gregor Martynus
9b1afca0f5 test(integration): do not mock environment variables with null
That results in the value `"null"` instead of undefined
2021-01-20 12:04:26 -08:00
Gregor Martynus
3c3b20c470 build(package): lock file 2021-01-20 11:21:02 -08:00
Josh Soref
3da96bbb90 ci: replace Travis environment variables with GitHub Action variables 2021-01-20 11:21:02 -08:00
Gregor Martynus
a2266ca47d ci: replace travis with actions, setup renovate 2021-01-20 11:21:02 -08:00
16 changed files with 13638 additions and 95 deletions

21
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: Release
on:
push:
branches:
- master
- next
- beta
- "*.x" # maintenance releases branches
jobs:
release:
name: release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: bahmutov/npm-install@v1
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_BOT_NPM_TOKEN }}

46
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,46 @@
name: Test
on:
push:
branches:
- master
- renovate/**
- 1692/setup-renovate-debug
pull_request:
types:
- opened
- synchronize
jobs:
test_matrix:
strategy:
matrix:
node-version:
# - 10
- 12
# - 14
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: git config --global user.name github-actions
- run: git config --global user.email github-actions@github.com
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- uses: bahmutov/npm-install@v1
- run: npx ava test/integration.test.js
# separate job to set as required in branch protection,
# as the build names above change each time Node versions change
test:
runs-on: ubuntu-latest
needs: test_matrix
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: bahmutov/npm-install@v1
- run: npm run lint

4
.gitignore vendored
View File

@ -125,10 +125,6 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
# Lockfiles
package-lock.json
yarn.lock
# Gitbook
_book

1
.npmrc
View File

@ -1 +0,0 @@
package-lock=false

View File

@ -1,11 +0,0 @@
version: ~> 1.0
services:
- docker
import:
- .travis/node.yml
- .travis/node-versions.yml
- .travis/semantic-release.yml
- .travis/greenkeeper.yml
- .travis/codecov.yml

View File

@ -1,2 +0,0 @@
after_success:
- npm run codecov

View File

@ -1,3 +0,0 @@
branches:
only:
- /^greenkeeper.*$/

View File

@ -1,3 +0,0 @@
node_js:
- 12
- 10.18

View File

@ -1,11 +0,0 @@
language: node_js
cache:
npm: false
# Retry install on fail to avoid failing a build on network/disk/external errors
install:
- travis_retry npm install
script:
- npm run test

View File

@ -1,15 +0,0 @@
branches:
only:
- master
- next
- beta
- /^\d+\.(\d+|x)(\.x)?$/
jobs:
include:
- stage: release
node_js: lts/*
install:
- travis_retry npm install
script:
- npm run semantic-release

View File

@ -1 +0,0 @@
--install.no-lockfile true

View File

@ -4,14 +4,8 @@
<a href="https://spectrum.chat/semantic-release">
<img alt="Join the community on Spectrum" src="https://withspectrum.github.io/badge/badge.svg">
</a>
<a href="https://travis-ci.org/semantic-release/semantic-release">
<img alt="Travis" src="https://img.shields.io/travis/semantic-release/semantic-release/master.svg">
</a>
<a href="https://codecov.io/gh/semantic-release/semantic-release">
<img alt="Codecov" src="https://img.shields.io/codecov/c/github/semantic-release/semantic-release/master.svg">
</a>
<a href="https://greenkeeper.io">
<img alt="Greenkeeper" src="https://badges.greenkeeper.io/semantic-release/semantic-release.svg">
<a href="https://github.com/semantic-release/semantic-release/actions?query=workflow%3ATest+branch%3Amaster">
<img alt="Build states" src="https://github.com/semantic-release/semantic-release/workflows/Test/badge.svg">
</a>
<a href="#badge">
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
@ -61,7 +55,7 @@ Tools such as [commitizen](https://github.com/commitizen/cz-cli) or [commitlint]
Here is an example of the release type that will be done based on a commit messages:
| Commit message | Release type |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------- |
| `fix(pencil): stop graphite breaking when too much pressure applied` | Patch Release |
| `feat(pencil): add 'graphiteWidth' option` | ~~Minor~~ Feature Release |
| `perf(pencil): remove graphiteWidth option`<br><br>`BREAKING CHANGE: The graphiteWidth option has been removed.`<br>`The default graphite width of 10mm is always used for performance reasons.` | ~~Major~~ Breaking Release |
@ -75,6 +69,7 @@ Here is an example of the release type that will be done based on a commit messa
For each new commits added to one of the release branches (for example `master`, `next`, `beta`), with `git push` or by merging a pull request or merging from another branch, a CI build is triggered and runs the `semantic-release` command to make a release if there are codebase changes since the last release that affect the package functionalities.
**semantic-release** offers various ways to control the timing, the content and the audience of published releases. See example workflows in the following recipes:
- [Using distribution channels](docs/recipes/distribution-channels.md#publishing-on-distribution-channels)
- [Maintenance releases](docs/recipes/maintenance-releases.md#publishing-maintenance-releases)
- [Pre-releases](docs/recipes/pre-releases.md#publishing-pre-releases)
@ -84,7 +79,7 @@ For each new commits added to one of the release branches (for example `master`,
After running the tests, the command `semantic-release` will execute the following steps:
| Step | Description |
|-------------------|---------------------------------------------------------------------------------------------------------------------------------|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Verify Conditions | Verify all the conditions to proceed with the release. |
| Get last release | Obtain the commit corresponding to the last release by analyzing [Git tags](https://git-scm.com/book/en/v2/Git-Basics-Tagging). |
| Analyze commits | Determine the type of release based on the commits added since the last release. |
@ -98,6 +93,7 @@ After running the tests, the command `semantic-release` will execute the followi
## Requirements
In order to use **semantic-release** you need:
- To host your code in a [Git repository](https://git-scm.com)
- Use a Continuous Integration service that allows you to [securely set up credentials](docs/usage/ci-configuration.md#authentication)
- Git CLI version [2.7.1 or higher](docs/support/FAQ.md#why-does-semantic-release-require-git-version--271) installed in your Continuous Integration environment
@ -160,7 +156,6 @@ Let people know that your package is published using **semantic-release** by inc
| ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| [Stephan Bönnemann](https://github.com/boennemann) | [Rolf Erik Lekang](https://github.com/relekang) | [Johannes Jörg Schmidt](https://github.com/jo) | [Finn Pauls](https://github.com/finnp) | [Christoph Witzko](https://github.com/christophwitzko) |
<p align="center">
<img alt="Kill all humans" src="media/bender.png">
</p>

View File

@ -21,6 +21,13 @@ See https://github.com/semantic-release/semantic-release/blob/master/docs/suppor
process.exit(1);
}
console.log("DEBUG START ==========")
console.log('process.env')
console.log(process.env)
console.log('envCi({ env: process.env })')
console.log(require('env-ci')({ env: process.env }))
console.log("DEBUG END ==========")
execa('git', ['--version'])
.then(({stdout}) => {
var gitVersion = findVersions(stdout)[0];

13513
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -122,7 +122,8 @@
"lint": "xo",
"pretest": "npm run lint",
"semantic-release": "./bin/semantic-release.js",
"test": "nyc ava -v"
"test": "nyc ava -v",
"test:ci": "nyc ava -v"
},
"xo": {
"prettier": true,
@ -130,5 +131,10 @@
"rules": {
"unicorn/string-content": "off"
}
},
"renovate": {
"extends": [
"github>semantic-release/.github"
]
}
}

View File

@ -1,5 +1,5 @@
const path = require('path');
const test = require('ava');
const { serial: test } = require('ava');
const proxyquire = require('proxyquire');
const {escapeRegExp} = require('lodash');
const {writeJson, readJson} = require('fs-extra');
@ -29,17 +29,24 @@ const npmRegistry = require('./helpers/npm-registry');
const requireNoCache = proxyquire.noPreserveCache();
// Environment variables used with semantic-release cli (similar to what a user would setup)
const {
GITHUB_ACTION,
GITHUB_TOKEN,
...processEnvWithoutGitHubActionsVariables
} = process.env
const env = {
...processEnvWithoutGitHubActionsVariables,
...npmRegistry.authEnv,
GH_TOKEN: gitbox.gitCredential,
GITHUB_URL: mockServer.url,
TRAVIS: 'true',
CI: 'true',
GH_TOKEN: gitbox.gitCredential,
TRAVIS: 'true',
TRAVIS_BRANCH: 'master',
TRAVIS_PULL_REQUEST: 'false',
GITHUB_API_URL: mockServer.url,
};
// Environment variables used only for the local npm command used to do verification
const testEnv = {
const npmTestEnv = {
...process.env,
...npmRegistry.authEnv,
npm_config_registry: npmRegistry.url,
@ -74,7 +81,7 @@ test('Release patch, minor and major versions', async (t) => {
release: {branches: ['master', 'next'], success: false, fail: false},
});
// Create a npm-shrinkwrap.json file
await execa('npm', ['shrinkwrap'], {env: testEnv, cwd});
await execa('npm', ['shrinkwrap'], {env: npmTestEnv, cwd, extendEnv: false});
/* No release */
let verifyMock = await mockServer.mock(
@ -85,7 +92,7 @@ test('Release patch, minor and major versions', async (t) => {
t.log('Commit a chore');
await gitCommits(['chore: Init repository'], {cwd});
t.log('$ semantic-release');
let {stdout, exitCode} = await execa(cli, [], {env, cwd});
let {stdout, exitCode} = await execa(cli, [], {env, cwd, extendEnv: false});
t.regex(stdout, /There are no relevant changes, so no new version is released/);
t.is(exitCode, 0);
@ -108,7 +115,7 @@ test('Release patch, minor and major versions', async (t) => {
t.log('Commit a feature');
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release');
({stdout, exitCode} = await execa(cli, [], {env, cwd}));
({stdout, exitCode} = await execa(cli, [], {env, cwd, extendEnv: false}));
t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`));
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
t.is(exitCode, 0);
@ -120,7 +127,7 @@ test('Release patch, minor and major versions', async (t) => {
// Retrieve the published package from the registry and check version and gitHead
let {
'dist-tags': {latest: releasedVersion},
} = await npmView(packageName, testEnv);
} = await npmView(packageName, npmTestEnv);
let head = await gitHead({cwd});
t.is(releasedVersion, version);
t.is(await gitTagHead(`v${version}`, {cwd}), head);
@ -149,7 +156,7 @@ test('Release patch, minor and major versions', async (t) => {
t.log('Commit a fix');
await gitCommits(['fix: bar'], {cwd});
t.log('$ semantic-release');
({stdout, exitCode} = await execa(cli, [], {env, cwd}));
({stdout, exitCode} = await execa(cli, [], {env, cwd, extendEnv: false}));
t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`));
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
t.is(exitCode, 0);
@ -161,7 +168,7 @@ test('Release patch, minor and major versions', async (t) => {
// Retrieve the published package from the registry and check version and gitHead
({
'dist-tags': {latest: releasedVersion},
} = await npmView(packageName, testEnv));
} = await npmView(packageName, npmTestEnv));
head = await gitHead({cwd});
t.is(releasedVersion, version);
t.is(await gitTagHead(`v${version}`, {cwd}), head);
@ -190,7 +197,7 @@ test('Release patch, minor and major versions', async (t) => {
t.log('Commit a feature');
await gitCommits(['feat: baz'], {cwd});
t.log('$ semantic-release');
({stdout, exitCode} = await execa(cli, [], {env, cwd}));
({stdout, exitCode} = await execa(cli, [], {env, cwd, extendEnv: false}));
t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`));
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
t.is(exitCode, 0);
@ -202,7 +209,7 @@ test('Release patch, minor and major versions', async (t) => {
// Retrieve the published package from the registry and check version and gitHead
({
'dist-tags': {latest: releasedVersion},
} = await npmView(packageName, testEnv));
} = await npmView(packageName, npmTestEnv));
head = await gitHead({cwd});
t.is(releasedVersion, version);
t.is(await gitTagHead(`v${version}`, {cwd}), head);
@ -233,7 +240,7 @@ test('Release patch, minor and major versions', async (t) => {
await gitPush('origin', 'next', {cwd});
await gitCommits(['feat: foo\n\n BREAKING CHANGE: bar'], {cwd});
t.log('$ semantic-release');
({stdout, exitCode} = await execa(cli, [], {env: {...env, TRAVIS_BRANCH: 'next'}, cwd}));
({stdout, exitCode} = await execa(cli, [], {env: {...env, TRAVIS_BRANCH: 'next'}, cwd, extendEnv: false}));
t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`));
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
t.is(exitCode, 0);
@ -245,7 +252,7 @@ test('Release patch, minor and major versions', async (t) => {
// Retrieve the published package from the registry and check version and gitHead
({
'dist-tags': {next: releasedVersion},
} = await npmView(packageName, testEnv));
} = await npmView(packageName, npmTestEnv));
head = await gitHead({cwd});
t.is(releasedVersion, version);
t.is(await gitGetNote(`v${version}`, {cwd}), '{"channels":["next"]}');
@ -283,7 +290,7 @@ test('Release patch, minor and major versions', async (t) => {
await merge('next', {cwd});
await gitPush('origin', 'master', {cwd});
t.log('$ semantic-release');
({stdout, exitCode} = await execa(cli, [], {env, cwd}));
({stdout, exitCode} = await execa(cli, [], {env, cwd, extendEnv: false}));
t.regex(stdout, new RegExp(`Updated GitHub release: release-url/${version}`));
t.regex(stdout, new RegExp(`Adding version ${version} to npm registry on dist-tag latest`));
t.is(exitCode, 0);
@ -293,7 +300,7 @@ test('Release patch, minor and major versions', async (t) => {
// Retrieve the published package from the registry and check version and gitHead
({
'dist-tags': {latest: releasedVersion},
} = await npmView(packageName, testEnv));
} = await npmView(packageName, npmTestEnv));
t.is(releasedVersion, version);
t.is(await gitGetNote(`v${version}`, {cwd}), '{"channels":["next",null]}');
t.is(await gitTagHead(`v${version}`, {cwd}), await gitTagHead(`v${version}`, {cwd}));
@ -318,7 +325,7 @@ test('Exit with 1 if a plugin is not found', async (t) => {
release: {analyzeCommits: 'non-existing-path', success: false, fail: false},
});
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd, extendEnv: false}));
t.is(exitCode, 1);
t.regex(stderr, /Cannot find module/);
});
@ -336,7 +343,7 @@ test('Exit with 1 if a shareable config is not found', async (t) => {
release: {extends: 'non-existing-path', success: false, fail: false},
});
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd, extendEnv: false}));
t.is(exitCode, 1);
t.regex(stderr, /Cannot find module/);
});
@ -357,7 +364,7 @@ test('Exit with 1 if a shareable config reference a not found plugin', async (t)
});
await writeJson(path.resolve(cwd, 'shareable.json'), shareable);
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
const {exitCode, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd, extendEnv: false}));
t.is(exitCode, 1);
t.regex(stderr, /Cannot find module/);
});
@ -387,7 +394,7 @@ test('Dry-run', async (t) => {
t.log('Commit a feature');
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release -d');
const {stdout, exitCode} = await execa(cli, ['-d'], {env, cwd});
const {stdout, exitCode} = await execa(cli, ['-d'], {env, cwd, extendEnv: false});
t.regex(stdout, new RegExp(`There is no previous release, the next release version is ${version}`));
t.regex(stdout, new RegExp(`Release note for version ${version}`));
t.regex(stdout, /Initial commit/);
@ -400,7 +407,6 @@ test('Dry-run', async (t) => {
test('Allow local releases with "noCi" option', async (t) => {
const envNoCi = {...env};
delete envNoCi.TRAVIS;
delete envNoCi.CI;
const packageName = 'test-no-ci';
const owner = 'git';
@ -435,7 +441,7 @@ test('Allow local releases with "noCi" option', async (t) => {
t.log('Commit a feature');
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release --no-ci');
const {stdout, exitCode} = await execa(cli, ['--no-ci'], {env: envNoCi, cwd});
const {stdout, exitCode} = await execa(cli, ['--no-ci'], {env: envNoCi, cwd, extendEnv: false});
t.regex(stdout, new RegExp(`Published GitHub release: release-url/${version}`));
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
t.is(exitCode, 0);
@ -444,7 +450,7 @@ test('Allow local releases with "noCi" option', async (t) => {
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
// Retrieve the published package from the registry and check version and gitHead
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, testEnv);
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, npmTestEnv);
const head = await gitHead({cwd});
t.is(releasedVersion, version);
@ -488,7 +494,7 @@ test('Pass options via CLI arguments', async (t) => {
false,
'--debug',
],
{env, cwd}
{env, cwd, extendEnv: false}
);
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
t.is(exitCode, 0);
@ -497,7 +503,7 @@ test('Pass options via CLI arguments', async (t) => {
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
// Retrieve the published package from the registry and check version and gitHead
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, testEnv);
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, npmTestEnv);
const head = await gitHead({cwd});
t.is(releasedVersion, version);
t.is(releasedGitHead, head);
@ -553,7 +559,7 @@ test('Run via JS API', async (t) => {
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
// Retrieve the published package from the registry and check version and gitHead
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, testEnv);
const {version: releasedVersion, gitHead: releasedGitHead} = await npmView(packageName, npmTestEnv);
const head = await gitHead({cwd});
t.is(releasedVersion, version);
t.is(releasedGitHead, head);
@ -582,7 +588,7 @@ test('Log unexpected errors from plugins and exit with 1', async (t) => {
t.log('Commit a feature');
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release');
const {stderr, exitCode} = await execa(cli, [], {env, cwd, reject: false});
const {stderr, exitCode} = await execa(cli, [], {env, cwd, reject: false, extendEnv: false});
// Verify the type and message are logged
t.regex(stderr, /Error: a/);
// Verify the the stacktrace is logged
@ -609,7 +615,7 @@ test('Log errors inheriting SemanticReleaseError and exit with 1', async (t) =>
t.log('Commit a feature');
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release');
const {stderr, exitCode} = await execa(cli, [], {env, cwd, reject: false});
const {stderr, exitCode} = await execa(cli, [], {env, cwd, reject: false, extendEnv: false});
// Verify the type and message are logged
t.regex(stderr, /EINHERITED Inherited error/);
t.is(exitCode, 1);
@ -630,7 +636,7 @@ test('Exit with 1 if missing permission to push to the remote repository', async
const {stderr, exitCode} = await execa(
cli,
['--repository-url', 'http://user:wrong_pass@localhost:2080/git/unauthorized.git'],
{env: {...env, GH_TOKEN: 'user:wrong_pass'}, cwd, reject: false}
{env: {...env, GH_TOKEN: 'user:wrong_pass'}, cwd, reject: false, extendEnv: false}
);
// Verify the type and message are logged
t.regex(stderr, /EGITNOPERMISSION/);
@ -650,7 +656,7 @@ test('Hide sensitive environment variable values from the logs', async (t) => {
});
t.log('$ semantic-release');
const {stdout, stderr} = await execa(cli, [], {env: {...env, MY_TOKEN: 'secret token'}, cwd, reject: false});
const {stdout, stderr} = await execa(cli, [], {env: {...env, MY_TOKEN: 'secret token'}, cwd, reject: false, extendEnv: false});
t.regex(stdout, new RegExp(`Console: Exposing token ${escapeRegExp(SECRET_REPLACEMENT)}`));
t.regex(stdout, new RegExp(`Log: Exposing token ${escapeRegExp(SECRET_REPLACEMENT)}`));
@ -680,7 +686,7 @@ test('Use the valid git credentials when multiple are provided', async (t) => {
test('Use the repository URL as is if none of the given git credentials are valid', async (t) => {
const {cwd} = await gitbox.createRepo('test-invalid-auth');
const dummyUrl = 'http://toto@localhost:2080/git/test-auth.git';
const dummyUrl = 'http://toto@localhost:2080/git/test-invalid-auth.git';
t.is(
await getAuthUrl({