feat: pass cwd and env context to plugins

- Allow to run semantic-release (via API) from anywhere passing the current working directory.
- Allows to simplify the tests and to run them in parallel in both the core and plugins.
This commit is contained in:
Pierre Vanduynslager
2018-07-17 00:42:04 -04:00
parent 12e4155cd3
commit a94e08de9a
32 changed files with 1361 additions and 1332 deletions
+148 -168
View File
@@ -1,15 +1,19 @@
import path from 'path';
import proxyquire from 'proxyquire';
import test from 'ava';
import {escapeRegExp} from 'lodash';
import {writeJson, readJson} from 'fs-extra';
import {stub} from 'sinon';
import execa from 'execa';
import {SECRET_REPLACEMENT} from '../lib/definitions/constants';
import {gitHead as getGitHead, gitTagHead, gitRepo, gitCommits, gitRemoteTagHead, gitPush} from './helpers/git-utils';
import gitbox from './helpers/gitbox';
import mockServer from './helpers/mockserver';
import npmRegistry from './helpers/npm-registry';
import semanticRelease from '..';
/* eslint camelcase: ["error", {properties: "never"}] */
const requireNoCache = proxyquire.noPreserveCache();
// Environment variables used with semantic-release cli (similar to what a user would setup)
const env = {
GH_TOKEN: gitbox.gitCredential,
@@ -17,86 +21,40 @@ const env = {
NPM_EMAIL: 'integration@test.com',
NPM_USERNAME: 'integration',
NPM_PASSWORD: 'suchsecure',
TRAVIS: 'true',
CI: 'true',
TRAVIS_BRANCH: 'master',
TRAVIS_PULL_REQUEST: 'false',
};
// Environment variables used only for the local npm command used to do verification
const testEnv = Object.assign({}, process.env, {
const testEnv = {
...process.env,
npm_config_registry: npmRegistry.url,
NPM_EMAIL: 'integration@test.com',
LEGACY_TOKEN: Buffer.from(`${process.env.NPM_USERNAME}:${process.env.NPM_PASSWORD}`, 'utf8').toString('base64'),
});
// Save the current process.env
const envBackup = Object.assign({}, process.env);
};
const cli = require.resolve('../bin/semantic-release');
const pluginError = require.resolve('./fixtures/plugin-error');
const pluginInheritedError = require.resolve('./fixtures/plugin-error-inherited');
// Save the current working diretory
const cwd = process.cwd();
// Disable logs during tests
stub(process.stdout, 'write');
stub(process.stderr, 'write');
const pluginLogEnv = require.resolve('./fixtures/plugin-log-env');
test.before(async () => {
// Start the Git server
await gitbox.start();
// Start the local NPM registry
await npmRegistry.start();
// Start Mock Server
await mockServer.start();
});
test.beforeEach(() => {
// Delete environment variables that could have been set on the machine running the tests
delete process.env.NPM_TOKEN;
delete process.env.NPM_USERNAME;
delete process.env.NPM_PASSWORD;
delete process.env.NPM_EMAIL;
delete process.env.GH_URL;
delete process.env.GITHUB_URL;
delete process.env.GH_PREFIX;
delete process.env.GITHUB_PREFIX;
delete process.env.GIT_CREDENTIALS;
delete process.env.GH_TOKEN;
delete process.env.GITHUB_TOKEN;
delete process.env.GL_TOKEN;
delete process.env.GITLAB_TOKEN;
process.env.TRAVIS = 'true';
process.env.CI = 'true';
process.env.TRAVIS_BRANCH = 'master';
process.env.TRAVIS_PULL_REQUEST = 'false';
// Delete all `npm_config` environment variable set by CI as they take precedence over the `.npmrc` because the process that runs the tests is started before the `.npmrc` is created
for (let i = 0, keys = Object.keys(process.env); i < keys.length; i++) {
if (keys[i].startsWith('npm_')) {
delete process.env[keys[i]];
}
}
});
test.afterEach.always(() => {
// Restore process.env
process.env = envBackup;
// Restore the current working directory
process.chdir(cwd);
await Promise.all([gitbox.start(), npmRegistry.start(), mockServer.start()]);
});
test.after.always(async () => {
// Stop the Git server
await gitbox.stop();
// Stop the local NPM registry
await npmRegistry.stop();
// Stop Mock Server
await mockServer.stop();
await Promise.all([gitbox.stop(), npmRegistry.stop(), mockServer.stop()]);
});
test.serial('Release patch, minor and major versions', async t => {
test('Release patch, minor and major versions', async t => {
const packageName = 'test-release';
const owner = 'git';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository and package.json');
const {repositoryUrl, authUrl} = await gitbox.createRepo(packageName);
const {cwd, repositoryUrl, authUrl} = await gitbox.createRepo(packageName);
// Create package.json in repository root
await writeJson('./package.json', {
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: repositoryUrl},
@@ -104,19 +62,18 @@ test.serial('Release patch, minor and major versions', async t => {
release: {success: false, fail: false},
});
// Create a npm-shrinkwrap.json file
await execa('npm', ['shrinkwrap'], {env: testEnv});
await execa('npm', ['shrinkwrap'], {env: testEnv, cwd});
/* No release */
let verifyMock = await mockServer.mock(
`/repos/${owner}/${packageName}`,
{headers: [{name: 'Authorization', values: [`token ${env.GH_TOKEN}`]}]},
{body: {permissions: {push: true}}, method: 'GET'}
);
t.log('Commit a chore');
await gitCommits(['chore: Init repository']);
await gitCommits(['chore: Init repository'], {cwd});
t.log('$ semantic-release');
let {stdout, code} = await execa(cli, [], {env});
let {stdout, code} = await execa(cli, [], {env, cwd});
t.regex(stdout, /There are no relevant changes, so no new version is released/);
t.is(code, 0);
@@ -137,26 +94,26 @@ test.serial('Release patch, minor and major versions', async t => {
);
t.log('Commit a feature');
await gitCommits(['feat: Initial commit']);
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release');
({stdout, code} = await execa(cli, [], {env}));
({stdout, code} = 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);
// Verify package.json and npm-shrinkwrap.json have been updated
t.is((await readJson('./package.json')).version, version);
t.is((await readJson('./npm-shrinkwrap.json')).version, version);
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
t.is((await readJson(path.resolve(cwd, 'npm-shrinkwrap.json'))).version, version);
// Retrieve the published package from the registry and check version and gitHead
let [, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv})).stdout
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv, cwd})).stdout
);
let gitHead = await getGitHead();
let gitHead = await getGitHead({cwd});
t.is(releasedVersion, version);
t.is(releasedGitHead, gitHead);
t.is(await gitTagHead(`v${version}`), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`), gitHead);
t.is(await gitTagHead(`v${version}`, {cwd}), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`, {cwd}), gitHead);
t.log(`+ released ${releasedVersion} with gitHead ${releasedGitHead}`);
await mockServer.verify(verifyMock);
@@ -179,26 +136,26 @@ test.serial('Release patch, minor and major versions', async t => {
);
t.log('Commit a fix');
await gitCommits(['fix: bar']);
await gitCommits(['fix: bar'], {cwd});
t.log('$ semantic-release');
({stdout, code} = await execa(cli, [], {env}));
({stdout, code} = 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);
// Verify package.json and npm-shrinkwrap.json have been updated
t.is((await readJson('./package.json')).version, version);
t.is((await readJson('./npm-shrinkwrap.json')).version, version);
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
t.is((await readJson(path.resolve(cwd, 'npm-shrinkwrap.json'))).version, version);
// Retrieve the published package from the registry and check version and gitHead
[, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv})).stdout
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv, cwd})).stdout
);
gitHead = await getGitHead();
gitHead = await getGitHead({cwd});
t.is(releasedVersion, version);
t.is(releasedGitHead, gitHead);
t.is(await gitTagHead(`v${version}`), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`), gitHead);
t.is(await gitTagHead(`v${version}`, {cwd}), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`, {cwd}), gitHead);
t.log(`+ released ${releasedVersion} with gitHead ${releasedGitHead}`);
await mockServer.verify(verifyMock);
@@ -221,26 +178,26 @@ test.serial('Release patch, minor and major versions', async t => {
);
t.log('Commit a feature');
await gitCommits(['feat: baz']);
await gitCommits(['feat: baz'], {cwd});
t.log('$ semantic-release');
({stdout, code} = await execa(cli, [], {env}));
({stdout, code} = 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);
// Verify package.json and npm-shrinkwrap.json have been updated
t.is((await readJson('./package.json')).version, version);
t.is((await readJson('./npm-shrinkwrap.json')).version, version);
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
t.is((await readJson(path.resolve(cwd, 'npm-shrinkwrap.json'))).version, version);
// Retrieve the published package from the registry and check version and gitHead
[, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv})).stdout
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv, cwd})).stdout
);
gitHead = await getGitHead();
gitHead = await getGitHead({cwd});
t.is(releasedVersion, version);
t.is(releasedGitHead, gitHead);
t.is(await gitTagHead(`v${version}`), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`), gitHead);
t.is(await gitTagHead(`v${version}`, {cwd}), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`, {cwd}), gitHead);
t.log(`+ released ${releasedVersion} with gitHead ${releasedGitHead}`);
await mockServer.verify(verifyMock);
@@ -263,97 +220,97 @@ test.serial('Release patch, minor and major versions', async t => {
);
t.log('Commit a breaking change');
await gitCommits(['feat: foo\n\n BREAKING CHANGE: bar']);
await gitCommits(['feat: foo\n\n BREAKING CHANGE: bar'], {cwd});
t.log('$ semantic-release');
({stdout, code} = await execa(cli, [], {env}));
({stdout, code} = 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);
// Verify package.json and npm-shrinkwrap.json have been updated
t.is((await readJson('./package.json')).version, version);
t.is((await readJson('./npm-shrinkwrap.json')).version, version);
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
t.is((await readJson(path.resolve(cwd, 'npm-shrinkwrap.json'))).version, version);
// Retrieve the published package from the registry and check version and gitHead
[, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv})).stdout
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv, cwd})).stdout
);
gitHead = await getGitHead();
gitHead = await getGitHead({cwd});
t.is(releasedVersion, version);
t.is(releasedGitHead, gitHead);
t.is(await gitTagHead(`v${version}`), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`), gitHead);
t.is(await gitTagHead(`v${version}`, {cwd}), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`, {cwd}), gitHead);
t.log(`+ released ${releasedVersion} with gitHead ${releasedGitHead}`);
await mockServer.verify(verifyMock);
await mockServer.verify(createReleaseMock);
});
test.serial('Exit with 1 if a plugin is not found', async t => {
test('Exit with 1 if a plugin is not found', async t => {
const packageName = 'test-plugin-not-found';
const owner = 'test-repo';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository');
await gitRepo();
await writeJson('./package.json', {
const {cwd} = await gitRepo();
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: `git+https://github.com/${owner}/${packageName}`},
release: {analyzeCommits: 'non-existing-path', success: false, fail: false},
});
const {code, stderr} = await t.throws(execa(cli, [], {env}));
const {code, stderr} = await t.throws(execa(cli, [], {env, cwd}));
t.is(code, 1);
t.regex(stderr, /Cannot find module/);
});
test.serial('Exit with 1 if a shareable config is not found', async t => {
test('Exit with 1 if a shareable config is not found', async t => {
const packageName = 'test-config-not-found';
const owner = 'test-repo';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository');
await gitRepo();
await writeJson('./package.json', {
const {cwd} = await gitRepo();
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: `git+https://github.com/${owner}/${packageName}`},
release: {extends: 'non-existing-path', success: false, fail: false},
});
const {code, stderr} = await t.throws(execa(cli, [], {env}));
const {code, stderr} = await t.throws(execa(cli, [], {env, cwd}));
t.is(code, 1);
t.regex(stderr, /Cannot find module/);
});
test.serial('Exit with 1 if a shareable config reference a not found plugin', async t => {
test('Exit with 1 if a shareable config reference a not found plugin', async t => {
const packageName = 'test-config-ref-not-found';
const owner = 'test-repo';
const shareable = {analyzeCommits: 'non-existing-path'};
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository');
await gitRepo();
await writeJson('./package.json', {
const {cwd} = await gitRepo();
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: `git+https://github.com/${owner}/${packageName}`},
release: {extends: './shareable.json', success: false, fail: false},
});
await writeJson('./shareable.json', shareable);
await writeJson(path.resolve(cwd, 'shareable.json'), shareable);
const {code, stderr} = await t.throws(execa(cli, [], {env}));
const {code, stderr} = await t.throws(execa(cli, [], {env, cwd}));
t.is(code, 1);
t.regex(stderr, /Cannot find module/);
});
test.serial('Dry-run', async t => {
test('Dry-run', async t => {
const packageName = 'test-dry-run';
const owner = 'git';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository and package.json');
const {repositoryUrl} = await gitbox.createRepo(packageName);
const {cwd, repositoryUrl} = await gitbox.createRepo(packageName);
// Create package.json in repository root
await writeJson('./package.json', {
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: repositoryUrl},
@@ -369,29 +326,30 @@ test.serial('Dry-run', async t => {
);
const version = '1.0.0';
t.log('Commit a feature');
await gitCommits(['feat: Initial commit']);
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release -d');
const {stdout, code} = await execa(cli, ['-d'], {env});
const {stdout, code} = 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);
// Verify package.json and has not been modified
t.is((await readJson('./package.json')).version, '0.0.0-dev');
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, '0.0.0-dev');
await mockServer.verify(verifyMock);
});
test.serial('Allow local releases with "noCi" option', async t => {
delete process.env.TRAVIS;
delete process.env.CI;
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';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository and package.json');
const {repositoryUrl, authUrl} = await gitbox.createRepo(packageName);
const {cwd, repositoryUrl, authUrl} = await gitbox.createRepo(packageName);
// Create package.json in repository root
await writeJson('./package.json', {
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: repositoryUrl},
@@ -416,39 +374,39 @@ test.serial('Allow local releases with "noCi" option', async t => {
);
t.log('Commit a feature');
await gitCommits(['feat: Initial commit']);
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release --no-ci');
const {stdout, code} = await execa(cli, ['--no-ci'], {env});
const {stdout, code} = 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);
// Verify package.json and has been updated
t.is((await readJson('./package.json')).version, version);
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
// Retrieve the published package from the registry and check version and gitHead
const [, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv})).stdout
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv, cwd})).stdout
);
const gitHead = await getGitHead();
const gitHead = await getGitHead({cwd});
t.is(releasedVersion, version);
t.is(releasedGitHead, gitHead);
t.is(await gitTagHead(`v${version}`), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`), gitHead);
t.is(await gitTagHead(`v${version}`, {cwd}), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`, {cwd}), gitHead);
t.log(`+ released ${releasedVersion} with gitHead ${releasedGitHead}`);
await mockServer.verify(verifyMock);
await mockServer.verify(createReleaseMock);
});
test.serial('Pass options via CLI arguments', async t => {
test('Pass options via CLI arguments', async t => {
const packageName = 'test-cli';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository and package.json');
const {repositoryUrl, authUrl} = await gitbox.createRepo(packageName);
const {cwd, repositoryUrl, authUrl} = await gitbox.createRepo(packageName);
// Create package.json in repository root
await writeJson('./package.json', {
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: repositoryUrl},
@@ -458,7 +416,7 @@ test.serial('Pass options via CLI arguments', async t => {
/* Initial release */
const version = '1.0.0';
t.log('Commit a feature');
await gitCommits(['feat: Initial commit']);
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release');
const {stdout, code} = await execa(
cli,
@@ -473,34 +431,38 @@ test.serial('Pass options via CLI arguments', async t => {
false,
'--debug',
],
{env}
{env, cwd}
);
t.regex(stdout, new RegExp(`Publishing version ${version} to npm registry`));
t.is(code, 0);
// Verify package.json and has been updated
t.is((await readJson('./package.json')).version, version);
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
// Retrieve the published package from the registry and check version and gitHead
const [, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv})).stdout
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv, cwd})).stdout
);
const gitHead = await getGitHead();
const gitHead = await getGitHead({cwd});
t.is(releasedVersion, version);
t.is(releasedGitHead, gitHead);
t.is(await gitTagHead(`v${version}`), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`), gitHead);
t.is(await gitTagHead(`v${version}`, {cwd}), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`, {cwd}), gitHead);
t.log(`+ released ${releasedVersion} with gitHead ${releasedGitHead}`);
});
test.serial('Run via JS API', async t => {
test('Run via JS API', async t => {
const semanticRelease = requireNoCache('..', {
'./lib/logger': {log: () => {}, error: () => {}, stdout: () => {}},
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
});
const packageName = 'test-js-api';
const owner = 'git';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository and package.json');
const {repositoryUrl, authUrl} = await gitbox.createRepo(packageName);
const {cwd, repositoryUrl, authUrl} = await gitbox.createRepo(packageName);
// Create package.json in repository root
await writeJson('./package.json', {
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: repositoryUrl},
@@ -523,38 +485,36 @@ test.serial('Run via JS API', async t => {
{body: {html_url: `release-url/${version}`}}
);
process.env = Object.assign(process.env, env);
t.log('Commit a feature');
await gitCommits(['feat: Initial commit']);
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ Call semantic-release via API');
await semanticRelease({fail: false, success: false});
await semanticRelease({fail: false, success: false}, {cwd, env});
// Verify package.json and has been updated
t.is((await readJson('./package.json')).version, version);
t.is((await readJson(path.resolve(cwd, 'package.json'))).version, version);
// Retrieve the published package from the registry and check version and gitHead
const [, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv})).stdout
(await execa('npm', ['show', packageName, 'version', 'gitHead'], {env: testEnv, cwd})).stdout
);
const gitHead = await getGitHead();
const gitHead = await getGitHead({cwd});
t.is(releasedVersion, version);
t.is(releasedGitHead, gitHead);
t.is(await gitTagHead(`v${version}`), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`), gitHead);
t.is(await gitTagHead(`v${version}`, {cwd}), gitHead);
t.is(await gitRemoteTagHead(authUrl, `v${version}`, {cwd}), gitHead);
t.log(`+ released ${releasedVersion} with gitHead ${releasedGitHead}`);
await mockServer.verify(verifyMock);
await mockServer.verify(createReleaseMock);
});
test.serial('Log unexpected errors from plugins and exit with 1', async t => {
test('Log unexpected errors from plugins and exit with 1', async t => {
const packageName = 'test-unexpected-error';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository and package.json');
const {repositoryUrl} = await gitbox.createRepo(packageName);
const {cwd, repositoryUrl} = await gitbox.createRepo(packageName);
// Create package.json in repository root
await writeJson('./package.json', {
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: repositoryUrl},
@@ -563,9 +523,9 @@ test.serial('Log unexpected errors from plugins and exit with 1', async t => {
/* Initial release */
t.log('Commit a feature');
await gitCommits(['feat: Initial commit']);
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release');
const {stderr, code} = await execa(cli, [], {env, reject: false});
const {stderr, code} = 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
@@ -575,13 +535,13 @@ test.serial('Log unexpected errors from plugins and exit with 1', async t => {
t.is(code, 1);
});
test.serial('Log errors inheriting SemanticReleaseError and exit with 1', async t => {
test('Log errors inheriting SemanticReleaseError and exit with 1', async t => {
const packageName = 'test-inherited-error';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository and package.json');
const {repositoryUrl} = await gitbox.createRepo(packageName);
const {cwd, repositoryUrl} = await gitbox.createRepo(packageName);
// Create package.json in repository root
await writeJson('./package.json', {
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: repositoryUrl},
@@ -590,33 +550,53 @@ test.serial('Log errors inheriting SemanticReleaseError and exit with 1', async
/* Initial release */
t.log('Commit a feature');
await gitCommits(['feat: Initial commit']);
await gitCommits(['feat: Initial commit'], {cwd});
t.log('$ semantic-release');
const {stdout, code} = await execa(cli, [], {env, reject: false});
const {stdout, code} = await execa(cli, [], {env, cwd, reject: false});
// Verify the type and message are logged
t.regex(stdout, /EINHERITED Inherited error/);
t.is(code, 1);
});
test.serial('Exit with 1 if missing permission to push to the remote repository', async t => {
test('Exit with 1 if missing permission to push to the remote repository', async t => {
const packageName = 'unauthorized';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository');
await gitbox.createRepo(packageName);
await writeJson('./package.json', {name: packageName, version: '0.0.0-dev'});
const {cwd} = await gitbox.createRepo(packageName);
await writeJson(path.resolve(cwd, 'package.json'), {name: packageName, version: '0.0.0-dev'});
/* Initial release */
t.log('Commit a feature');
await gitCommits(['feat: Initial commit']);
await gitPush();
await gitCommits(['feat: Initial commit'], {cwd});
await gitPush('origin', 'master', {cwd});
t.log('$ semantic-release');
const {stdout, code} = await execa(
cli,
['--repository-url', 'http://user:wrong_pass@localhost:2080/git/unauthorized.git'],
{env: {...env, GH_TOKEN: 'user:wrong_pass'}, reject: false}
{env: {...env, GH_TOKEN: 'user:wrong_pass'}, cwd, reject: false}
);
// Verify the type and message are logged
t.regex(stdout, /EGITNOPERMISSION/);
t.is(code, 1);
});
test('Hide sensitive environment variable values from the logs', async t => {
const packageName = 'log-secret';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository');
const {cwd, repositoryUrl} = await gitbox.createRepo(packageName);
await writeJson(path.resolve(cwd, 'package.json'), {
name: packageName,
version: '0.0.0-dev',
repository: {url: repositoryUrl},
release: {verifyConditions: [pluginLogEnv], fail: false, success: false},
});
t.log('$ semantic-release');
const {stdout, stderr} = await execa(cli, [], {env: {...env, MY_TOKEN: 'secret token'}, cwd, reject: false});
t.regex(stdout, new RegExp(`Console: Exposing token ${escapeRegExp(SECRET_REPLACEMENT)}`));
t.regex(stdout, new RegExp(`Log: Exposing token ${escapeRegExp(SECRET_REPLACEMENT)}`));
t.regex(stderr, new RegExp(`Error: Console token ${escapeRegExp(SECRET_REPLACEMENT)}`));
t.regex(stderr, new RegExp(`Throw error: Exposing ${escapeRegExp(SECRET_REPLACEMENT)}`));
});