diff --git a/index.js b/index.js index a0c648ea..e6bee3e2 100644 --- a/index.js +++ b/index.js @@ -22,6 +22,10 @@ async function run(options, plugins) { if (!isCi && !options.dryRun && !options.noCi) { logger.log('This run was not triggered in a known CI environment, running in dry-run mode.'); options.dryRun = true; + } else { + // When running on CI, prevent the `git` CLI to prompt for username/password. See #703. + process.env.GIT_ASKPASS = 'echo'; + process.env.GIT_TERMINAL_PROMPT = 0; } if (isCi && isPr && !options.noCi) { diff --git a/lib/git.js b/lib/git.js index 35f6ac8b..4a746edc 100644 --- a/lib/git.js +++ b/lib/git.js @@ -1,5 +1,8 @@ const execa = require('execa'); const debug = require('debug')('semantic-release:git'); +const envCi = require('env-ci'); + +const timeout = envCi().isCi ? 10000 : 0; /** * Get the commit sha for a given tag. @@ -10,7 +13,7 @@ const debug = require('debug')('semantic-release:git'); */ async function gitTagHead(tagName) { try { - return await execa.stdout('git', ['rev-list', '-1', tagName]); + return await execa.stdout('git', ['rev-list', '-1', tagName], {timeout}); } catch (err) { debug(err); } @@ -21,7 +24,7 @@ async function gitTagHead(tagName) { * @throws {Error} If the `git` command fails. */ async function gitTags() { - return (await execa.stdout('git', ['tag'])) + return (await execa.stdout('git', ['tag'], {timeout})) .split('\n') .map(tag => tag.trim()) .filter(tag => Boolean(tag)); @@ -36,7 +39,7 @@ async function gitTags() { */ async function isRefInHistory(ref) { try { - return (await execa('git', ['merge-base', '--is-ancestor', ref, 'HEAD'])).code === 0; + return (await execa('git', ['merge-base', '--is-ancestor', ref, 'HEAD'], {timeout})).code === 0; } catch (err) { debug(err); } @@ -46,14 +49,14 @@ async function isRefInHistory(ref) { * Unshallow the git repository (retriving every commits and tags). */ async function unshallow() { - await execa('git', ['fetch', '--unshallow', '--tags'], {reject: false}); + await execa('git', ['fetch', '--unshallow', '--tags'], {reject: false, timeout}); } /** * @return {string} the sha of the HEAD commit. */ async function gitHead() { - return execa.stdout('git', ['rev-parse', 'HEAD']); + return execa.stdout('git', ['rev-parse', 'HEAD'], {timeout}); } /** @@ -61,7 +64,7 @@ async function gitHead() { */ async function repoUrl() { try { - return await execa.stdout('git', ['remote', 'get-url', 'origin']); + return await execa.stdout('git', ['remote', 'get-url', 'origin'], {timeout}); } catch (err) { debug(err); } @@ -72,7 +75,7 @@ async function repoUrl() { */ async function isGitRepo() { try { - return (await execa('git', ['rev-parse', '--git-dir'])).code === 0; + return (await execa('git', ['rev-parse', '--git-dir'], {timeout})).code === 0; } catch (err) { debug(err); } @@ -88,7 +91,7 @@ async function isGitRepo() { */ async function verifyAuth(origin, branch) { try { - return (await execa('git', ['push', '--dry-run', origin, `HEAD:${branch}`])).code === 0; + return (await execa('git', ['push', '--dry-run', origin, `HEAD:${branch}`], {timeout})).code === 0; } catch (err) { debug(err); } @@ -101,7 +104,7 @@ async function verifyAuth(origin, branch) { * @throws {Error} if the tag creation failed. */ async function tag(tagName) { - await execa('git', ['tag', tagName]); + await execa('git', ['tag', tagName], {timeout}); } /** @@ -112,19 +115,18 @@ async function tag(tagName) { * @throws {Error} if the push failed. */ async function push(origin, branch) { - await execa('git', ['push', '--tags', origin, `HEAD:${branch}`]); + await execa('git', ['push', '--tags', origin, `HEAD:${branch}`], {timeout}); } /** * Verify a tag name is a valid Git reference. * - * @method verifyTagName * @param {string} tagName the tag name to verify. * @return {boolean} `true` if valid, falsy otherwise. */ async function verifyTagName(tagName) { try { - return (await execa('git', ['check-ref-format', `refs/tags/${tagName}`])).code === 0; + return (await execa('git', ['check-ref-format', `refs/tags/${tagName}`], {timeout})).code === 0; } catch (err) { debug(err); }