diff --git a/lib/fail.js b/lib/fail.js index 4ea51c45..482fb85a 100644 --- a/lib/fail.js +++ b/lib/fail.js @@ -7,9 +7,15 @@ const getClient = require('./get-client'); const findSRIssues = require('./find-sr-issues'); const getFailComment = require('./get-fail-comment'); -module.exports = async (pluginConfig, {options: {branch, repositoryUrl}, errors, logger}) => { +module.exports = async (pluginConfig, context) => { + const { + options: {branch, repositoryUrl}, + errors, + logger, + } = context; const {githubToken, githubUrl, githubApiPathPrefix, proxy, failComment, failTitle, labels, assignees} = resolveConfig( - pluginConfig + pluginConfig, + context ); const {name: repo, owner} = parseGithubUrl(repositoryUrl); const github = getClient({githubToken, githubUrl, githubApiPathPrefix, proxy}); diff --git a/lib/glob-assets.js b/lib/glob-assets.js index 48d26007..3000c2de 100644 --- a/lib/glob-assets.js +++ b/lib/glob-assets.js @@ -3,7 +3,7 @@ const {isPlainObject, castArray, uniqWith} = require('lodash'); const globby = require('globby'); const debug = require('debug')('semantic-release:github'); -module.exports = async assets => +module.exports = async ({cwd}, assets) => uniqWith( [] .concat( @@ -19,7 +19,7 @@ module.exports = async assets => ); return []; } - const globbed = await globby(glob, {expandDirectories: true, gitignore: false, dot: true}); + const globbed = await globby(glob, {cwd, expandDirectories: true, gitignore: false, dot: true}); if (isPlainObject(asset)) { if (globbed.length > 1) { // If asset is an Object with a glob the `path` property that resolve to multiple files, diff --git a/lib/publish.js b/lib/publish.js index a4b8010f..7238714c 100644 --- a/lib/publish.js +++ b/lib/publish.js @@ -1,4 +1,4 @@ -const {basename, extname} = require('path'); +const {basename, extname, resolve} = require('path'); const {stat, readFile} = require('fs-extra'); const {isPlainObject} = require('lodash'); const parseGithubUrl = require('parse-github-url'); @@ -8,8 +8,14 @@ const globAssets = require('./glob-assets.js'); const resolveConfig = require('./resolve-config'); const getClient = require('./get-client'); -module.exports = async (pluginConfig, {options: {branch, repositoryUrl}, nextRelease: {gitTag, notes}, logger}) => { - const {githubToken, githubUrl, githubApiPathPrefix, proxy, assets} = resolveConfig(pluginConfig); +module.exports = async (pluginConfig, context) => { + const { + cwd, + options: {branch, repositoryUrl}, + nextRelease: {gitTag, notes}, + logger, + } = context; + const {githubToken, githubUrl, githubApiPathPrefix, proxy, assets} = resolveConfig(pluginConfig, context); const {name: repo, owner} = parseGithubUrl(repositoryUrl); const github = getClient({githubToken, githubUrl, githubApiPathPrefix, proxy}); const release = {owner, repo, tag_name: gitTag, name: gitTag, target_commitish: branch, body: notes}; // eslint-disable-line camelcase @@ -25,7 +31,7 @@ module.exports = async (pluginConfig, {options: {branch, repositoryUrl}, nextRel logger.log('Published GitHub release: %s', url); if (assets && assets.length > 0) { - const globbedAssets = await globAssets(assets); + const globbedAssets = await globAssets(context, assets); debug('globed assets: %o', globbedAssets); await Promise.all( @@ -34,7 +40,7 @@ module.exports = async (pluginConfig, {options: {branch, repositoryUrl}, nextRel let file; try { - file = await stat(filePath); + file = await stat(resolve(cwd, filePath)); } catch (err) { logger.error('The asset %s cannot be read, and will be ignored.', filePath); return; @@ -47,7 +53,7 @@ module.exports = async (pluginConfig, {options: {branch, repositoryUrl}, nextRel const fileName = asset.name || basename(filePath); const upload = { url: uploadUrl, - file: await readFile(filePath), + file: await readFile(resolve(cwd, filePath)), contentType: mime.getType(extname(fileName)) || 'text/plain', contentLength: file.size, name: fileName, diff --git a/lib/resolve-config.js b/lib/resolve-config.js index 50e7c90d..6a23cab7 100644 --- a/lib/resolve-config.js +++ b/lib/resolve-config.js @@ -1,20 +1,13 @@ const {isUndefined, castArray} = require('lodash'); -module.exports = ({ - githubUrl, - githubApiPathPrefix, - proxy, - assets, - successComment, - failTitle, - failComment, - labels, - assignees, -}) => ({ - githubToken: process.env.GH_TOKEN || process.env.GITHUB_TOKEN, - githubUrl: githubUrl || process.env.GH_URL || process.env.GITHUB_URL, - githubApiPathPrefix: githubApiPathPrefix || process.env.GH_PREFIX || process.env.GITHUB_PREFIX || '', - proxy: proxy || process.env.HTTP_PROXY, +module.exports = ( + {githubUrl, githubApiPathPrefix, proxy, assets, successComment, failTitle, failComment, labels, assignees}, + {env} +) => ({ + githubToken: env.GH_TOKEN || env.GITHUB_TOKEN, + githubUrl: githubUrl || env.GH_URL || env.GITHUB_URL, + githubApiPathPrefix: githubApiPathPrefix || env.GH_PREFIX || env.GITHUB_PREFIX || '', + proxy: proxy || env.HTTP_PROXY, assets: assets ? castArray(assets) : assets, successComment, failTitle: isUndefined(failTitle) || failTitle === false ? 'The automated release is failing 🚨' : failTitle, diff --git a/lib/success.js b/lib/success.js index a6415b0a..12503951 100644 --- a/lib/success.js +++ b/lib/success.js @@ -10,11 +10,19 @@ const getSearchQueries = require('./get-search-queries'); const getSuccessComment = require('./get-success-comment'); const findSRIssues = require('./find-sr-issues'); -module.exports = async ( - pluginConfig, - {options: {branch, repositoryUrl}, lastRelease, commits, nextRelease, releases, logger} -) => { - const {githubToken, githubUrl, githubApiPathPrefix, proxy, successComment, failTitle} = resolveConfig(pluginConfig); +module.exports = async (pluginConfig, context) => { + const { + options: {branch, repositoryUrl}, + lastRelease, + commits, + nextRelease, + releases, + logger, + } = context; + const {githubToken, githubUrl, githubApiPathPrefix, proxy, successComment, failTitle} = resolveConfig( + pluginConfig, + context + ); const {name: repo, owner} = parseGithubUrl(repositoryUrl); const github = getClient({githubToken, githubUrl, githubApiPathPrefix, proxy}); const parser = issueParser('github', githubUrl ? {hosts: [githubUrl]} : {}); diff --git a/lib/verify.js b/lib/verify.js index a9db8a78..280c9134 100644 --- a/lib/verify.js +++ b/lib/verify.js @@ -23,8 +23,12 @@ const VALIDATORS = { assignees: isArrayOf(isStringOrStringArray), }; -module.exports = async (pluginConfig, {options: {repositoryUrl}, logger}) => { - const {githubToken, githubUrl, githubApiPathPrefix, proxy, ...options} = resolveConfig(pluginConfig); +module.exports = async (pluginConfig, context) => { + const { + options: {repositoryUrl}, + logger, + } = context; + const {githubToken, githubUrl, githubApiPathPrefix, proxy, ...options} = resolveConfig(pluginConfig, context); const errors = Object.entries({...options, proxy}).reduce( (errors, [option, value]) => diff --git a/package.json b/package.json index 3d409499..c0e36701 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,9 @@ ], "all": true }, + "peerDependencies": { + "semantic-release": ">=15.8.0 <16.0.0" + }, "prettier": { "printWidth": 120, "trailingComma": "es5" diff --git a/test/fail.test.js b/test/fail.test.js index 89047477..d6aa0f59 100644 --- a/test/fail.test.js +++ b/test/fail.test.js @@ -14,17 +14,7 @@ const fail = proxyquire('../lib/fail', { './get-client': proxyquire('../lib/get-client', {'./definitions/rate-limit': rateLimit}), }); -// Save the current process.env -const envBackup = Object.assign({}, process.env); - test.beforeEach(t => { - // Delete env variables in case they are on the machine running the tests - delete process.env.GH_TOKEN; - delete process.env.GITHUB_TOKEN; - delete process.env.GH_URL; - delete process.env.GITHUB_URL; - delete process.env.GH_PREFIX; - delete process.env.GITHUB_PREFIX; // Mock logger t.context.log = stub(); t.context.error = stub(); @@ -32,8 +22,6 @@ test.beforeEach(t => { }); test.afterEach.always(() => { - // Restore process.env - process.env = envBackup; // Clear nock nock.cleanAll(); }); @@ -41,7 +29,7 @@ test.afterEach.always(() => { test.serial('Open a new issue with the list of errors', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; @@ -50,7 +38,7 @@ test.serial('Open a new issue with the list of errors', async t => { new SemanticReleaseError('Error message 2', 'ERR2', 'Error 2 details'), new SemanticReleaseError('Error message 3', 'ERR3', 'Error 3 details'), ]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' @@ -64,7 +52,7 @@ test.serial('Open a new issue with the list of errors', async t => { }) .reply(200, {html_url: 'https://github.com/issues/1', number: 1}); - await fail(pluginConfig, {options, errors, logger: t.context.logger}); + await fail(pluginConfig, {env, options, errors, logger: t.context.logger}); t.true(t.context.log.calledWith('Created issue #%d: %s.', 1, 'https://github.com/issues/1')); t.true(github.isDone()); @@ -73,7 +61,7 @@ test.serial('Open a new issue with the list of errors', async t => { test.serial('Open a new issue with the list of errors, retrying 4 times', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; @@ -82,7 +70,7 @@ test.serial('Open a new issue with the list of errors, retrying 4 times', async new SemanticReleaseError('Error message 2', 'ERR2', 'Error 2 details'), new SemanticReleaseError('Error message 3', 'ERR3', 'Error 3 details'), ]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' @@ -110,7 +98,7 @@ test.serial('Open a new issue with the list of errors, retrying 4 times', async }) .reply(200, {html_url: 'https://github.com/issues/1', number: 1}); - await fail(pluginConfig, {options, errors, logger: t.context.logger}); + await fail(pluginConfig, {env, options, errors, logger: t.context.logger}); t.true(t.context.log.calledWith('Created issue #%d: %s.', 1, 'https://github.com/issues/1')); t.true(github.isDone()); @@ -119,7 +107,7 @@ test.serial('Open a new issue with the list of errors, retrying 4 times', async test.serial('Open a new issue with the list of errors and custom title and comment', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'Custom title'; const failComment = `branch \${branch} \${errors[0].message} \${errors[1].message} \${errors[2].message}`; const pluginConfig = {failTitle, failComment}; @@ -129,7 +117,7 @@ test.serial('Open a new issue with the list of errors and custom title and comme new SemanticReleaseError('Error message 2', 'ERR2', 'Error 2 details'), new SemanticReleaseError('Error message 3', 'ERR3', 'Error 3 details'), ]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' @@ -143,7 +131,7 @@ test.serial('Open a new issue with the list of errors and custom title and comme }) .reply(200, {html_url: 'https://github.com/issues/1', number: 1}); - await fail(pluginConfig, {options, errors, logger: t.context.logger}); + await fail(pluginConfig, {env, options, errors, logger: t.context.logger}); t.true(t.context.log.calledWith('Created issue #%d: %s.', 1, 'https://github.com/issues/1')); t.true(github.isDone()); @@ -152,7 +140,7 @@ test.serial('Open a new issue with the list of errors and custom title and comme test.serial('Open a new issue with assignees and the list of errors', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const assignees = ['user1', 'user2']; const pluginConfig = {failTitle, assignees}; @@ -161,7 +149,7 @@ test.serial('Open a new issue with assignees and the list of errors', async t => new SemanticReleaseError('Error message 1', 'ERR1', 'Error 1 details'), new SemanticReleaseError('Error message 2', 'ERR2', 'Error 2 details'), ]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' @@ -176,7 +164,7 @@ test.serial('Open a new issue with assignees and the list of errors', async t => }) .reply(200, {html_url: 'https://github.com/issues/1', number: 1}); - await fail(pluginConfig, {options, errors, logger: t.context.logger}); + await fail(pluginConfig, {env, options, errors, logger: t.context.logger}); t.true(t.context.log.calledWith('Created issue #%d: %s.', 1, 'https://github.com/issues/1')); t.true(github.isDone()); @@ -185,7 +173,7 @@ test.serial('Open a new issue with assignees and the list of errors', async t => test.serial('Open a new issue without labels and the list of errors', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const labels = false; const pluginConfig = {failTitle, labels}; @@ -194,7 +182,7 @@ test.serial('Open a new issue without labels and the list of errors', async t => new SemanticReleaseError('Error message 1', 'ERR1', 'Error 1 details'), new SemanticReleaseError('Error message 2', 'ERR2', 'Error 2 details'), ]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' @@ -208,7 +196,7 @@ test.serial('Open a new issue without labels and the list of errors', async t => }) .reply(200, {html_url: 'https://github.com/issues/1', number: 1}); - await fail(pluginConfig, {options, errors, logger: t.context.logger}); + await fail(pluginConfig, {env, options, errors, logger: t.context.logger}); t.true(t.context.log.calledWith('Created issue #%d: %s.', 1, 'https://github.com/issues/1')); t.true(github.isDone()); @@ -217,7 +205,7 @@ test.serial('Open a new issue without labels and the list of errors', async t => test.serial('Update the first existing issue with the list of errors', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; @@ -231,7 +219,7 @@ test.serial('Update the first existing issue with the list of errors', async t = {number: 2, body: `Issue 2 body\n\n${ISSUE_ID}`, title: failTitle}, {number: 3, body: `Issue 3 body\n\n${ISSUE_ID}`, title: failTitle}, ]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' @@ -243,7 +231,7 @@ test.serial('Update the first existing issue with the list of errors', async t = }) .reply(200, {html_url: 'https://github.com/issues/2', number: 2}); - await fail(pluginConfig, {options, errors, logger: t.context.logger}); + await fail(pluginConfig, {env, options, errors, logger: t.context.logger}); t.true(t.context.log.calledWith('Found existing semantic-release issue #%d.', 2)); t.true(t.context.log.calledWith('Added comment to issue #%d: %s.', 2, 'https://github.com/issues/2')); diff --git a/test/find-sr-issue.test.js b/test/find-sr-issue.test.js index 17da2394..3cd47a0f 100644 --- a/test/find-sr-issue.test.js +++ b/test/find-sr-issue.test.js @@ -8,19 +8,10 @@ import findSRIssues from '../lib/find-sr-issues'; import {authenticate} from './helpers/mock-github'; import rateLimit from './helpers/rate-limit'; -// Save the current process.env -const envBackup = Object.assign({}, process.env); const githubToken = 'github_token'; const client = proxyquire('../lib/get-client', {'./definitions/rate-limit': rateLimit})({githubToken}); test.beforeEach(t => { - // Delete env variables in case they are on the machine running the tests - delete process.env.GH_TOKEN; - delete process.env.GITHUB_TOKEN; - delete process.env.GH_URL; - delete process.env.GITHUB_URL; - delete process.env.GH_PREFIX; - delete process.env.GITHUB_PREFIX; // Mock logger t.context.log = stub(); t.context.error = stub(); @@ -28,8 +19,6 @@ test.beforeEach(t => { }); test.afterEach.always(() => { - // Restore process.env - process.env = envBackup; // Clear nock nock.cleanAll(); }); @@ -44,7 +33,7 @@ test.serial('Filter out issues without ID', async t => { {number: 2, body: `Issue 2 body\n\n${ISSUE_ID}`, title}, {number: 3, body: `Issue 3 body\n\n${ISSUE_ID}`, title}, ]; - const github = authenticate({githubToken}) + const github = authenticate({}, {githubToken}) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' @@ -68,7 +57,7 @@ test.serial('Return empty array if not issues found', async t => { const githubToken = 'github_token'; const title = 'The automated release is failing 🚨'; const issues = []; - const github = authenticate({githubToken}) + const github = authenticate({}, {githubToken}) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' @@ -89,7 +78,7 @@ test.serial('Return empty array if not issues has matching ID', async t => { const githubToken = 'github_token'; const title = 'The automated release is failing 🚨'; const issues = [{number: 1, body: 'Issue 1 body', title}, {number: 2, body: 'Issue 2 body', title}]; - const github = authenticate({githubToken}) + const github = authenticate({}, {githubToken}) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' @@ -107,7 +96,7 @@ test.serial('Retries 4 times', async t => { const owner = 'test_user'; const repo = 'test_repo'; const title = 'The automated release is failing :rotating_light:'; - const github = authenticate({githubToken}) + const github = authenticate({}, {githubToken}) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' @@ -126,7 +115,7 @@ test.serial('Do not retry on 401 error', async t => { const owner = 'test_user'; const repo = 'test_repo'; const title = 'The automated release is failing :rotating_light:'; - const github = authenticate({githubToken}) + const github = authenticate({}, {githubToken}) .get( `/search/issues?q=${escape('in:title')}+${escape(`repo:${owner}/${repo}`)}+${escape('type:issue')}+${escape( 'state:open' diff --git a/test/glob-assets.test.js b/test/glob-assets.test.js index f40f976d..f5abc2db 100644 --- a/test/glob-assets.test.js +++ b/test/glob-assets.test.js @@ -1,167 +1,141 @@ import test from 'ava'; import globAssets from '../lib/glob-assets'; +const cwd = 'test/fixtures/files'; + test('Retrieve file from single path', async t => { - const globbedAssets = await globAssets(['test/fixtures/files/upload.txt']); + const globbedAssets = await globAssets({cwd}, ['upload.txt']); - t.deepEqual(globbedAssets, ['test/fixtures/files/upload.txt']); + t.deepEqual(globbedAssets, ['upload.txt']); }); test('Retrieve multiple files from path', async t => { - const globbedAssets = (await globAssets([ - 'test/fixtures/files/upload.txt', - 'test/fixtures/files/upload_other.txt', - ])).sort(); + const globbedAssets = (await globAssets({cwd}, ['upload.txt', 'upload_other.txt'])).sort(); - t.deepEqual(globbedAssets, ['test/fixtures/files/upload_other.txt', 'test/fixtures/files/upload.txt'].sort()); + t.deepEqual(globbedAssets, ['upload_other.txt', 'upload.txt'].sort()); }); test('Include missing files as defined, using Object definition', async t => { - const globbedAssets = (await globAssets([ - 'test/fixtures/files/upload.txt', - {path: 'test/fixtures/files/miss*.txt', label: 'Missing'}, - ])).sort(); + const globbedAssets = (await globAssets({cwd}, ['upload.txt', {path: 'miss*.txt', label: 'Missing'}])).sort(); - t.deepEqual( - globbedAssets, - ['test/fixtures/files/upload.txt', {path: 'test/fixtures/files/miss*.txt', label: 'Missing'}].sort() - ); + t.deepEqual(globbedAssets, ['upload.txt', {path: 'miss*.txt', label: 'Missing'}].sort()); }); test('Retrieve multiple files from Object', async t => { - const globbedAssets = (await globAssets([ - {path: 'test/fixtures/files/upload.txt', name: 'upload_name', label: 'Upload label'}, - 'test/fixtures/files/upload_other.txt', + const globbedAssets = (await globAssets({cwd}, [ + {path: 'upload.txt', name: 'upload_name', label: 'Upload label'}, + 'upload_other.txt', ])).sort(); t.deepEqual( globbedAssets, - [ - {path: 'test/fixtures/files/upload.txt', name: 'upload_name', label: 'Upload label'}, - 'test/fixtures/files/upload_other.txt', - ].sort() + [{path: 'upload.txt', name: 'upload_name', label: 'Upload label'}, 'upload_other.txt'].sort() ); }); test('Retrieve multiple files without duplicates', async t => { - const globbedAssets = (await globAssets([ - 'test/fixtures/files/upload_other.txt', - 'test/fixtures/files/upload.txt', - 'test/fixtures/files/upload_other.txt', - 'test/fixtures/files/upload.txt', - 'test/fixtures/files/upload.txt', - 'test/fixtures/files/upload_other.txt', + const globbedAssets = (await globAssets({cwd}, [ + 'upload_other.txt', + 'upload.txt', + 'upload_other.txt', + 'upload.txt', + 'upload.txt', + 'upload_other.txt', ])).sort(); - t.deepEqual(globbedAssets, ['test/fixtures/files/upload_other.txt', 'test/fixtures/files/upload.txt'].sort()); + t.deepEqual(globbedAssets, ['upload_other.txt', 'upload.txt'].sort()); }); test('Favor Object over String values when removing duplicates', async t => { - const globbedAssets = (await globAssets([ - 'test/fixtures/files/upload_other.txt', - 'test/fixtures/files/upload.txt', - {path: 'test/fixtures/files/upload.txt', name: 'upload_name'}, - 'test/fixtures/files/upload.txt', - {path: 'test/fixtures/files/upload_other.txt', name: 'upload_other_name'}, - 'test/fixtures/files/upload.txt', - 'test/fixtures/files/upload_other.txt', + const globbedAssets = (await globAssets({cwd}, [ + 'upload_other.txt', + 'upload.txt', + {path: 'upload.txt', name: 'upload_name'}, + 'upload.txt', + {path: 'upload_other.txt', name: 'upload_other_name'}, + 'upload.txt', + 'upload_other.txt', ])).sort(); t.deepEqual( globbedAssets, - [ - {path: 'test/fixtures/files/upload.txt', name: 'upload_name'}, - {path: 'test/fixtures/files/upload_other.txt', name: 'upload_other_name'}, - ].sort() + [{path: 'upload.txt', name: 'upload_name'}, {path: 'upload_other.txt', name: 'upload_other_name'}].sort() ); }); test('Retrieve file from single glob', async t => { - const globbedAssets = await globAssets(['test/fixtures/files/upload.*']); + const globbedAssets = await globAssets({cwd}, ['upload.*']); - t.deepEqual(globbedAssets, ['test/fixtures/files/upload.txt']); + t.deepEqual(globbedAssets, ['upload.txt']); }); test('Retrieve multiple files from single glob', async t => { - const globbedAssets = (await globAssets(['test/fixtures/files/*.txt'])).sort(); + const globbedAssets = (await globAssets({cwd}, ['*.txt'])).sort(); - t.deepEqual(globbedAssets, ['test/fixtures/files/upload_other.txt', 'test/fixtures/files/upload.txt'].sort()); + t.deepEqual(globbedAssets, ['upload_other.txt', 'upload.txt'].sort()); }); test('Accept glob array with one value', async t => { - const globbedAssets = (await globAssets([ - ['test/fixtures/files/*load.txt'], - ['test/fixtures/files/*_other.txt'], - ])).sort(); + const globbedAssets = (await globAssets({cwd}, [['*load.txt'], ['*_other.txt']])).sort(); - t.deepEqual(globbedAssets, ['test/fixtures/files/upload_other.txt', 'test/fixtures/files/upload.txt'].sort()); + t.deepEqual(globbedAssets, ['upload_other.txt', 'upload.txt'].sort()); }); test('Include globs that resolve to no files as defined', async t => { - const globbedAssets = (await globAssets([ - ['test/fixtures/files/upload.txt', '!test/fixtures/files/upload.txt'], - ])).sort(); + const globbedAssets = (await globAssets({cwd}, [['upload.txt', '!upload.txt']])).sort(); - t.deepEqual(globbedAssets, ['!test/fixtures/files/upload.txt', 'test/fixtures/files/upload.txt'].sort()); + t.deepEqual(globbedAssets, ['!upload.txt', 'upload.txt'].sort()); }); test('Accept glob array with one value for missing files', async t => { - const globbedAssets = (await globAssets([ - ['test/fixtures/files/*missing.txt'], - ['test/fixtures/files/*_other.txt'], - ])).sort(); + const globbedAssets = (await globAssets({cwd}, [['*missing.txt'], ['*_other.txt']])).sort(); - t.deepEqual(globbedAssets, ['test/fixtures/files/upload_other.txt', 'test/fixtures/files/*missing.txt'].sort()); + t.deepEqual(globbedAssets, ['upload_other.txt', '*missing.txt'].sort()); }); test('Replace name by filename for Object that match multiple files', async t => { - const globbedAssets = (await globAssets([ - {path: 'test/fixtures/files/*.txt', name: 'upload_name', label: 'Upload label'}, - ])).sort(); + const globbedAssets = (await globAssets({cwd}, [{path: '*.txt', name: 'upload_name', label: 'Upload label'}])).sort(); t.deepEqual( globbedAssets, [ - {path: 'test/fixtures/files/upload.txt', name: 'upload.txt', label: 'Upload label'}, - {path: 'test/fixtures/files/upload_other.txt', name: 'upload_other.txt', label: 'Upload label'}, + {path: 'upload.txt', name: 'upload.txt', label: 'Upload label'}, + {path: 'upload_other.txt', name: 'upload_other.txt', label: 'Upload label'}, ].sort() ); }); test('Include dotfiles', async t => { - const globbedAssets = await globAssets(['test/fixtures/files/.dot*']); + const globbedAssets = await globAssets({cwd}, ['.dot*']); - t.deepEqual(globbedAssets, ['test/fixtures/files/.dotfile']); + t.deepEqual(globbedAssets, ['.dotfile']); }); test('Ingnore single negated glob', async t => { - const globbedAssets = await globAssets(['!test/fixtures/files/*.txt']); + const globbedAssets = await globAssets({cwd}, ['!*.txt']); t.deepEqual(globbedAssets, []); }); test('Ingnore single negated glob in Object', async t => { - const globbedAssets = await globAssets([{path: '!test/fixtures/files/*.txt'}]); + const globbedAssets = await globAssets({cwd}, [{path: '!*.txt'}]); t.deepEqual(globbedAssets, []); }); test('Accept negated globs', async t => { - const globbedAssets = await globAssets([['test/fixtures/files/*.txt', '!**/*_other.txt']]); + const globbedAssets = await globAssets({cwd}, [['*.txt', '!**/*_other.txt']]); - t.deepEqual(globbedAssets, ['test/fixtures/files/upload.txt']); + t.deepEqual(globbedAssets, ['upload.txt']); }); test('Expand directories', async t => { - const globbedAssets = (await globAssets([['test/fixtures/files']])).sort(); + const globbedAssets = (await globAssets({cwd}, [['.']])).sort(); - t.deepEqual( - globbedAssets, - ['test/fixtures/files/upload_other.txt', 'test/fixtures/files/upload.txt', 'test/fixtures/files/.dotfile'].sort() - ); + t.deepEqual(globbedAssets, ['upload_other.txt', 'upload.txt', '.dotfile'].sort()); }); test('Include empty directory as defined', async t => { - const globbedAssets = await globAssets([['test/empty']]); + const globbedAssets = await globAssets({cwd}, [['test/empty']]); t.deepEqual(globbedAssets, ['test/empty']); }); diff --git a/test/helpers/mock-github.js b/test/helpers/mock-github.js index f0089d52..6203d24d 100644 --- a/test/helpers/mock-github.js +++ b/test/helpers/mock-github.js @@ -3,32 +3,40 @@ import nock from 'nock'; /** * Retun a `nock` object setup to respond to a github authentication request. Other expectation and responses can be chained. * - * @param {String} [githubToken=process.env.GH_TOKEN || process.env.GITHUB_TOKEN || 'GH_TOKEN'] The github token to return in the authentication response. - * @param {String} [githubUrl=process.env.GH_URL || process.env.GITHUB_URL || 'https://api.github.com'] The url on which to intercept http requests. - * @param {String} [githubApiPathPrefix=process.env.GH_PREFIX || process.env.GITHUB_PREFIX || ''] The GitHub Enterprise API prefix. + * @param {Object} [env={}] Environment variables. + * @param {String} [githubToken=env.GH_TOKEN || env.GITHUB_TOKEN || 'GH_TOKEN'] The github token to return in the authentication response. + * @param {String} [githubUrl=env.GH_URL || env.GITHUB_URL || 'https://api.github.com'] The url on which to intercept http requests. + * @param {String} [githubApiPathPrefix=env.GH_PREFIX || env.GITHUB_PREFIX || ''] The GitHub Enterprise API prefix. * @return {Object} A `nock` object ready to respond to a github authentication request. */ -export function authenticate({ - githubToken = process.env.GH_TOKEN || process.env.GITHUB_TOKEN || 'GH_TOKEN', - githubUrl = process.env.GH_URL || process.env.GITHUB_URL || 'https://api.github.com', - githubApiPathPrefix = process.env.GH_PREFIX || process.env.GITHUB_PREFIX || '', -} = {}) { +export function authenticate( + env = {}, + { + githubToken = env.GH_TOKEN || env.GITHUB_TOKEN || 'GH_TOKEN', + githubUrl = env.GH_URL || env.GITHUB_URL || 'https://api.github.com', + githubApiPathPrefix = env.GH_PREFIX || env.GITHUB_PREFIX || '', + } = {} +) { return nock(`${githubUrl}/${githubApiPathPrefix}`, {reqheaders: {Authorization: `token ${githubToken}`}}); } /** * Retun a `nock` object setup to respond to a github release upload request. Other expectation and responses can be chained. * - * @param {String} [githubToken=process.env.GH_TOKEN || process.env.GITHUB_TOKEN || 'GH_TOKEN'] The github token to return in the authentication response. + * @param {Object} [env={}] Environment variables. + * @param {String} [githubToken=env.GH_TOKEN || env.GITHUB_TOKEN || 'GH_TOKEN'] The github token to return in the authentication response. * @param {String} [uploadUrl] The url on which to intercept http requests. * @return {Object} A `nock` object ready to respond to a github file upload request. */ -export function upload({ - githubToken = process.env.GH_TOKEN || process.env.GITHUB_TOKEN || 'GH_TOKEN', - uploadUrl, - contentType = 'text/plain', - contentLength, -} = {}) { +export function upload( + env = {}, + { + githubToken = env.GH_TOKEN || env.GITHUB_TOKEN || 'GH_TOKEN', + uploadUrl, + contentType = 'text/plain', + contentLength, + } = {} +) { return nock(uploadUrl, { reqheaders: {Authorization: `token ${githubToken}`, 'content-type': contentType, 'content-length': contentLength}, }); diff --git a/test/integration.test.js b/test/integration.test.js index 59247064..23fedf7d 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -1,3 +1,4 @@ +import path from 'path'; import {escape} from 'querystring'; import test from 'ava'; import {stat} from 'fs-extra'; @@ -11,18 +12,10 @@ import rateLimit from './helpers/rate-limit'; /* eslint camelcase: ["error", {properties: "never"}] */ -// Save the current process.env -const envBackup = Object.assign({}, process.env); +const cwd = 'test/fixtures/files'; const client = proxyquire('../lib/get-client', {'./definitions/rate-limit': rateLimit}); test.beforeEach(t => { - // Delete env variables in case they are on the machine running the tests - delete process.env.GH_TOKEN; - delete process.env.GITHUB_TOKEN; - delete process.env.GH_URL; - delete process.env.GITHUB_URL; - delete process.env.GH_PREFIX; - delete process.env.GITHUB_PREFIX; // Clear npm cache to refresh the module state clearModule('..'); t.context.m = proxyquire('..', { @@ -38,47 +31,45 @@ test.beforeEach(t => { }); test.afterEach.always(() => { - // Restore process.env - process.env = envBackup; // Clear nock nock.cleanAll(); }); test.serial('Verify GitHub auth', async t => { - process.env.GITHUB_TOKEN = 'github_token'; const owner = 'test_user'; const repo = 'test_repo'; + const env = {GITHUB_TOKEN: 'github_token'}; const options = {repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`}; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); - await t.notThrows(t.context.m.verifyConditions({}, {options, logger: t.context.logger})); + await t.notThrows(t.context.m.verifyConditions({}, {cwd, env, options, logger: t.context.logger})); t.true(github.isDone()); }); test.serial('Verify GitHub auth with publish options', async t => { - process.env.GITHUB_TOKEN = 'github_token'; const owner = 'test_user'; const repo = 'test_repo'; + const env = {GITHUB_TOKEN: 'github_token'}; const options = { publish: {path: '@semantic-release/github'}, repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`, }; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); - await t.notThrows(t.context.m.verifyConditions({}, {options, logger: t.context.logger})); + await t.notThrows(t.context.m.verifyConditions({}, {cwd, env, options, logger: t.context.logger})); t.true(github.isDone()); }); test.serial('Verify GitHub auth and assets config', async t => { - process.env.GH_TOKEN = 'github_token'; const owner = 'test_user'; const repo = 'test_repo'; + const env = {GITHUB_TOKEN: 'github_token'}; const assets = [ {path: 'lib/file.js'}, 'file.js', @@ -90,16 +81,17 @@ test.serial('Verify GitHub auth and assets config', async t => { publish: [{path: '@semantic-release/npm'}], repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`, }; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); - await t.notThrows(t.context.m.verifyConditions({assets}, {options, logger: t.context.logger})); + await t.notThrows(t.context.m.verifyConditions({assets}, {cwd, env, options, logger: t.context.logger})); t.true(github.isDone()); }); test.serial('Throw SemanticReleaseError if invalid config', async t => { + const env = {}; const assets = [{wrongProperty: 'lib/file.js'}]; const successComment = 42; const failComment = 42; @@ -114,7 +106,7 @@ test.serial('Throw SemanticReleaseError if invalid config', async t => { repositoryUrl: 'invalid_url', }; - const errors = [...(await t.throws(t.context.m.verifyConditions({}, {options, logger: t.context.logger})))]; + const errors = [...(await t.throws(t.context.m.verifyConditions({}, {cwd, env, options, logger: t.context.logger})))]; t.is(errors[0].name, 'SemanticReleaseError'); t.is(errors[0].code, 'EINVALIDASSETS'); @@ -137,11 +129,11 @@ test.serial('Throw SemanticReleaseError if invalid config', async t => { test.serial('Publish a release with an array of assets', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GH_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const assets = [ - 'test/fixtures/files/upload.txt', - {path: ['test/fixtures/files/*.txt', '!**/*_other.txt'], name: 'upload_file_name.txt'}, - {path: ['test/fixtures/files/*.txt'], name: 'other_file.txt', label: 'Other File'}, + 'upload.txt', + {path: ['*.txt', '!**/*_other.txt'], name: 'upload_file_name.txt'}, + {path: ['*.txt'], name: 'other_file.txt', label: 'Other File'}, ]; const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; @@ -151,7 +143,7 @@ test.serial('Publish a release with an array of assets', async t => { const releaseId = 1; const uploadUri = `/api/uploads/repos/${owner}/${repo}/releases/${releaseId}/assets`; const uploadUrl = `https://github.com${uploadUri}{?name,label}`; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}) .post(`/repos/${owner}/${repo}/releases`, { @@ -161,20 +153,20 @@ test.serial('Publish a release with an array of assets', async t => { body: nextRelease.notes, }) .reply(200, {upload_url: uploadUrl, html_url: releaseUrl}); - const githubUpload1 = upload({ + const githubUpload1 = upload(env, { uploadUrl: 'https://github.com', - contentLength: (await stat('test/fixtures/files/upload.txt')).size, + contentLength: (await stat(path.resolve(cwd, 'upload.txt'))).size, }) .post(`${uploadUri}?name=${escape('upload_file_name.txt')}`) .reply(200, {browser_download_url: assetUrl}); - const githubUpload2 = upload({ + const githubUpload2 = upload(env, { uploadUrl: 'https://github.com', - contentLength: (await stat('test/fixtures/files/upload_other.txt')).size, + contentLength: (await stat(path.resolve(cwd, 'upload_other.txt'))).size, }) .post(`${uploadUri}?name=${escape('upload_other.txt')}&label=${escape('Other File')}`) .reply(200, {browser_download_url: otherAssetUrl}); - const result = await t.context.m.publish({assets}, {nextRelease, options, logger: t.context.logger}); + const result = await t.context.m.publish({assets}, {cwd, env, options, nextRelease, logger: t.context.logger}); t.is(result.url, releaseUrl); t.deepEqual(t.context.log.args[0], ['Verify GitHub authentication']); @@ -189,14 +181,14 @@ test.serial('Publish a release with an array of assets', async t => { test.serial('Comment on PR included in the releases', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GH_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const prs = [{number: 1, pull_request: {}, state: 'closed'}]; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; const commits = [{hash: '123', message: 'Commit 1 message', tree: {long: 'aaa'}}]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}) .get( @@ -216,7 +208,7 @@ test.serial('Comment on PR included in the releases', async t => { ) .reply(200, {items: []}); - await t.context.m.success({failTitle}, {options, commits, nextRelease, releases, logger: t.context.logger}); + await t.context.m.success({failTitle}, {cwd, env, options, commits, nextRelease, releases, logger: t.context.logger}); t.deepEqual(t.context.log.args[0], ['Verify GitHub authentication']); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 1, 'https://github.com/successcomment-1')); @@ -226,7 +218,7 @@ test.serial('Comment on PR included in the releases', async t => { test.serial('Open a new issue with the list of errors', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; const errors = [ @@ -234,7 +226,7 @@ test.serial('Open a new issue with the list of errors', async t => { new SemanticReleaseError('Error message 2', 'ERR2', 'Error 2 details'), new SemanticReleaseError('Error message 3', 'ERR3', 'Error 3 details'), ]; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}) .get( @@ -250,7 +242,7 @@ test.serial('Open a new issue with the list of errors', async t => { }) .reply(200, {html_url: 'https://github.com/issues/1', number: 1}); - await t.context.m.fail({failTitle}, {options, errors, logger: t.context.logger}); + await t.context.m.fail({failTitle}, {cwd, env, options, errors, logger: t.context.logger}); t.deepEqual(t.context.log.args[0], ['Verify GitHub authentication']); t.true(t.context.log.calledWith('Created issue #%d: %s.', 1, 'https://github.com/issues/1')); @@ -258,13 +250,10 @@ test.serial('Open a new issue with the list of errors', async t => { }); test.serial('Verify, release and notify success', async t => { - process.env.GH_TOKEN = 'github_token'; const owner = 'test_user'; const repo = 'test_repo'; - const assets = [ - 'test/fixtures/files/upload.txt', - {path: 'test/fixtures/files/upload_other.txt', name: 'other_file.txt', label: 'Other File'}, - ]; + const env = {GITHUB_TOKEN: 'github_token'}; + const assets = ['upload.txt', {path: 'upload_other.txt', name: 'other_file.txt', label: 'Other File'}]; const failTitle = 'The automated release is failing 🚨'; const options = { publish: [{path: '@semantic-release/npm'}, {path: '@semantic-release/github', assets}], @@ -280,7 +269,7 @@ test.serial('Verify, release and notify success', async t => { const uploadUrl = `https://github.com${uploadUri}{?name,label}`; const prs = [{number: 1, pull_request: {}, state: 'closed'}]; const commits = [{hash: '123', message: 'Commit 1 message', tree: {long: 'aaa'}}]; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}) .post(`/repos/${owner}/${repo}/releases`, { @@ -306,24 +295,24 @@ test.serial('Verify, release and notify success', async t => { )}+${escape(failTitle)}` ) .reply(200, {items: []}); - const githubUpload1 = upload({ + const githubUpload1 = upload(env, { uploadUrl: 'https://github.com', - contentLength: (await stat('test/fixtures/files/upload.txt')).size, + contentLength: (await stat(path.resolve(cwd, 'upload.txt'))).size, }) .post(`${uploadUri}?name=${escape('upload.txt')}`) .reply(200, {browser_download_url: assetUrl}); - const githubUpload2 = upload({ + const githubUpload2 = upload(env, { uploadUrl: 'https://github.com', - contentLength: (await stat('test/fixtures/files/upload_other.txt')).size, + contentLength: (await stat(path.resolve(cwd, 'upload_other.txt'))).size, }) .post(`${uploadUri}?name=${escape('other_file.txt')}&label=${escape('Other File')}`) .reply(200, {browser_download_url: otherAssetUrl}); - await t.notThrows(t.context.m.verifyConditions({}, {options, logger: t.context.logger})); - await t.context.m.publish({assets}, {nextRelease, options, logger: t.context.logger}); + await t.notThrows(t.context.m.verifyConditions({}, {cwd, env, options, logger: t.context.logger})); + await t.context.m.publish({assets}, {cwd, env, options, nextRelease, logger: t.context.logger}); await t.context.m.success( {assets, failTitle}, - {nextRelease, options, commits, releases: [], logger: t.context.logger} + {cwd, env, options, nextRelease, commits, releases: [], logger: t.context.logger} ); t.deepEqual(t.context.log.args[0], ['Verify GitHub authentication']); @@ -338,7 +327,7 @@ test.serial('Verify, release and notify success', async t => { test.serial('Verify and notify failure', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; const errors = [ @@ -346,7 +335,7 @@ test.serial('Verify and notify failure', async t => { new SemanticReleaseError('Error message 2', 'ERR2', 'Error 2 details'), new SemanticReleaseError('Error message 3', 'ERR3', 'Error 3 details'), ]; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}) .get( @@ -362,8 +351,8 @@ test.serial('Verify and notify failure', async t => { }) .reply(200, {html_url: 'https://github.com/issues/1', number: 1}); - await t.notThrows(t.context.m.verifyConditions({}, {options, logger: t.context.logger})); - await t.context.m.fail({failTitle}, {options, errors, logger: t.context.logger}); + await t.notThrows(t.context.m.verifyConditions({}, {cwd, env, options, logger: t.context.logger})); + await t.context.m.fail({failTitle}, {cwd, env, options, errors, logger: t.context.logger}); t.deepEqual(t.context.log.args[0], ['Verify GitHub authentication']); t.true(t.context.log.calledWith('Created issue #%d: %s.', 1, 'https://github.com/issues/1')); diff --git a/test/publish.test.js b/test/publish.test.js index 3ecea5fb..adbc99c0 100644 --- a/test/publish.test.js +++ b/test/publish.test.js @@ -1,3 +1,4 @@ +import path from 'path'; import {escape} from 'querystring'; import test from 'ava'; import {stat} from 'fs-extra'; @@ -10,21 +11,12 @@ import rateLimit from './helpers/rate-limit'; /* eslint camelcase: ["error", {properties: "never"}] */ +const cwd = 'test/fixtures/files'; const publish = proxyquire('../lib/publish', { './get-client': proxyquire('../lib/get-client', {'./definitions/rate-limit': rateLimit}), }); -// Save the current process.env -const envBackup = Object.assign({}, process.env); - test.beforeEach(t => { - // Delete env variables in case they are on the machine running the tests - delete process.env.GH_TOKEN; - delete process.env.GITHUB_TOKEN; - delete process.env.GH_URL; - delete process.env.GITHUB_URL; - delete process.env.GH_PREFIX; - delete process.env.GITHUB_PREFIX; // Mock logger t.context.log = stub(); t.context.error = stub(); @@ -32,8 +24,6 @@ test.beforeEach(t => { }); test.afterEach.always(() => { - // Restore process.env - process.env = envBackup; // Clear nock nock.cleanAll(); }); @@ -41,7 +31,7 @@ test.afterEach.always(() => { test.serial('Publish a release', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const pluginConfig = {}; const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; @@ -50,7 +40,7 @@ test.serial('Publish a release', async t => { const uploadUri = `/api/uploads/repos/${owner}/${repo}/releases/${releaseId}/assets`; const uploadUrl = `https://github.com${uploadUri}{?name,label}`; - const github = authenticate() + const github = authenticate(env) .post(`/repos/${owner}/${repo}/releases`, { tag_name: nextRelease.gitTag, target_commitish: options.branch, @@ -59,7 +49,7 @@ test.serial('Publish a release', async t => { }) .reply(200, {upload_url: uploadUrl, html_url: releaseUrl}); - const result = await publish(pluginConfig, {options, nextRelease, logger: t.context.logger}); + const result = await publish(pluginConfig, {cwd, env, options, nextRelease, logger: t.context.logger}); t.is(result.url, releaseUrl); t.deepEqual(t.context.log.args[0], ['Published GitHub release: %s', releaseUrl]); @@ -69,7 +59,7 @@ test.serial('Publish a release', async t => { test.serial('Publish a release, retrying 4 times', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const pluginConfig = {}; const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; @@ -78,7 +68,7 @@ test.serial('Publish a release, retrying 4 times', async t => { const uploadUri = `/api/uploads/repos/${owner}/${repo}/releases/${releaseId}/assets`; const uploadUrl = `https://github.com${uploadUri}{?name,label}`; - const github = authenticate() + const github = authenticate(env) .post(`/repos/${owner}/${repo}/releases`, { tag_name: nextRelease.gitTag, target_commitish: options.branch, @@ -95,7 +85,7 @@ test.serial('Publish a release, retrying 4 times', async t => { }) .reply(200, {upload_url: uploadUrl, html_url: releaseUrl}); - const result = await publish(pluginConfig, {options, nextRelease, logger: t.context.logger}); + const result = await publish(pluginConfig, {cwd, env, options, nextRelease, logger: t.context.logger}); t.is(result.url, releaseUrl); t.deepEqual(t.context.log.args[0], ['Published GitHub release: %s', releaseUrl]); @@ -105,12 +95,9 @@ test.serial('Publish a release, retrying 4 times', async t => { test.serial('Publish a release with one asset', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GH_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const pluginConfig = { - assets: [ - ['test/fixtures/files/**', '!**/*.txt'], - {path: 'test/fixtures/files/.dotfile', label: 'A dotfile with no ext'}, - ], + assets: [['**', '!**/*.txt'], {path: '.dotfile', label: 'A dotfile with no ext'}], }; const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; @@ -120,7 +107,7 @@ test.serial('Publish a release with one asset', async t => { const uploadUri = `/api/uploads/repos/${owner}/${repo}/releases/${releaseId}/assets`; const uploadUrl = `https://github.com${uploadUri}{?name,label}`; - const github = authenticate() + const github = authenticate(env) .post(`/repos/${owner}/${repo}/releases`, { tag_name: nextRelease.gitTag, target_commitish: options.branch, @@ -129,14 +116,14 @@ test.serial('Publish a release with one asset', async t => { }) .reply(200, {upload_url: uploadUrl, html_url: releaseUrl}); - const githubUpload = upload({ + const githubUpload = upload(env, { uploadUrl: 'https://github.com', - contentLength: (await stat('test/fixtures/files/.dotfile')).size, + contentLength: (await stat(path.resolve(cwd, '.dotfile'))).size, }) .post(`${uploadUri}?name=${escape('.dotfile')}&label=${escape('A dotfile with no ext')}`) .reply(200, {browser_download_url: assetUrl}); - const result = await publish(pluginConfig, {options, nextRelease, logger: t.context.logger}); + const result = await publish(pluginConfig, {cwd, env, options, nextRelease, logger: t.context.logger}); t.is(result.url, releaseUrl); t.deepEqual(t.context.log.args[0], ['Published GitHub release: %s', releaseUrl]); @@ -148,28 +135,19 @@ test.serial('Publish a release with one asset', async t => { test.serial('Publish a release with one asset and custom github url', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GH_URL = 'https://othertesturl.com:443'; - process.env.GH_TOKEN = 'github_token'; - process.env.GH_PREFIX = 'prefix'; + const env = {GH_URL: 'https://othertesturl.com:443', GH_TOKEN: 'github_token', GH_PREFIX: 'prefix'}; const pluginConfig = { - assets: [ - ['test/fixtures/files/*.txt', '!**/*_other.txt'], - {path: ['test/fixtures/files/*.txt', '!**/*_other.txt'], label: 'A text file'}, - 'test/fixtures/files/upload.txt', - ], + assets: [['*.txt', '!**/*_other.txt'], {path: ['*.txt', '!**/*_other.txt'], label: 'A text file'}, 'upload.txt'], }; const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; - const releaseUrl = `${process.env.GH_URL}/${owner}/${repo}/releases/${nextRelease.version}`; - const assetUrl = `${process.env.GH_URL}/${owner}/${repo}/releases/download/${nextRelease.version}/upload.txt`; + const releaseUrl = `${env.GH_URL}/${owner}/${repo}/releases/${nextRelease.version}`; + const assetUrl = `${env.GH_URL}/${owner}/${repo}/releases/download/${nextRelease.version}/upload.txt`; const releaseId = 1; const uploadUri = `/api/uploads/repos/${owner}/${repo}/releases/${releaseId}/assets`; - const uploadUrl = `${process.env.GH_URL}${uploadUri}{?name,label}`; + const uploadUrl = `${env.GH_URL}${uploadUri}{?name,label}`; - const github = authenticate({ - githubUrl: process.env.GH_URL, - githubApiPathPrefix: process.env.GH_PREFIX, - }) + const github = authenticate(env, {}) .post(`/repos/${owner}/${repo}/releases`, { tag_name: nextRelease.gitTag, target_commitish: options.branch, @@ -178,14 +156,14 @@ test.serial('Publish a release with one asset and custom github url', async t => }) .reply(200, {upload_url: uploadUrl, html_url: releaseUrl}); - const githubUpload = upload({ - uploadUrl: process.env.GH_URL, - contentLength: (await stat('test/fixtures/files/upload.txt')).size, + const githubUpload = upload(env, { + uploadUrl: env.GH_URL, + contentLength: (await stat(path.resolve(cwd, 'upload.txt'))).size, }) .post(`${uploadUri}?name=${escape('upload.txt')}&label=${escape('A text file')}`) .reply(200, {browser_download_url: assetUrl}); - const result = await publish(pluginConfig, {options, nextRelease, logger: t.context.logger}); + const result = await publish(pluginConfig, {cwd, env, options, nextRelease, logger: t.context.logger}); t.is(result.url, releaseUrl); t.deepEqual(t.context.log.args[0], ['Published GitHub release: %s', releaseUrl]); @@ -197,9 +175,9 @@ test.serial('Publish a release with one asset and custom github url', async t => test.serial('Publish a release with an array of missing assets', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const emptyDirectory = tempy.directory(); - const pluginConfig = {assets: [emptyDirectory, {path: 'test/fixtures/files/missing.txt', name: 'missing.txt'}]}; + const pluginConfig = {assets: [emptyDirectory, {path: 'missing.txt', name: 'missing.txt'}]}; const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`; @@ -207,7 +185,7 @@ test.serial('Publish a release with an array of missing assets', async t => { const uploadUri = `/api/uploads/repos/${owner}/${repo}/releases/${releaseId}/assets`; const uploadUrl = `https://github.com${uploadUri}{?name,label}`; - const github = authenticate() + const github = authenticate(env) .post(`/repos/${owner}/${repo}/releases`, { tag_name: nextRelease.gitTag, target_commitish: options.branch, @@ -216,13 +194,11 @@ test.serial('Publish a release with an array of missing assets', async t => { }) .reply(200, {upload_url: uploadUrl, html_url: releaseUrl}); - const result = await publish(pluginConfig, {options, nextRelease, logger: t.context.logger}); + const result = await publish(pluginConfig, {cwd, env, options, nextRelease, logger: t.context.logger}); t.is(result.url, releaseUrl); t.deepEqual(t.context.log.args[0], ['Published GitHub release: %s', releaseUrl]); - t.true( - t.context.error.calledWith('The asset %s cannot be read, and will be ignored.', 'test/fixtures/files/missing.txt') - ); + t.true(t.context.error.calledWith('The asset %s cannot be read, and will be ignored.', 'missing.txt')); t.true(t.context.error.calledWith('The asset %s is not a file, and will be ignored.', emptyDirectory)); t.true(github.isDone()); }); @@ -230,12 +206,12 @@ test.serial('Publish a release with an array of missing assets', async t => { test.serial('Throw error without retries for 400 error', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const pluginConfig = {}; const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; - const github = authenticate() + const github = authenticate(env) .post(`/repos/${owner}/${repo}/releases`, { tag_name: nextRelease.gitTag, target_commitish: options.branch, @@ -251,7 +227,7 @@ test.serial('Throw error without retries for 400 error', async t => { }) .reply(400); - const error = await t.throws(publish(pluginConfig, {options, nextRelease, logger: t.context.logger})); + const error = await t.throws(publish(pluginConfig, {cwd, env, options, nextRelease, logger: t.context.logger})); t.is(error.code, 400); t.true(github.isDone()); diff --git a/test/success.test.js b/test/success.test.js index 8975f296..9fd1bbb0 100644 --- a/test/success.test.js +++ b/test/success.test.js @@ -14,17 +14,7 @@ const success = proxyquire('../lib/success', { './get-client': proxyquire('../lib/get-client', {'./definitions/rate-limit': rateLimit}), }); -// Save the current process.env -const envBackup = Object.assign({}, process.env); - test.beforeEach(t => { - // Delete env variables in case they are on the machine running the tests - delete process.env.GH_TOKEN; - delete process.env.GITHUB_TOKEN; - delete process.env.GH_URL; - delete process.env.GITHUB_URL; - delete process.env.GH_PREFIX; - delete process.env.GITHUB_PREFIX; // Mock logger t.context.log = stub(); t.context.error = stub(); @@ -32,8 +22,6 @@ test.beforeEach(t => { }); test.afterEach.always(() => { - // Restore process.env - process.env = envBackup; // Clear nock nock.cleanAll(); }); @@ -41,7 +29,7 @@ test.afterEach.always(() => { test.serial('Add comment to PRs associated with release commits and issues closed by PR/commits comments', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const prs = [ @@ -56,7 +44,7 @@ test.serial('Add comment to PRs associated with release commits and issues close ]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -86,7 +74,7 @@ test.serial('Add comment to PRs associated with release commits and issues close ) .reply(200, {items: []}); - await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 1, 'https://github.com/successcomment-1')); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 2, 'https://github.com/successcomment-2')); @@ -100,9 +88,7 @@ test.serial( async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GH_URL = 'https://custom-url.com'; - process.env.GH_TOKEN = 'github_token'; - process.env.GH_PREFIX = 'prefix'; + const env = {GH_URL: 'https://custom-url.com', GH_TOKEN: 'github_token', GH_PREFIX: 'prefix'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const prs = [ @@ -121,7 +107,7 @@ test.serial( ]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://custom-url.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -151,7 +137,7 @@ test.serial( ) .reply(200, {items: []}); - await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 1, 'https://custom-url.com/successcomment-1')); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 2, 'https://custom-url.com/successcomment-2')); @@ -164,7 +150,7 @@ test.serial( test.serial('Make multiple search queries if necessary', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const prs = [ @@ -187,7 +173,7 @@ test.serial('Make multiple search queries if necessary', async t => { ]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${ commits[0].hash @@ -231,7 +217,7 @@ test.serial('Make multiple search queries if necessary', async t => { ) .reply(200, {items: []}); - await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 1, 'https://github.com/successcomment-1')); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 2, 'https://github.com/successcomment-2')); @@ -245,7 +231,7 @@ test.serial('Make multiple search queries if necessary', async t => { test.serial('Do not add comment for unrelated PR returned by search (compare sha)', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const prs = [{number: 1, pull_request: {}, state: 'closed'}, {number: 2, pull_request: {}, state: 'closed'}]; @@ -256,7 +242,7 @@ test.serial('Do not add comment for unrelated PR returned by search (compare sha ]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -276,7 +262,7 @@ test.serial('Do not add comment for unrelated PR returned by search (compare sha ) .reply(200, {items: []}); - await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 1, 'https://github.com/successcomment-1')); t.true(github.isDone()); @@ -285,7 +271,7 @@ test.serial('Do not add comment for unrelated PR returned by search (compare sha test.serial('Do not add comment for unrelated PR returned by search (compare tree sha)', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const prs = [{number: 1, pull_request: {}, state: 'closed'}, {number: 2, pull_request: {}, state: 'closed'}]; @@ -296,7 +282,7 @@ test.serial('Do not add comment for unrelated PR returned by search (compare tre ]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -316,7 +302,7 @@ test.serial('Do not add comment for unrelated PR returned by search (compare tre ) .reply(200, {items: []}); - await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 1, 'https://github.com/successcomment-1')); t.true(github.isDone()); @@ -325,7 +311,7 @@ test.serial('Do not add comment for unrelated PR returned by search (compare tre test.serial('Do not add comment to open issues/PRs', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const prs = [{number: 1, pull_request: {}, body: 'Fixes #2', state: 'closed'}]; @@ -333,7 +319,7 @@ test.serial('Do not add comment to open issues/PRs', async t => { const commits = [{hash: '123', message: 'Commit 1 message', tree: {long: 'aaa'}}]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -353,7 +339,7 @@ test.serial('Do not add comment to open issues/PRs', async t => { ) .reply(200, {items: []}); - await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 1, 'https://github.com/successcomment-1')); t.true(t.context.log.calledWith("Skip comment on issue #%d as it's open: %s", 2)); @@ -363,14 +349,14 @@ test.serial('Do not add comment to open issues/PRs', async t => { test.serial('Do not add comment if no PR is associated with release commits', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; const commits = [{hash: '123', message: 'Commit 1 message', tree: {long: 'aaa'}}]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -384,7 +370,7 @@ test.serial('Do not add comment if no PR is associated with release commits', as ) .reply(200, {items: []}); - await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}); t.true(github.isDone()); }); @@ -392,7 +378,7 @@ test.serial('Do not add comment if no PR is associated with release commits', as test.serial('Do not add comment to PR/issues from other repo', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`}; @@ -403,7 +389,7 @@ test.serial('Do not add comment to PR/issues from other repo', async t => { ]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -421,7 +407,7 @@ test.serial('Do not add comment to PR/issues from other repo', async t => { ) .reply(200, {items: []}); - await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}); t.true(github.isDone()); }); @@ -429,7 +415,7 @@ test.serial('Do not add comment to PR/issues from other repo', async t => { test.serial('Ignore missing issues/PRs', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const prs = [ @@ -443,7 +429,7 @@ test.serial('Ignore missing issues/PRs', async t => { ]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -470,7 +456,7 @@ test.serial('Ignore missing issues/PRs', async t => { ) .reply(200, {items: []}); - await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 1, 'https://github.com/successcomment-1')); t.true(t.context.log.calledWith('Added comment to issue #%d: %s', 3, 'https://github.com/successcomment-3')); @@ -481,7 +467,7 @@ test.serial('Ignore missing issues/PRs', async t => { test.serial('Add custom comment', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = { successComment: `last release: \${lastRelease.version} nextRelease: \${nextRelease.version} branch: \${branch} commits: \${commits.length} releases: \${releases.length} PR attribute: \${issue.prop}`, @@ -493,7 +479,7 @@ test.serial('Add custom comment', async t => { const commits = [{hash: '123', message: 'Commit 1 message', tree: {long: 'aaa'}}]; const nextRelease = {version: '2.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -513,7 +499,7 @@ test.serial('Add custom comment', async t => { ) .reply(200, {items: []}); - await success(pluginConfig, {options, lastRelease, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, lastRelease, commits, nextRelease, releases, logger: t.context.logger}); t.true(github.isDone()); }); @@ -521,7 +507,7 @@ test.serial('Add custom comment', async t => { test.serial('Ignore errors when adding comments and closing issues', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const issues = [ @@ -537,7 +523,7 @@ test.serial('Ignore errors when adding comments and closing issues', async t => ]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -565,7 +551,7 @@ test.serial('Ignore errors when adding comments and closing issues', async t => .reply(200, {html_url: 'https://github.com/issues/3'}); const [error1, error2] = await t.throws( - success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}) + success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}) ); t.is(error1.code, 400); @@ -580,7 +566,7 @@ test.serial('Ignore errors when adding comments and closing issues', async t => test.serial('Close open issues when a release is successful', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GITHUB_TOKEN: 'github_token'}; const failTitle = 'The automated release is failing 🚨'; const pluginConfig = {failTitle}; const issues = [ @@ -592,7 +578,7 @@ test.serial('Close open issues when a release is successful', async t => { const commits = [{hash: '123', message: 'Commit 1 message', tree: {long: 'aaa'}}]; const nextRelease = {version: '1.0.0'}; const releases = [{name: 'GitHub release', url: 'https://github.com/release'}]; - const github = authenticate() + const github = authenticate(env) .get( `/search/issues?q=${escape(`repo:${owner}/${repo}`)}+${escape('type:pr')}+${escape('is:merged')}+${commits .map(commit => commit.hash) @@ -610,7 +596,7 @@ test.serial('Close open issues when a release is successful', async t => { .patch(`/repos/${owner}/${repo}/issues/3`, {state: 'closed'}) .reply(200, {html_url: 'https://github.com/issues/3'}); - await success(pluginConfig, {options, commits, nextRelease, releases, logger: t.context.logger}); + await success(pluginConfig, {env, options, commits, nextRelease, releases, logger: t.context.logger}); t.true(t.context.log.calledWith('Closed issue #%d: %s.', 2, 'https://github.com/issues/2')); t.true(t.context.log.calledWith('Closed issue #%d: %s.', 3, 'https://github.com/issues/3')); t.true(github.isDone()); diff --git a/test/verify.test.js b/test/verify.test.js index cc6e4033..25f71270 100644 --- a/test/verify.test.js +++ b/test/verify.test.js @@ -7,22 +7,11 @@ import rateLimit from './helpers/rate-limit'; /* eslint camelcase: ["error", {properties: "never"}] */ -// Save the current process.env -const envBackup = Object.assign({}, process.env); - const verify = proxyquire('../lib/verify', { './get-client': proxyquire('../lib/get-client', {'./definitions/rate-limit': rateLimit}), }); test.beforeEach(t => { - // Delete env variables in case they are on the machine running the tests - delete process.env.GH_TOKEN; - delete process.env.GITHUB_TOKEN; - delete process.env.GH_URL; - delete process.env.GITHUB_URL; - delete process.env.GH_PREFIX; - delete process.env.GITHUB_PREFIX; - delete process.env.HTTP_PROXY; // Mock logger t.context.log = stub(); t.context.error = stub(); @@ -30,8 +19,6 @@ test.beforeEach(t => { }); test.afterEach.always(() => { - // Restore process.env - process.env = envBackup; // Clear nock nock.cleanAll(); }); @@ -39,21 +26,21 @@ test.afterEach.always(() => { test.serial('Verify package, token and repository access', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GH_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const proxy = 'https://localhost'; const assets = [{path: 'lib/file.js'}, 'file.js']; const successComment = 'Test comment'; const failTitle = 'Test title'; const failComment = 'Test comment'; const labels = ['semantic-release']; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( verify( {proxy, assets, successComment, failTitle, failComment, labels}, - {options: {repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`}, logger: t.context.logger} + {env, options: {repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`}, logger: t.context.logger} ) ); t.true(github.isDone()); @@ -64,21 +51,21 @@ test.serial( async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GH_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const proxy = false; const assets = false; const successComment = false; const failTitle = false; const failComment = false; const labels = false; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( verify( {proxy, assets, successComment, failTitle, failComment, labels}, - {options: {repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`}, logger: t.context.logger} + {env, options: {repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`}, logger: t.context.logger} ) ); t.true(github.isDone()); @@ -88,17 +75,17 @@ test.serial( test.serial('Verify package, token and repository access and custom URL with prefix', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GH_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const githubUrl = 'https://othertesturl.com:9090'; const githubApiPathPrefix = 'prefix'; - const github = authenticate({githubUrl, githubApiPathPrefix}) + const github = authenticate(env, {githubUrl, githubApiPathPrefix}) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( verify( {githubUrl, githubApiPathPrefix}, - {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} ) ); @@ -109,16 +96,16 @@ test.serial('Verify package, token and repository access and custom URL with pre test.serial('Verify package, token and repository access and custom URL without prefix', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GH_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const githubUrl = 'https://othertesturl.com:9090'; - const github = authenticate({githubUrl}) + const github = authenticate(env, {githubUrl}) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( verify( {githubUrl}, - {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} ) ); @@ -129,16 +116,18 @@ test.serial('Verify package, token and repository access and custom URL without test.serial('Verify package, token and repository with environment variables', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GH_URL = 'https://othertesturl.com:443'; - process.env.GH_TOKEN = 'github_token'; - process.env.GH_PREFIX = 'prefix'; - process.env.HTTP_PROXY = 'https://localhost'; - const github = authenticate() + const env = { + GH_URL: 'https://othertesturl.com:443', + GH_TOKEN: 'github_token', + GH_PREFIX: 'prefix', + HTTP_PROXY: 'https://localhost', + }; + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( - verify({}, {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) + verify({}, {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) ); t.true(github.isDone()); @@ -148,16 +137,17 @@ test.serial('Verify package, token and repository with environment variables', a test.serial('Verify package, token and repository access with alternative environment varialbes', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_URL = 'https://othertesturl.com:443'; - process.env.GITHUB_TOKEN = 'github_token'; - process.env.GITHUB_PREFIX = 'prefix'; - - const github = authenticate() + const env = { + GITHUB_URL: 'https://othertesturl.com:443', + GITHUB_TOKEN: 'github_token', + GITHUB_PREFIX: 'prefix', + }; + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( - verify({}, {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) + verify({}, {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) ); t.true(github.isDone()); }); @@ -165,14 +155,17 @@ test.serial('Verify package, token and repository access with alternative enviro test.serial('Verify "proxy" is a String', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const proxy = 'https://locahost'; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( - verify({proxy}, {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) + verify( + {proxy}, + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + ) ); t.true(github.isDone()); @@ -181,14 +174,17 @@ test.serial('Verify "proxy" is a String', async t => { test.serial('Verify "proxy" is an object with "host" and "port" properties', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const proxy = {host: 'locahost', port: 80}; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( - verify({proxy}, {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) + verify( + {proxy}, + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + ) ); t.true(github.isDone()); @@ -197,14 +193,17 @@ test.serial('Verify "proxy" is an object with "host" and "port" properties', asy test.serial('Verify "assets" is a String', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assets = 'file2.js'; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( - verify({assets}, {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) + verify( + {assets}, + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + ) ); t.true(github.isDone()); @@ -213,14 +212,17 @@ test.serial('Verify "assets" is a String', async t => { test.serial('Verify "assets" is an Object with a path property', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assets = {path: 'file2.js'}; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( - verify({assets}, {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) + verify( + {assets}, + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + ) ); t.true(github.isDone()); @@ -229,14 +231,17 @@ test.serial('Verify "assets" is an Object with a path property', async t => { test.serial('Verify "assets" is an Array of Object with a path property', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assets = [{path: 'file1.js'}, {path: 'file2.js'}]; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( - verify({assets}, {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) + verify( + {assets}, + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + ) ); t.true(github.isDone()); @@ -245,14 +250,17 @@ test.serial('Verify "assets" is an Array of Object with a path property', async test.serial('Verify "assets" is an Array of glob Arrays', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assets = [['dist/**', '!**/*.js'], 'file2.js']; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( - verify({assets}, {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) + verify( + {assets}, + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + ) ); t.true(github.isDone()); @@ -261,14 +269,17 @@ test.serial('Verify "assets" is an Array of glob Arrays', async t => { test.serial('Verify "assets" is an Array of Object with a glob Arrays in path property', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assets = [{path: ['dist/**', '!**/*.js']}, {path: 'file2.js'}]; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( - verify({assets}, {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) + verify( + {assets}, + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + ) ); t.true(github.isDone()); @@ -277,14 +288,17 @@ test.serial('Verify "assets" is an Array of Object with a glob Arrays in path pr test.serial('Verify "labels" is a String', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const labels = 'semantic-release'; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( - verify({labels}, {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger}) + verify( + {labels}, + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + ) ); t.true(github.isDone()); @@ -293,16 +307,16 @@ test.serial('Verify "labels" is a String', async t => { test.serial('Verify "assignees" is a String', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assignees = 'user'; - const github = authenticate() + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: true}}); await t.notThrows( verify( {assignees}, - {options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} + {env, options: {repositoryUrl: `git@othertesturl.com:${owner}/${repo}.git`}, logger: t.context.logger} ) ); @@ -311,7 +325,10 @@ test.serial('Verify "assignees" is a String', async t => { test.serial('Throw SemanticReleaseError for missing github token', async t => { const [error] = await t.throws( - verify({}, {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger}) + verify( + {}, + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + ) ); t.is(error.name, 'SemanticReleaseError'); @@ -321,13 +338,13 @@ test.serial('Throw SemanticReleaseError for missing github token', async t => { test.serial('Throw SemanticReleaseError for invalid token', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; - const github = authenticate() + const env = {GH_TOKEN: 'github_token'}; + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(401); const [error] = await t.throws( - verify({}, {options: {repositoryUrl: `https://github.com/${owner}/${repo}.git`}, logger: t.context.logger}) + verify({}, {env, options: {repositoryUrl: `https://github.com/${owner}/${repo}.git`}, logger: t.context.logger}) ); t.is(error.name, 'SemanticReleaseError'); @@ -336,9 +353,9 @@ test.serial('Throw SemanticReleaseError for invalid token', async t => { }); test.serial('Throw SemanticReleaseError for invalid repositoryUrl', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; - const [error] = await t.throws(verify({}, {options: {repositoryUrl: 'invalid_url'}, logger: t.context.logger})); + const [error] = await t.throws(verify({}, {env, options: {repositoryUrl: 'invalid_url'}, logger: t.context.logger})); t.is(error.name, 'SemanticReleaseError'); t.is(error.code, 'EINVALIDGITHUBURL'); @@ -347,13 +364,13 @@ test.serial('Throw SemanticReleaseError for invalid repositoryUrl', async t => { test.serial("Throw SemanticReleaseError if token doesn't have the push permission on the repository", async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; - const github = authenticate() + const env = {GH_TOKEN: 'github_token'}; + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(200, {permissions: {push: false}}); const [error] = await t.throws( - verify({}, {options: {repositoryUrl: `https://github.com/${owner}/${repo}.git`}, logger: t.context.logger}) + verify({}, {env, options: {repositoryUrl: `https://github.com/${owner}/${repo}.git`}, logger: t.context.logger}) ); t.is(error.name, 'SemanticReleaseError'); @@ -364,14 +381,14 @@ test.serial("Throw SemanticReleaseError if token doesn't have the push permissio test.serial("Throw SemanticReleaseError if the repository doesn't exist", async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; - const github = authenticate() + const env = {GH_TOKEN: 'github_token'}; + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .times(4) .reply(404); const [error] = await t.throws( - verify({}, {options: {repositoryUrl: `https://github.com/${owner}/${repo}.git`}, logger: t.context.logger}) + verify({}, {env, options: {repositoryUrl: `https://github.com/${owner}/${repo}.git`}, logger: t.context.logger}) ); t.is(error.name, 'SemanticReleaseError'); @@ -382,13 +399,13 @@ test.serial("Throw SemanticReleaseError if the repository doesn't exist", async test.serial('Throw error if github return any other errors', async t => { const owner = 'test_user'; const repo = 'test_repo'; - process.env.GITHUB_TOKEN = 'github_token'; - const github = authenticate() + const env = {GH_TOKEN: 'github_token'}; + const github = authenticate(env) .get(`/repos/${owner}/${repo}`) .reply(500); const error = await t.throws( - verify({}, {options: {repositoryUrl: `https://github.com/${owner}/${repo}.git`}, logger: t.context.logger}) + verify({}, {env, options: {repositoryUrl: `https://github.com/${owner}/${repo}.git`}, logger: t.context.logger}) ); t.is(error.code, 500); @@ -396,13 +413,13 @@ test.serial('Throw error if github return any other errors', async t => { }); test.serial('Throw SemanticReleaseError if "proxy" option is not a String or an Object', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const proxy = 42; const [error] = await t.throws( verify( {proxy}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -411,13 +428,13 @@ test.serial('Throw SemanticReleaseError if "proxy" option is not a String or an }); test.serial('Throw SemanticReleaseError if "proxy" option is an Object with invalid properties', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const proxy = {host: 42}; const [error] = await t.throws( verify( {proxy}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -426,13 +443,13 @@ test.serial('Throw SemanticReleaseError if "proxy" option is an Object with inva }); test.serial('Throw SemanticReleaseError if "assets" option is not a String or an Array of Objects', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assets = 42; const [error] = await t.throws( verify( {assets}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -441,13 +458,13 @@ test.serial('Throw SemanticReleaseError if "assets" option is not a String or an }); test.serial('Throw SemanticReleaseError if "assets" option is an Array with invalid elements', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assets = ['file.js', 42]; const [error] = await t.throws( verify( {assets}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -456,13 +473,13 @@ test.serial('Throw SemanticReleaseError if "assets" option is an Array with inva }); test.serial('Throw SemanticReleaseError if "assets" option is an Object missing the "path" property', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assets = {name: 'file.js'}; const [error] = await t.throws( verify( {assets}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -473,13 +490,13 @@ test.serial('Throw SemanticReleaseError if "assets" option is an Object missing test.serial( 'Throw SemanticReleaseError if "assets" option is an Array with objects missing the "path" property', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assets = [{path: 'lib/file.js'}, {name: 'file.js'}]; const [error] = await t.throws( verify( {assets}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -493,7 +510,7 @@ test('Throw SemanticReleaseError if "successComment" option is not a String', as const [error] = await t.throws( verify( {successComment}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -506,7 +523,7 @@ test('Throw SemanticReleaseError if "successComment" option is an empty String', const [error] = await t.throws( verify( {successComment}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -519,7 +536,7 @@ test('Throw SemanticReleaseError if "successComment" option is a whitespace Stri const [error] = await t.throws( verify( {successComment}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -532,7 +549,7 @@ test('Throw SemanticReleaseError if "failTitle" option is not a String', async t const [error] = await t.throws( verify( {failTitle}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -545,7 +562,7 @@ test('Throw SemanticReleaseError if "failTitle" option is an empty String', asyn const [error] = await t.throws( verify( {failTitle}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -558,7 +575,7 @@ test('Throw SemanticReleaseError if "failTitle" option is a whitespace String', const [error] = await t.throws( verify( {failTitle}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -571,7 +588,7 @@ test('Throw SemanticReleaseError if "failComment" option is not a String', async const [error] = await t.throws( verify( {failComment}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -584,7 +601,7 @@ test('Throw SemanticReleaseError if "failComment" option is an empty String', as const [error] = await t.throws( verify( {failComment}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -597,7 +614,7 @@ test('Throw SemanticReleaseError if "failComment" option is a whitespace String' const [error] = await t.throws( verify( {failComment}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -606,13 +623,13 @@ test('Throw SemanticReleaseError if "failComment" option is a whitespace String' }); test.serial('Throw SemanticReleaseError if "labels" option is not a String or an Array of String', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const labels = 42; const [error] = await t.throws( verify( {labels}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -621,13 +638,13 @@ test.serial('Throw SemanticReleaseError if "labels" option is not a String or an }); test.serial('Throw SemanticReleaseError if "labels" option is an Array with invalid elements', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const labels = ['label1', 42]; const [error] = await t.throws( verify( {labels}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -640,7 +657,7 @@ test('Throw SemanticReleaseError if "labels" option is a whitespace String', asy const [error] = await t.throws( verify( {labels}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -649,13 +666,13 @@ test('Throw SemanticReleaseError if "labels" option is a whitespace String', asy }); test.serial('Throw SemanticReleaseError if "assignees" option is not a String or an Array of String', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assignees = 42; const [error] = await t.throws( verify( {assignees}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -664,13 +681,13 @@ test.serial('Throw SemanticReleaseError if "assignees" option is not a String or }); test.serial('Throw SemanticReleaseError if "assignees" option is an Array with invalid elements', async t => { - process.env.GITHUB_TOKEN = 'github_token'; + const env = {GH_TOKEN: 'github_token'}; const assignees = ['user', 42]; const [error] = await t.throws( verify( {assignees}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) ); @@ -683,7 +700,7 @@ test('Throw SemanticReleaseError if "assignees" option is a whitespace String', const [error] = await t.throws( verify( {assignees}, - {options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} + {env: {}, options: {repositoryUrl: 'https://github.com/semantic-release/github.git'}, logger: t.context.logger} ) );