From 0d2d1f237654f0f2c63967f7942c3eb8eb7f8e75 Mon Sep 17 00:00:00 2001 From: Pierre Vanduynslager Date: Wed, 24 Jan 2018 02:18:36 -0500 Subject: [PATCH] fix: fix the `--no-ci` arg parsing The `noCi` is no properly set based on the `--no-ci` CLI arg and it is overwritten by the `noCi` option --- cli.js | 5 ++- index.js | 11 +++---- test/index.test.js | 6 ++-- test/integration.test.js | 71 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 10 deletions(-) diff --git a/cli.js b/cli.js index 1f8e1365..70f24901 100755 --- a/cli.js +++ b/cli.js @@ -48,8 +48,11 @@ module.exports = async () => { program.outputHelp(); process.exitCode = 1; } else { + const opts = program.opts(); + // Set the `noCi` options as commander.js sets the `ci` options instead (becasue args starts with `--no`) + opts.noCi = opts.ci === false ? true : undefined; // Remove option with undefined values, as commander.js sets non defined options as `undefined` - await require('.')(pickBy(program.opts(), value => !isUndefined(value))); + await require('.')(pickBy(opts, value => !isUndefined(value))); } } catch (err) { process.exitCode = 1; diff --git a/index.js b/index.js index fa829d1f..bf9e4cfa 100644 --- a/index.js +++ b/index.js @@ -9,13 +9,15 @@ const {gitHead: getGitHead, isGitRepo} = require('./lib/git'); module.exports = async opts => { const {isCi, branch, isPr} = envCi(); + const config = await getConfig(opts, logger); + const {plugins, options} = config; - if (!isCi && !opts.dryRun && !opts.noCi) { + if (!isCi && !options.dryRun && !options.noCi) { logger.log('This run was not triggered in a known CI environment, running in dry-run mode.'); - opts.dryRun = true; + options.dryRun = true; } - if (isCi && isPr && !opts.noCi) { + if (isCi && isPr && !options.noCi) { logger.log("This run was triggered by a pull request and therefore a new version won't be published."); return; } @@ -25,9 +27,6 @@ module.exports = async opts => { return; } - const config = await getConfig(opts, logger); - const {plugins, options} = config; - if (branch !== options.branch) { logger.log( `This test run was triggered on the branch ${branch}, while semantic-release is configured to only publish from ${ diff --git a/test/index.test.js b/test/index.test.js index 43afe5bf..6bca7ccf 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -209,7 +209,7 @@ test.serial('Dry-run skips publish', async t => { t.is(publish.callCount, 0); }); -test.serial('Force a dry-run if not on a CI and ignore "noCi" is not explicitly set', async t => { +test.serial('Force a dry-run if not on a CI and "noCi" is not explicitly set', async t => { // Create a git repository, set the current working directory at the root of the repo await gitRepo(); // Add commits to the master branch @@ -369,7 +369,7 @@ test.serial('Returns falsy value if not running from a git repository', async t './lib/logger': t.context.logger, 'env-ci': () => ({isCi: true, branch: 'master', isPr: false}), }); - t.falsy(await semanticRelease()); + t.falsy(await semanticRelease({repositoryUrl: 'git@hostname.com:owner/module.git'})); t.is(t.context.error.args[0][0], 'Semantic-release must run from a git repository.'); }); @@ -384,7 +384,7 @@ test.serial('Returns falsy value if triggered by a PR', async t => { t.falsy(await semanticRelease({repositoryUrl: 'git@hostname.com:owner/module.git'})); t.is( - t.context.log.args[0][0], + t.context.log.args[7][0], "This run was triggered by a pull request and therefore a new version won't be published." ); }); diff --git a/test/integration.test.js b/test/integration.test.js index a0e4bbc5..11ff0d28 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -656,6 +656,77 @@ test.serial('Dry-run', async t => { await mockServer.verify(verifyMock); }); +test.serial('Allow local releases with "noCi" option', async t => { + delete process.env.TRAVIS; + delete process.env.CI; + const packageName = 'test-no-ci'; + const owner = 'test-repo'; + // Create a git repository, set the current working directory at the root of the repo + t.log('Create git repository and package.json'); + await gitRepo(); + // Create package.json in repository root + await writeJson('./package.json', { + name: packageName, + version: '0.0.0-dev', + repository: {url: `git+https://github.com/${owner}/${packageName}`}, + publishConfig: {registry: npmRegistry.url}, + }); + + /* Initial release */ + const version = '1.0.0'; + const verifyMock = await mockServer.mock( + `/repos/${owner}/${packageName}`, + {headers: [{name: 'Authorization', values: [`token ${env.GH_TOKEN}`]}]}, + {body: {permissions: {push: true}}, method: 'GET'} + ); + const getRefMock = await mockServer.mock( + `/repos/${owner}/${packageName}/git/refs/tags/v${version}`, + {}, + {body: {}, statusCode: 404, method: 'GET'} + ); + const createRefMock = await mockServer.mock( + `/repos/${owner}/${packageName}/git/refs`, + { + body: {ref: `refs/tags/v${version}`}, + headers: [{name: 'Authorization', values: [`token ${env.GH_TOKEN}`]}], + }, + {body: {ref: `refs/tags/${version}`}} + ); + const createReleaseMock = await mockServer.mock( + `/repos/${owner}/${packageName}/releases`, + { + body: {tag_name: `v${version}`, target_commitish: 'master', name: `v${version}`}, + headers: [{name: 'Authorization', values: [`token ${env.GH_TOKEN}`]}], + }, + {body: {html_url: `release-url/${version}`}} + ); + + t.log('Commit a feature'); + await gitCommits(['feat: Initial commit']); + t.log('$ semantic-release --no-ci'); + const {stdout, code} = await execa(cli, ['--no-ci'], {env}); + console.log(stdout); + 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); + + // 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 + ); + t.is(releasedVersion, version); + t.is(releasedGitHead, await gitHead()); + t.log(`+ released ${releasedVersion} with gitHead ${releasedGitHead}`); + + await mockServer.verify(verifyMock); + await mockServer.verify(getRefMock); + await mockServer.verify(createRefMock); + await mockServer.verify(createReleaseMock); +}); + test.serial('Pass options via CLI arguments', async t => { const packageName = 'test-cli'; const owner = 'test-repo';