From feb8766c4d8cc8c54c042d010720a8dcf11c71cf Mon Sep 17 00:00:00 2001 From: Tiffany K Date: Fri, 9 Jul 2021 12:13:39 -0700 Subject: [PATCH] feat(2492): Update to eslint-config-screwdriver v5 (#192) --- index.js | 670 +++++++------- package.json | 14 +- test/index.test.js | 2141 ++++++++++++++++++++++---------------------- 3 files changed, 1456 insertions(+), 1369 deletions(-) diff --git a/index.js b/index.js index 07af336..9b62b2e 100644 --- a/index.js +++ b/index.js @@ -39,9 +39,7 @@ const DESCRIPTION_MAP = { FAILURE: 'Did not work as expected.', PENDING: 'Parked it as Pending...' }; -const PERMITTED_RELEASE_EVENT = [ - 'published' -]; +const PERMITTED_RELEASE_EVENT = ['published']; const DEPLOY_KEY_GENERATOR_CONFIG = { DEPLOY_KEYS_FILE: `${__dirname}/keys_rsa`, @@ -58,7 +56,7 @@ const DEPLOY_KEY_GENERATOR_CONFIG = { * @return {Object} An object with the user, repo, host, branch, and rootDir */ function getInfo(scmUrl, rootDir) { - const matched = (schema.config.regex.CHECKOUT_URL).exec(scmUrl); + const matched = schema.config.regex.CHECKOUT_URL.exec(scmUrl); // Check if regex did not pass if (!matched) { @@ -90,20 +88,25 @@ class GithubScm extends Scm { * @param {Function} callback Callback function from github API */ _githubCommand(options, callback) { - const config = Object.assign({ auth: `token ${options.token}` }, this.octokitConfig); + const config = { auth: `token ${options.token}`, ...this.octokitConfig }; const octokit = new Octokit(config); const scopeType = options.scopeType || 'repos'; if (scopeType === 'request' || scopeType === 'paginate') { // for deprecation of 'octokit.repos.getById({id})' // ref: https://github.com/octokit/rest.js/releases/tag/v16.0.1 - octokit[scopeType](options.route, options.params).then(function cb() { // Use "function" (not "arrow function") for getting "arguments" - callback(null, ...arguments); - }).catch(err => callback(err)); + octokit[scopeType](options.route, options.params) + .then(function cb() { + // Use "function" (not "arrow function") for getting "arguments" + callback(null, ...arguments); + }) + .catch(err => callback(err)); } else { - octokit[scopeType][options.action](options.params).then(function cb() { - callback(null, ...arguments); - }).catch(err => callback(err)); + octokit[scopeType][options.action](options.params) + .then(function cb() { + callback(null, ...arguments); + }) + .catch(err => callback(err)); } } @@ -128,32 +131,70 @@ class GithubScm extends Scm { super(); // Validate configuration - this.config = joi.attempt(config, joi.object().keys({ - privateRepo: joi.boolean().optional().default(false), - gheProtocol: joi.string().optional().default('https'), - gheHost: joi.string().optional().description('GitHub Enterpise host'), - username: joi.string().optional().default('sd-buildbot'), - email: joi.string().optional().default('dev-null@screwdriver.cd'), - commentUserToken: joi.string().optional().description('Token for PR comments'), - autoDeployKeyGeneration: joi.boolean().optional().default(false), - readOnly: joi.object().keys({ - enabled: joi.boolean().optional(), - username: joi.string().optional(), - accessToken: joi.string().optional(), - cloneType: joi.string().valid('https', 'ssh').optional().default('https') - }).optional().default({}), - https: joi.boolean().optional().default(false), - oauthClientId: joi.string().required(), - oauthClientSecret: joi.string().required(), - fusebox: joi.object().default({}), - secret: joi.string().required() - }).unknown(true), 'Invalid config for GitHub'); + this.config = joi.attempt( + config, + joi + .object() + .keys({ + privateRepo: joi + .boolean() + .optional() + .default(false), + gheProtocol: joi + .string() + .optional() + .default('https'), + gheHost: joi + .string() + .optional() + .description('GitHub Enterpise host'), + username: joi + .string() + .optional() + .default('sd-buildbot'), + email: joi + .string() + .optional() + .default('dev-null@screwdriver.cd'), + commentUserToken: joi + .string() + .optional() + .description('Token for PR comments'), + autoDeployKeyGeneration: joi + .boolean() + .optional() + .default(false), + readOnly: joi + .object() + .keys({ + enabled: joi.boolean().optional(), + username: joi.string().optional(), + accessToken: joi.string().optional(), + cloneType: joi + .string() + .valid('https', 'ssh') + .optional() + .default('https') + }) + .optional() + .default({}), + https: joi + .boolean() + .optional() + .default(false), + oauthClientId: joi.string().required(), + oauthClientSecret: joi.string().required(), + fusebox: joi.object().default({}), + secret: joi.string().required() + }) + .unknown(true), + 'Invalid config for GitHub' + ); this.octokitConfig = {}; if (this.config.gheHost) { - this.octokitConfig.baseUrl = - `${this.config.gheProtocol}://${this.config.gheHost}/api/v3`; + this.octokitConfig.baseUrl = `${this.config.gheProtocol}://${this.config.gheHost}/api/v3`; } // eslint-disable-next-line no-underscore-dangle @@ -225,7 +266,7 @@ class GithubScm extends Scm { * @return {Promise} */ promiseToWait(timeToWait) { - return new Promise((resolve) => { + return new Promise(resolve => { setTimeout(() => resolve(), timeToWait * 1000); }); } @@ -247,9 +288,9 @@ class GithubScm extends Scm { if (pullRequestInfo.mergeable) { return { success: true, pullRequestInfo }; - } else if (count >= POLLING_MAX_ATTEMPT - 1) { - logger.warn('Computing mergerbility did not finish. ' - + `scmUri: ${scmUri}, prNum: ${prNum}`); + } + if (count >= POLLING_MAX_ATTEMPT - 1) { + logger.warn(`Computing mergerbility did not finish. scmUri: ${scmUri}, prNum: ${prNum}`); return { success: false, pullRequestInfo }; } @@ -336,21 +377,24 @@ class GithubScm extends Scm { const password = DEPLOY_KEY_GENERATOR_CONFIG.DEPLOY_KEYS_PASSWORD; const format = DEPLOY_KEY_GENERATOR_CONFIG.DEPLOY_KEYS_FORMAT; - keygen({ - location, - comment, - password, - read: true, - format - }, (err, keyPair) => { - if (err) { - logger.error('Failed to create keys: ', err); - - return reject(err); - } + keygen( + { + location, + comment, + password, + read: true, + format + }, + (err, keyPair) => { + if (err) { + logger.error('Failed to create keys: ', err); + + return reject(err); + } - return resolve(keyPair); - }); + return resolve(keyPair); + } + ); }); } @@ -424,9 +468,7 @@ class GithubScm extends Scm { } }); - const screwdriverHook = hooks.data.find(hook => - hoek.reach(hook, 'config.url') === config.url - ); + const screwdriverHook = hooks.data.find(hook => hoek.reach(hook, 'config.url') === config.url); if (!screwdriverHook && hooks.data.length === WEBHOOK_PAGE_SIZE) { config.page += 1; @@ -456,8 +498,7 @@ class GithubScm extends Scm { let action = 'createWebhook'; const params = { active: true, - events: config.actions.length === 0 ? - ['push', 'pull_request', 'create', 'release'] : config.actions, + events: config.actions.length === 0 ? ['push', 'pull_request', 'create', 'release'] : config.actions, owner: config.scmInfo.owner, repo: config.scmInfo.repo, name: 'web', @@ -549,12 +590,13 @@ class GithubScm extends Scm { const command = []; - command.push("export SD_GIT_WRAPPER=\"$(if [ `uname` = 'Darwin' ]; " + - "then echo 'eval'; " + - "else echo 'sd-step exec core/git'; fi)\""); + command.push( + "export SD_GIT_WRAPPER=\"$(if [ `uname` = 'Darwin' ]; " + + "then echo 'eval'; " + + "else echo 'sd-step exec core/git'; fi)\"" + ); - command.push('if [ ! -z $SD_SCM_DEPLOY_KEY ]; ' + - 'then export SCM_CLONE_TYPE=ssh; fi'); + command.push('if [ ! -z $SD_SCM_DEPLOY_KEY ]; then export SCM_CLONE_TYPE=ssh; fi'); // Export environment variables command.push('echo Exporting environment variables'); @@ -563,16 +605,20 @@ class GithubScm extends Scm { if (hoek.reach(this.config, 'readOnly.cloneType') === 'ssh') { command.push(`export SCM_URL=${sshCheckoutUrl}`); } else { - command.push('if [ ! -z $SCM_USERNAME ] && [ ! -z $SCM_ACCESS_TOKEN ]; ' + - `then export SCM_URL=https://$SCM_USERNAME:$SCM_ACCESS_TOKEN@${checkoutUrl}; ` + - `else export SCM_URL=https://${checkoutUrl}; fi`); + command.push( + 'if [ ! -z $SCM_USERNAME ] && [ ! -z $SCM_ACCESS_TOKEN ]; ' + + `then export SCM_URL=https://$SCM_USERNAME:$SCM_ACCESS_TOKEN@${checkoutUrl}; ` + + `else export SCM_URL=https://${checkoutUrl}; fi` + ); } } else { - command.push('if [ ! -z $SCM_CLONE_TYPE ] && [ $SCM_CLONE_TYPE = ssh ]; ' + - `then export SCM_URL=${sshCheckoutUrl}; ` + - 'elif [ ! -z $SCM_USERNAME ] && [ ! -z $SCM_ACCESS_TOKEN ]; ' + - `then export SCM_URL=https://$SCM_USERNAME:$SCM_ACCESS_TOKEN@${checkoutUrl}; ` + - `else export SCM_URL=https://${checkoutUrl}; fi`); + command.push( + 'if [ ! -z $SCM_CLONE_TYPE ] && [ $SCM_CLONE_TYPE = ssh ]; ' + + `then export SCM_URL=${sshCheckoutUrl}; ` + + 'elif [ ! -z $SCM_USERNAME ] && [ ! -z $SCM_ACCESS_TOKEN ]; ' + + `then export SCM_URL=https://$SCM_USERNAME:$SCM_ACCESS_TOKEN@${checkoutUrl}; ` + + `else export SCM_URL=https://${checkoutUrl}; fi` + ); } command.push('export GIT_URL=$SCM_URL.git'); // git 1.7.1 doesn't support --no-edit with merge, this should do same thing @@ -583,11 +629,13 @@ class GithubScm extends Scm { // 2. Store the deploy private key to /tmp/git_key // 3. Give it the necessary permissions and set env var to instruct git to use the key // 4. Add SCM host as a known host by adding config to ~/.ssh/config - command.push('if [ ! -z $SD_SCM_DEPLOY_KEY ] && [ $SCM_CLONE_TYPE = ssh ]; ' + - 'then ' + - 'echo $SD_SCM_DEPLOY_KEY | base64 -d > /tmp/git_key && echo "" >> /tmp/git_key && ' + - 'chmod 600 /tmp/git_key && export GIT_SSH_COMMAND="ssh -i /tmp/git_key" && ' + - `mkdir -p ~/.ssh/ && printf "%s\n" "${gitConfigB64}" | base64 -d >> ~/.ssh/config; fi`); + command.push( + 'if [ ! -z $SD_SCM_DEPLOY_KEY ] && [ $SCM_CLONE_TYPE = ssh ]; ' + + 'then ' + + 'echo $SD_SCM_DEPLOY_KEY | base64 -d > /tmp/git_key && echo "" >> /tmp/git_key && ' + + 'chmod 600 /tmp/git_key && export GIT_SSH_COMMAND="ssh -i /tmp/git_key" && ' + + `mkdir -p ~/.ssh/ && printf "%s\n" "${gitConfigB64}" | base64 -d >> ~/.ssh/config; fi` + ); // Set config command.push('echo Setting user name and user email'); @@ -599,59 +647,64 @@ class GithubScm extends Scm { // eslint-disable-next-line max-len command.push('if [ ! -z $SD_CHECKOUT_DIR ]; then export SD_CHECKOUT_DIR_FINAL=$SD_CHECKOUT_DIR; fi'); - const shallowCloneCmd = 'else if [ ! -z "$GIT_SHALLOW_CLONE_SINCE" ]; ' - + 'then export GIT_SHALLOW_CLONE_DEPTH_OPTION=' - + '"--shallow-since=\'$GIT_SHALLOW_CLONE_SINCE\'"; ' - + 'else if [ -z $GIT_SHALLOW_CLONE_DEPTH ]; ' - + 'then export GIT_SHALLOW_CLONE_DEPTH=50; fi; ' - + 'export GIT_SHALLOW_CLONE_DEPTH_OPTION="--depth=$GIT_SHALLOW_CLONE_DEPTH"; fi; ' - + 'export GIT_SHALLOW_CLONE_BRANCH="--no-single-branch"; ' - + 'if [ "$GIT_SHALLOW_CLONE_SINGLE_BRANCH" = true ]; ' - + 'then export GIT_SHALLOW_CLONE_BRANCH=""; fi; ' - + '$SD_GIT_WRAPPER ' - + '"git clone $GIT_SHALLOW_CLONE_DEPTH_OPTION $GIT_SHALLOW_CLONE_BRANCH '; + const shallowCloneCmd = + 'else if [ ! -z "$GIT_SHALLOW_CLONE_SINCE" ]; ' + + 'then export GIT_SHALLOW_CLONE_DEPTH_OPTION=' + + '"--shallow-since=\'$GIT_SHALLOW_CLONE_SINCE\'"; ' + + 'else if [ -z $GIT_SHALLOW_CLONE_DEPTH ]; ' + + 'then export GIT_SHALLOW_CLONE_DEPTH=50; fi; ' + + 'export GIT_SHALLOW_CLONE_DEPTH_OPTION="--depth=$GIT_SHALLOW_CLONE_DEPTH"; fi; ' + + 'export GIT_SHALLOW_CLONE_BRANCH="--no-single-branch"; ' + + 'if [ "$GIT_SHALLOW_CLONE_SINGLE_BRANCH" = true ]; ' + + 'then export GIT_SHALLOW_CLONE_BRANCH=""; fi; ' + + '$SD_GIT_WRAPPER ' + + '"git clone $GIT_SHALLOW_CLONE_DEPTH_OPTION $GIT_SHALLOW_CLONE_BRANCH '; // Checkout config pipeline if this is a child pipeline if (config.parentConfig) { - const parentCheckoutUrl = `${config.parentConfig.host}/${config.parentConfig.org}/` - + `${config.parentConfig.repo}`; // URL for https - const parentSshCheckoutUrl = `git@${config.parentConfig.host}:` - + `${config.parentConfig.org}/${config.parentConfig.repo}`; // URL for ssh + const parentCheckoutUrl = `${config.parentConfig.host}/${config.parentConfig.org}/${config.parentConfig.repo}`; // URL for https + const parentSshCheckoutUrl = `git@${config.parentConfig.host}:${config.parentConfig.org}/${config.parentConfig.repo}`; // URL for ssh const parentBranch = config.parentConfig.branch; const externalConfigDir = '$SD_ROOT_DIR/config'; - command.push('if [ ! -z $SCM_CLONE_TYPE ] && [ $SCM_CLONE_TYPE = ssh ]; ' + - `then export CONFIG_URL=${parentSshCheckoutUrl}; ` + - 'elif [ ! -z $SCM_USERNAME ] && [ ! -z $SCM_ACCESS_TOKEN ]; ' + - 'then export CONFIG_URL=https://$SCM_USERNAME:$SCM_ACCESS_TOKEN@' - + `${parentCheckoutUrl}; ` + - `else export CONFIG_URL=https://${parentCheckoutUrl}; fi`); + command.push( + 'if [ ! -z $SCM_CLONE_TYPE ] && [ $SCM_CLONE_TYPE = ssh ]; ' + + `then export CONFIG_URL=${parentSshCheckoutUrl}; ` + + 'elif [ ! -z $SCM_USERNAME ] && [ ! -z $SCM_ACCESS_TOKEN ]; ' + + 'then export CONFIG_URL=https://$SCM_USERNAME:$SCM_ACCESS_TOKEN@' + + `${parentCheckoutUrl}; ` + + `else export CONFIG_URL=https://${parentCheckoutUrl}; fi` + ); command.push(`export SD_CONFIG_DIR=${externalConfigDir}`); // Git clone command.push(`echo 'Cloning external config repo ${parentCheckoutUrl}'`); - command.push(`${'if [ ! -z $GIT_SHALLOW_CLONE ] && [ $GIT_SHALLOW_CLONE = false ]; ' - + 'then $SD_GIT_WRAPPER ' - + `"git clone --recursive --quiet --progress --branch '${parentBranch}' ` - + '$CONFIG_URL $SD_CONFIG_DIR"; '}${shallowCloneCmd}` - + `--recursive --quiet --progress --branch '${parentBranch}' ` - + '$CONFIG_URL $SD_CONFIG_DIR"; fi'); + command.push( + `${'if [ ! -z $GIT_SHALLOW_CLONE ] && [ $GIT_SHALLOW_CLONE = false ]; ' + + 'then $SD_GIT_WRAPPER ' + + `"git clone --recursive --quiet --progress --branch '${parentBranch}' ` + + '$CONFIG_URL $SD_CONFIG_DIR"; '}${shallowCloneCmd}` + + `--recursive --quiet --progress --branch '${parentBranch}' ` + + '$CONFIG_URL $SD_CONFIG_DIR"; fi' + ); // Reset to SHA - command.push('$SD_GIT_WRAPPER "git -C $SD_CONFIG_DIR reset --hard ' - + `${config.parentConfig.sha} --"`); + command.push(`$SD_GIT_WRAPPER "git -C $SD_CONFIG_DIR reset --hard ${config.parentConfig.sha} --"`); command.push(`echo Reset external config repo to ${config.parentConfig.sha}`); } if (config.manifest) { - const curlWrapper = '$(if curl --version > /dev/null 2>&1; ' + + const curlWrapper = + '$(if curl --version > /dev/null 2>&1; ' + "then echo 'eval'; " + "else echo 'sd-step exec core/curl'; fi)"; - const wgetWrapper = '$(if wget --version > /dev/null 2>&1; ' + + const wgetWrapper = + '$(if wget --version > /dev/null 2>&1; ' + "then echo 'eval'; " + "else echo 'sd-step exec core/wget'; fi)"; - const grepWrapper = '$(if grep --version > /dev/null 2>&1; ' + + const grepWrapper = + '$(if grep --version > /dev/null 2>&1; ' + "then echo 'eval'; " + "else echo 'sd-step exec core/grep'; fi)"; @@ -660,41 +713,46 @@ class GithubScm extends Scm { const sdRepoReleasesFile = 'sd-repo-releases.html'; const sdRepoLatestFile = 'sd-repo-latest'; - command.push('echo Checking out code using the repo manifest defined in ' - + `${config.manifest}`); + command.push(`echo Checking out code using the repo manifest defined in ${config.manifest}`); // Get the repo binary command.push(`${curlWrapper} "curl -s ${repoDownloadUrl} > /usr/local/bin/repo"`); command.push('chmod a+x /usr/local/bin/repo'); // Get the sd-repo binary and execute it - command.push(`${wgetWrapper} "wget -q -O - ${sdRepoReleasesUrl} > ` - + `${sdRepoReleasesFile}"`); - command.push(`${grepWrapper} "grep -E -o ` - + '/screwdriver-cd/sd-repo/releases/download/v[0-9.]*/sd-repo_linux_amd64 ' - + `${sdRepoReleasesFile} > ${sdRepoLatestFile}"`); - command.push(`${wgetWrapper} "wget --base=http://github.com/ -q -i ` - + `${sdRepoLatestFile} -O /usr/local/bin/sd-repo"`); + command.push(`${wgetWrapper} "wget -q -O - ${sdRepoReleasesUrl} > ${sdRepoReleasesFile}"`); + command.push( + `${grepWrapper} "grep -E -o ` + + '/screwdriver-cd/sd-repo/releases/download/v[0-9.]*/sd-repo_linux_amd64 ' + + `${sdRepoReleasesFile} > ${sdRepoLatestFile}"` + ); + command.push( + `${wgetWrapper} "wget --base=http://github.com/ -q -i ` + + `${sdRepoLatestFile} -O /usr/local/bin/sd-repo"` + ); command.push('chmod a+x /usr/local/bin/sd-repo'); - command.push(`sd-repo -manifestUrl=${config.manifest} ` - + `-sourceRepo=${config.org}/${config.repo}`); + command.push(`sd-repo -manifestUrl=${config.manifest} -sourceRepo=${config.org}/${config.repo}`); // sourcePath is the file created by `sd-repo` which contains the relative path to the source repository const sourcePath = 'sourcePath'; // Export $SD_SOURCE_DIR to source repo path and cd into it - command.push(`if [ $(cat ${sourcePath}) != "." ]; ` - + `then export SD_SOURCE_DIR=$SD_SOURCE_DIR/$(cat ${sourcePath}); fi`); + command.push( + `if [ $(cat ${sourcePath}) != "." ]; ` + + `then export SD_SOURCE_DIR=$SD_SOURCE_DIR/$(cat ${sourcePath}); fi` + ); command.push('cd $SD_SOURCE_DIR'); } else { // Git clone command.push(`echo 'Cloning ${checkoutUrl}, on branch ${branch}'`); - command.push(`${'if [ ! -z $GIT_SHALLOW_CLONE ] && [ $GIT_SHALLOW_CLONE = false ]; ' - + 'then $SD_GIT_WRAPPER ' - + `"git clone --recursive --quiet --progress --branch '${branch}' ` - + '$SCM_URL $SD_CHECKOUT_DIR_FINAL"; '}${shallowCloneCmd}` - + `--recursive --quiet --progress --branch '${branch}' ` - + '$SCM_URL $SD_CHECKOUT_DIR_FINAL"; fi'); + command.push( + `${'if [ ! -z $GIT_SHALLOW_CLONE ] && [ $GIT_SHALLOW_CLONE = false ]; ' + + 'then $SD_GIT_WRAPPER ' + + `"git clone --recursive --quiet --progress --branch '${branch}' ` + + '$SCM_URL $SD_CHECKOUT_DIR_FINAL"; '}${shallowCloneCmd}` + + `--recursive --quiet --progress --branch '${branch}' ` + + '$SCM_URL $SD_CHECKOUT_DIR_FINAL"; fi' + ); // Reset to SHA command.push(`$SD_GIT_WRAPPER "git reset --hard '${checkoutRef}' --"`); command.push(`echo 'Reset to ${checkoutRef}'`); @@ -814,9 +872,7 @@ class GithubScm extends Scm { } catch (err) { // Suspended user if (err.message.match(/suspend/i)) { - logger.info( - `User's account suspended for ${config.scmUri}, ` + - 'it will be removed from pipeline admins.'); + logger.info(`User's account suspended for ${config.scmUri}, it will be removed from pipeline admins.`); return { admin: false, push: false, pull: false }; } @@ -851,8 +907,8 @@ class GithubScm extends Scm { org: config.organization } }); - const role = permission.data.role; - const state = permission.data.state; + const { role } = permission.data; + const { state } = permission.data; if (state !== 'active') { return result; @@ -951,7 +1007,8 @@ class GithubScm extends Scm { }); return tagObj.data.object.sha; - } else if (refObj.data.object.type === 'commit') { + } + if (refObj.data.object.type === 'commit') { // commit or lightweight tag return refObj.data.object.sha; } @@ -977,14 +1034,14 @@ class GithubScm extends Scm { * @param {String} config.description Status description * @return {Promise} Resolves when operation completed */ - async _updateCommitStatus({ scmUri, sha, buildStatus, token, jobName, url, - pipelineId, context, description }) { + async _updateCommitStatus({ scmUri, sha, buildStatus, token, jobName, url, pipelineId, context, description }) { const { owner, repo } = await this.lookupScmUri({ scmUri, token }); - const statusTitle = context ? `Screwdriver/${pipelineId}/${context}` : - `Screwdriver/${pipelineId}/${jobName.replace(/^PR-\d+/g, 'PR')}`; // (e.g. Screwdriver/12/PR:main) + const statusTitle = context + ? `Screwdriver/${pipelineId}/${context}` + : `Screwdriver/${pipelineId}/${jobName.replace(/^PR-\d+/g, 'PR')}`; // (e.g. Screwdriver/12/PR:main) const params = { context: statusTitle, description: description || DESCRIPTION_MAP[buildStatus], @@ -1168,8 +1225,8 @@ class GithubScm extends Scm { const authorName = hoek.reach(commit, 'data.commit.author.name'); const committerLogin = hoek.reach(commit, 'data.committer.login'); const committerName = hoek.reach(commit, 'data.commit.committer.name'); - let author = Object.assign({}, DEFAULT_AUTHOR); - let committer = Object.assign({}, DEFAULT_AUTHOR); + let author = { ...DEFAULT_AUTHOR }; + let committer = { ...DEFAULT_AUTHOR }; if (authorLogin) { author = await this.decorateAuthor({ @@ -1226,14 +1283,7 @@ class GithubScm extends Scm { lookupConfig.scmRepo = scmRepo; } - const { - host, - owner, - repo, - branch, - rootDir, - privateRepo - } = await this.lookupScmUri(lookupConfig); + const { host, owner, repo, branch, rootDir, privateRepo } = await this.lookupScmUri(lookupConfig); const baseUrl = `${host}/${owner}/${repo}/tree/${branch}`; @@ -1318,8 +1368,7 @@ class GithubScm extends Scm { const commits = hoek.reach(webhookPayload, 'commits'); const deleted = hoek.reach(webhookPayload, 'deleted'); - const checkoutSshHost = this.config.gheHost - ? this.config.gheHost : 'github.com'; + const checkoutSshHost = this.config.gheHost ? this.config.gheHost : 'github.com'; const regexMatchArray = checkoutUrl.match(CHECKOUT_URL_REGEX); if (!regexMatchArray || regexMatchArray[1] !== checkoutSshHost) { @@ -1334,121 +1383,120 @@ class GithubScm extends Scm { } switch (type) { - case 'pull_request': { - let action = hoek.reach(webhookPayload, 'action'); - const prNum = hoek.reach(webhookPayload, 'pull_request.number'); - const prTitle = hoek.reach(webhookPayload, 'pull_request.title'); - const baseSource = hoek.reach(webhookPayload, 'pull_request.base.repo.id'); - const headSource = hoek.reach(webhookPayload, 'pull_request.head.repo.id'); - const prSource = baseSource === headSource ? 'branch' : 'fork'; - const ref = `pull/${prNum}/merge`; - - // Possible actions - // "opened", "closed", "reopened", "synchronize", - // "assigned", "unassigned", "labeled", "unlabeled", "edited" - if (!['opened', 'reopened', 'synchronize', 'closed'].includes(action)) { - return null; - } + case 'pull_request': { + let action = hoek.reach(webhookPayload, 'action'); + const prNum = hoek.reach(webhookPayload, 'pull_request.number'); + const prTitle = hoek.reach(webhookPayload, 'pull_request.title'); + const baseSource = hoek.reach(webhookPayload, 'pull_request.base.repo.id'); + const headSource = hoek.reach(webhookPayload, 'pull_request.head.repo.id'); + const prSource = baseSource === headSource ? 'branch' : 'fork'; + const ref = `pull/${prNum}/merge`; + + // Possible actions + // "opened", "closed", "reopened", "synchronize", + // "assigned", "unassigned", "labeled", "unlabeled", "edited" + if (!['opened', 'reopened', 'synchronize', 'closed'].includes(action)) { + return null; + } + + if (action === 'synchronize') { + action = 'synchronized'; + } - if (action === 'synchronize') { - action = 'synchronized'; + return { + action, + branch: hoek.reach(webhookPayload, 'pull_request.base.ref'), + checkoutUrl, + prNum, + prTitle, + prRef: ref, + ref, + prSource, + sha: hoek.reach(webhookPayload, 'pull_request.head.sha'), + type: 'pr', + username: hoek.reach(webhookPayload, 'sender.login'), + hookId, + scmContext: scmContexts[0] + }; } + case 'push': { + const ref = hoek.reach(webhookPayload, 'ref'); - return { - action, - branch: hoek.reach(webhookPayload, 'pull_request.base.ref'), - checkoutUrl, - prNum, - prTitle, - prRef: ref, - ref, - prSource, - sha: hoek.reach(webhookPayload, 'pull_request.head.sha'), - type: 'pr', - username: hoek.reach(webhookPayload, 'sender.login'), - hookId, - scmContext: scmContexts[0] - }; - } - case 'push': { - const ref = hoek.reach(webhookPayload, 'ref'); + // repository tag pushed + if (ref.startsWith('refs/tags/')) { + return null; + } - // repository tag pushed - if (ref.startsWith('refs/tags/')) { - return null; - } + if (Array.isArray(commits)) { + commits.forEach(commit => { + commitAuthors.push(commit.author.name); + }); + } - if (Array.isArray(commits)) { - commits.forEach((commit) => { - commitAuthors.push(commit.author.name); - }); - } + if (deleted) { + return null; + } - if (deleted) { - return null; + return { + action: 'push', + branch: hoek.reach(webhookPayload, 'ref').replace(/^refs\/heads\//, ''), + checkoutUrl, + sha: hoek.reach(webhookPayload, 'after'), + type: 'repo', + username: hoek.reach(webhookPayload, 'sender.login'), + commitAuthors, + lastCommitMessage: hoek.reach(webhookPayload, 'head_commit.message') || '', + hookId, + scmContext: scmContexts[0], + ref: hoek.reach(webhookPayload, 'ref') + }; } + case 'release': { + const action = hoek.reach(webhookPayload, 'action'); - return { - action: 'push', - branch: hoek.reach(webhookPayload, 'ref').replace(/^refs\/heads\//, ''), - checkoutUrl, - sha: hoek.reach(webhookPayload, 'after'), - type: 'repo', - username: hoek.reach(webhookPayload, 'sender.login'), - commitAuthors, - lastCommitMessage: hoek.reach(webhookPayload, 'head_commit.message') || '', - hookId, - scmContext: scmContexts[0], - ref: hoek.reach(webhookPayload, 'ref') - }; - } - case 'release': { - const action = hoek.reach(webhookPayload, 'action'); + if (!PERMITTED_RELEASE_EVENT.includes(action)) { + return null; + } - if (!PERMITTED_RELEASE_EVENT.includes(action)) { - return null; + return { + action: 'release', + branch: hoek.reach(webhookPayload, 'repository.default_branch'), + checkoutUrl, + type: 'repo', + username: hoek.reach(webhookPayload, 'sender.login'), + hookId, + scmContext: scmContexts[0], + ref: hoek.reach(webhookPayload, 'release.tag_name'), + releaseId: hoek.reach(webhookPayload, 'release.id').toString(), + releaseName: hoek.reach(webhookPayload, 'release.name') || '', + releaseAuthor: hoek.reach(webhookPayload, 'release.author.login') || '' + }; } + case 'create': { + const refType = hoek.reach(webhookPayload, 'ref_type'); - return { - action: 'release', - branch: hoek.reach(webhookPayload, 'repository.default_branch'), - checkoutUrl, - type: 'repo', - username: hoek.reach(webhookPayload, 'sender.login'), - hookId, - scmContext: scmContexts[0], - ref: hoek.reach(webhookPayload, 'release.tag_name'), - releaseId: hoek.reach(webhookPayload, 'release.id').toString(), - releaseName: hoek.reach(webhookPayload, 'release.name') || '', - releaseAuthor: hoek.reach(webhookPayload, 'release.author.login') || '' - }; - } - case 'create': { - const refType = hoek.reach(webhookPayload, 'ref_type'); + if (refType !== 'tag') { + logger.info('%s event of %s is not available yet in scm-github plugin', type, refType); - if (refType !== 'tag') { - logger.info('%s event of %s is not available yet in scm-github plugin', - type, refType); + return null; + } - return null; + return { + action: 'tag', + branch: hoek.reach(webhookPayload, 'repository.default_branch'), + checkoutUrl, + type: 'repo', + username: hoek.reach(webhookPayload, 'sender.login'), + hookId, + scmContext: scmContexts[0], + ref: hoek.reach(webhookPayload, 'ref') + }; } - return { - action: 'tag', - branch: hoek.reach(webhookPayload, 'repository.default_branch'), - checkoutUrl, - type: 'repo', - username: hoek.reach(webhookPayload, 'sender.login'), - hookId, - scmContext: scmContexts[0], - ref: hoek.reach(webhookPayload, 'ref') - }; - } + default: + logger.info('%s event is not available yet in scm-github plugin', type); - default: - logger.info('%s event is not available yet in scm-github plugin', type); - - return null; + return null; } } @@ -1490,9 +1538,7 @@ class GithubScm extends Scm { const scmContexts = this._getScmContexts(); const scmContext = scmContexts[0]; const scope = ['admin:repo_hook', 'read:org', 'repo:status']; - const cookie = this.config.gheHost - ? `github-${this.config.gheHost}` - : 'github-github.com'; + const cookie = this.config.gheHost ? `github-${this.config.gheHost}` : 'github-github.com'; const bellConfig = { provider: 'github', cookie, @@ -1545,9 +1591,8 @@ class GithubScm extends Scm { repo: scmInfo.repo } }); - const prSource = pullRequestInfo.data.head.repo.id === pullRequestInfo.data.base.repo.id - ? 'branch' - : 'fork'; + const prSource = + pullRequestInfo.data.head.repo.id === pullRequestInfo.data.base.repo.id ? 'branch' : 'fork'; return { name: `PR-${pullRequestInfo.data.number}`, @@ -1588,13 +1633,11 @@ class GithubScm extends Scm { const prComments = await this.prComments(scmInfo, prNum, token); if (prComments) { - const botComment = prComments.comments.find(commentObj => - commentObj.user.login === this.config.username); + const botComment = prComments.comments.find(commentObj => commentObj.user.login === this.config.username); if (botComment) { try { - const pullRequestComment = await this.editPrComment( - botComment.id, scmInfo, comment); + const pullRequestComment = await this.editPrComment(botComment.id, scmInfo, comment); return { commentId: `${pullRequestComment.data.id}`, @@ -1640,9 +1683,7 @@ class GithubScm extends Scm { * @return {Array} Array of scm contexts */ _getScmContexts() { - const contextName = this.config.gheHost - ? [`github:${this.config.gheHost}`] - : ['github:github.com']; + const contextName = this.config.gheHost ? [`github:${this.config.gheHost}`] : ['github:github.com']; return contextName; } @@ -1722,79 +1763,88 @@ class GithubScm extends Scm { scmInfo, page: 1, token: config.token - }).catch((err) => { + }).catch(err => { logger.error('Failed to getBranchList: ', err); throw err; }); } /** - * Open a pull request on the repository with given file change - * - * @method _openPr - * @param {Object} config Configuration - * @param {String} config.checkoutUrl Checkout url to the repo - * @param {String} config.token Service token to authenticate with the SCM service - * @param {String} config.files Files to open pull request with - * @param {String} config.title Pull request title - * @param {String} config.message Pull request message - * @param {String} [config.scmContext] The scm context name - * @return {Promise} Resolves when operation completed without failure - */ + * Open a pull request on the repository with given file change + * + * @method _openPr + * @param {Object} config Configuration + * @param {String} config.checkoutUrl Checkout url to the repo + * @param {String} config.token Service token to authenticate with the SCM service + * @param {String} config.files Files to open pull request with + * @param {String} config.title Pull request title + * @param {String} config.message Pull request message + * @param {String} [config.scmContext] The scm context name + * @return {Promise} Resolves when operation completed without failure + */ async _openPr(config) { const { checkoutUrl, token, files, title, message } = config; const [, , owner, repo, branch] = checkoutUrl.match(CHECKOUT_URL_REGEX); const newBranch = title.replace(/ /g, '_'); - return this.breaker.runCommand({ - action: 'getBranch', - scopeType: 'repos', - token, - params: { - owner, - repo, - branch: branch.slice(1) - } - }) - .then(baseBranch => this.breaker.runCommand({ - action: 'createRef', - scopeType: 'git', + return this.breaker + .runCommand({ + action: 'getBranch', + scopeType: 'repos', token, params: { owner, repo, - ref: `refs/heads/${newBranch}`, - sha: baseBranch.data.commit.sha + branch: branch.slice(1) } - })) - .then(() => Promise.all(files.map(file => + }) + .then(baseBranch => this.breaker.runCommand({ - action: 'createOrUpdateFileContents', - scopeType: 'repos', + action: 'createRef', + scopeType: 'git', token, params: { owner, repo, - path: file.name, - branch: newBranch, - message, - content: Buffer.from(file.content).toString('base64') + ref: `refs/heads/${newBranch}`, + sha: baseBranch.data.commit.sha } - })) - )) - .then(() => this.breaker.runCommand({ - action: 'create', - scopeType: 'pulls', - token, - params: { - owner, - repo, - title, - head: `${owner}:${newBranch}`, - base: branch.slice(1) - } - })) - .catch((err) => { + }) + ) + .then(() => + Promise.all( + files.map(file => + this.breaker.runCommand({ + action: 'createOrUpdateFileContents', + scopeType: 'repos', + token, + params: { + owner, + repo, + path: file.name, + branch: newBranch, + message, + content: Buffer.from(file.content).toString('base64') + } + }) + ) + ) + ) + .then(() => + this.breaker.runCommand({ + action: 'create', + scopeType: 'pulls', + token, + params: { + owner, + repo, + title, + head: `${owner}:${newBranch}`, + base: branch.slice(1) + } + }) + ) + .catch(err => { logger.error('Failed to openPr: ', err); throw err; }); diff --git a/package.json b/package.json index f829058..97ca14a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "url": "git@github.com:screwdriver-cd/scm-github.git" }, "homepage": "https://github.com/screwdriver-cd/scm-github", - "bugs": "https://github.com/screwdriver-cd/scm-github/issues", + "bugs": "https://github.com/screwdriver-cd/screwdriver/issues", "keywords": [ "screwdriver", "yahoo" @@ -32,23 +32,23 @@ "Tiffany Kyi " ], "devDependencies": { - "chai": "^3.5.0", - "eslint": "^4.19.1", - "eslint-config-screwdriver": "^3.0.1", + "chai": "^4.2.0", + "eslint": "^7.5.0", + "eslint-config-screwdriver": "^5.0.1", "mocha": "^8.4.0", "mocha-multi-reporters": "^1.5.1", "mocha-sonarqube-reporter": "^1.0.2", "mockery": "^2.0.0", "nyc": "^15.0.0", - "sinon": "^7.5.0" + "sinon": "^9.0.0" }, "dependencies": { "@hapi/hoek": "^9.2.0", - "@octokit/rest": "^18.6.2", + "@octokit/rest": "^18.6.7", "@octokit/webhooks": "^7.24.3", "circuit-fuses": "^4.0.6", "joi": "^17.4.0", - "screwdriver-data-schema": "^21.3.0", + "screwdriver-data-schema": "^21.6.1", "screwdriver-logger": "^1.0.2", "screwdriver-scm-base": "^7.2.1", "ssh-keygen": "^0.5.0" diff --git a/test/index.test.js b/test/index.test.js index c01fc04..25cc1f6 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -37,7 +37,7 @@ sinon.assert.expose(assert, { prefix: '' }); -describe('index', function () { +describe('index', function() { // Time not important. Only life important this.timeout(5000); @@ -77,7 +77,6 @@ describe('index', function () { listBranches: sinon.stub(), listWebhooks: sinon.stub(), updateWebhook: sinon.stub() - }, users: { getByUsername: sinon.stub() @@ -104,7 +103,7 @@ describe('index', function () { mockery.registerMock('screwdriver-logger', winstonMock); // eslint-disable-next-line global-require - GithubScm = require('../'); + GithubScm = require('..'); scm = new GithubScm({ fusebox: { @@ -164,9 +163,7 @@ describe('index', function () { scm = new GithubScm(config); scm._githubCommand(dummyOption, () => { - assert.equal(scm.octokitConfig.baseUrl, - 'https://github.screwdriver.cd/api/v3' - ); + assert.equal(scm.octokitConfig.baseUrl, 'https://github.screwdriver.cd/api/v3'); assert.calledWith(githubMockClass.Octokit, { auth: 'token sometoken', baseUrl: 'https://github.screwdriver.cd/api/v3' @@ -181,10 +178,7 @@ describe('index', function () { dummyOption.params = { id: 1234 }; scm = new GithubScm(config); scm._githubCommand(dummyOption, () => { - assert.calledWith(githubMock.request, - dummyOption.route, - { id: dummyOption.params.id } - ); + assert.calledWith(githubMock.request, dummyOption.route, { id: dummyOption.params.id }); }); }); }); @@ -205,11 +199,9 @@ describe('index', function () { }); it('promises to get the checkout command for the pipeline branch', () => - scm.getCheckoutCommand(config) - .then((command) => { - assert.deepEqual(command, testCommands); - }) - ); + scm.getCheckoutCommand(config).then(command => { + assert.deepEqual(command, testCommands); + })); it('gets the checkout command with https clone type when read-only is enabled', () => { scm = new GithubScm({ @@ -223,10 +215,9 @@ describe('index', function () { } }); - return scm.getCheckoutCommand(config) - .then((command) => { - assert.deepEqual(command, testReadOnlyCommandsHttps); - }); + return scm.getCheckoutCommand(config).then(command => { + assert.deepEqual(command, testReadOnlyCommandsHttps); + }); }); it('gets the checkout command with ssh clone type when read-only is enabled', () => { @@ -241,29 +232,26 @@ describe('index', function () { } }); - return scm.getCheckoutCommand(config) - .then((command) => { - assert.deepEqual(command, testReadOnlyCommandsSsh); - }); + return scm.getCheckoutCommand(config).then(command => { + assert.deepEqual(command, testReadOnlyCommandsSsh); + }); }); it('promises to get the checkout command for a pull request', () => { config.prRef = 'pull/3/merge'; - return scm.getCheckoutCommand(config) - .then((command) => { - assert.deepEqual(command, testPrCommands); - }); + return scm.getCheckoutCommand(config).then(command => { + assert.deepEqual(command, testPrCommands); + }); }); it('promises to get the checkout command for a pull request from forked repo', () => { config.prRef = 'pull/3/merge'; config.prSource = 'fork'; - return scm.getCheckoutCommand(config) - .then((command) => { - assert.deepEqual(command, testForkPrCommands); - }); + return scm.getCheckoutCommand(config).then(command => { + assert.deepEqual(command, testForkPrCommands); + }); }); it('promises to get the checkout command with custom username and email', () => { @@ -277,37 +265,33 @@ describe('index', function () { email: 'dev-null@my.email.com' }); - return scm.getCheckoutCommand(config) - .then((command) => { - assert.deepEqual(command, testCustomPrCommands); - }); + return scm.getCheckoutCommand(config).then(command => { + assert.deepEqual(command, testCustomPrCommands); + }); }); it('promises to get the checkout command for a repo manifest file', () => { config.manifest = 'git@github.com:org/repo.git/default.xml'; - return scm.getCheckoutCommand(config) - .then((command) => { - assert.deepEqual(command, testRepoCommands); - }); + return scm.getCheckoutCommand(config).then(command => { + assert.deepEqual(command, testRepoCommands); + }); }); it('promises to get the checkout command when rootDir is passed in', () => { config.rootDir = 'src/app/component'; - return scm.getCheckoutCommand(config) - .then((command) => { - assert.deepEqual(command, testRootDirCommands); - }); + return scm.getCheckoutCommand(config).then(command => { + assert.deepEqual(command, testRootDirCommands); + }); }); it('promises to use committed branch', () => { config.commitBranch = 'commitBranch'; - return scm.getCheckoutCommand(config) - .then((command) => { - assert.deepEqual(command, testCommitBranchCommands); - }); + return scm.getCheckoutCommand(config).then(command => { + assert.deepEqual(command, testCommitBranchCommands); + }); }); it('promises to get the checkout command for a child pipeline', () => { @@ -319,10 +303,9 @@ describe('index', function () { sha: '54321' }; - return scm.getCheckoutCommand(config) - .then((command) => { - assert.deepEqual(command, testChildCommands); - }); + return scm.getCheckoutCommand(config).then(command => { + assert.deepEqual(command, testChildCommands); + }); }); }); @@ -340,41 +323,41 @@ describe('index', function () { it('promises to get the commit sha without prNum', () => { githubMock.repos.getBranch.resolves({ data: branch }); - githubMock.request.resolves({ data: { - full_name: 'screwdriver-cd/models' - } }); + githubMock.request.resolves({ + data: { + full_name: 'screwdriver-cd/models' + } + }); - return scm.getCommitSha(config) - .then((data) => { - assert.deepEqual(data, branch.commit.sha); - assert.calledWith(githubMock.repos.getBranch, { - owner: 'screwdriver-cd', - repo: 'models', - branch: 'master' - }); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '920414' } - ); + return scm.getCommitSha(config).then(data => { + assert.deepEqual(data, branch.commit.sha); + assert.calledWith(githubMock.repos.getBranch, { + owner: 'screwdriver-cd', + repo: 'models', + branch: 'master' }); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '920414' }); + }); }); it('promises to get the commit sha with prNum', () => { config.prNum = 1; - githubMock.request.resolves({ data: { - full_name: 'screwdriver-cd/models' - } }); + githubMock.request.resolves({ + data: { + full_name: 'screwdriver-cd/models' + } + }); githubMock.pulls.get.resolves({ data: testPrGet }); - return scm.getCommitSha(config) - .then((data) => { - assert.deepEqual(data, branch.commit.sha); - assert.calledWith(githubMock.pulls.get, { - owner: 'screwdriver-cd', - repo: 'models', - pull_number: config.prNum - }); - delete config.prNum; + return scm.getCommitSha(config).then(data => { + assert.deepEqual(data, branch.commit.sha); + assert.calledWith(githubMock.pulls.get, { + owner: 'screwdriver-cd', + repo: 'models', + pull_number: config.prNum }); + delete config.prNum; + }); }); it('fails when unable to get a repo by ID', () => { @@ -382,42 +365,44 @@ describe('index', function () { githubMock.request.rejects(error); - return scm.getCommitSha(config) + return scm + .getCommitSha(config) .then(() => { assert.fail('This should not fail the test'); }) - .catch((err) => { + .catch(err => { assert.deepEqual(err, error); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '920414' } - ); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '920414' }); }); }); it('fails when unable to get the branch info from a repo', () => { const error = new Error('githubBreaking'); - githubMock.request.resolves({ data: { - full_name: 'screwdriver-cd/models' - } }); + githubMock.request.resolves({ + data: { + full_name: 'screwdriver-cd/models' + } + }); githubMock.repos.getBranch.rejects(error); - return scm.getCommitSha(config).then(() => { - assert.fail('This should not fail the test'); - }).catch((err) => { - assert.deepEqual(err, error); + return scm + .getCommitSha(config) + .then(() => { + assert.fail('This should not fail the test'); + }) + .catch(err => { + assert.deepEqual(err, error); - assert.calledWith(githubMock.repos.getBranch, { - owner: 'screwdriver-cd', - repo: 'models', - branch: 'master' - }); + assert.calledWith(githubMock.repos.getBranch, { + owner: 'screwdriver-cd', + repo: 'models', + branch: 'master' + }); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '920414' } - ); - }); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '920414' }); + }); }); }); @@ -435,63 +420,62 @@ describe('index', function () { it('promises to get the commit sha', () => { githubMock.git.getRef.resolves({ data: { object: { sha, type: 'commit' } } }); - return scm.getCommitRefSha(config) - .then((data) => { - assert.deepEqual(data, sha); + return scm.getCommitRefSha(config).then(data => { + assert.deepEqual(data, sha); - assert.calledWith(githubMock.git.getRef, { - owner: 'screwdriver-cd', - repo: 'models', - ref: 'tags/v0.0.1' - }); + assert.calledWith(githubMock.git.getRef, { + owner: 'screwdriver-cd', + repo: 'models', + ref: 'tags/v0.0.1' }); + }); }); it('promises to get the commit sha for tag', () => { githubMock.git.getRef.resolves({ data: { object: { sha: tagSha, type: 'tag' } } }); githubMock.git.getTag.resolves({ data: { object: { sha } } }); - return scm.getCommitRefSha(config) - .then((data) => { - assert.deepEqual(data, sha); + return scm.getCommitRefSha(config).then(data => { + assert.deepEqual(data, sha); - assert.calledWith(githubMock.git.getRef, { - owner: 'screwdriver-cd', - repo: 'models', - ref: 'tags/v0.0.1' - }); - assert.calledWith(githubMock.git.getTag, { - owner: 'screwdriver-cd', - repo: 'models', - tag_sha: tagSha - }); + assert.calledWith(githubMock.git.getRef, { + owner: 'screwdriver-cd', + repo: 'models', + ref: 'tags/v0.0.1' + }); + assert.calledWith(githubMock.git.getTag, { + owner: 'screwdriver-cd', + repo: 'models', + tag_sha: tagSha }); + }); }); it('throws error when getRef API returned unexpected type', () => { - const type = Math.random().toString(36).slice(-8); - const err = new Error(`Cannot handle ${type} type`); + const type = Math.random() + .toString(36) + .slice(-8); + const err = `Cannot handle ${type} type`; githubMock.git.getRef.resolves({ data: { object: { sha: tagSha, type } } }); githubMock.git.getTag.resolves({ data: { object: { sha } } }); - return scm.getCommitRefSha(config) + return scm + .getCommitRefSha(config) .then(() => assert.fail('This should not fail the test')) - .catch((actual) => { - assert.deepEqual(actual, err); + .catch(actual => { + assert.deepEqual(actual.message, err); }); }); it('throws error when failed to get the commit sha', () => { const err = new Error('githubError'); - githubMock.repos.getCommit.rejects(err); + githubMock.git.getRef.rejects(err); - return scm.getCommitRefSha(config) - .then(() => assert.fail('This should not fail the test')) - .catch((actual) => { - assert.deepEqual(actual, err); - }); + return scm.getCommitRefSha(config).catch(actual => { + assert.deepEqual(actual, err); + }); }); }); @@ -510,31 +494,30 @@ describe('index', function () { }; beforeEach(() => { - githubMock.request.resolves({ data: { - full_name: 'screwdriver-cd/models' - } }); + githubMock.request.resolves({ + data: { + full_name: 'screwdriver-cd/models' + } + }); }); it('promises to get permissions', () => { githubMock.repos.get.resolves({ data: repo }); - return scm.getPermissions(config) - .then((data) => { - assert.deepEqual(data, repo.permissions); + return scm.getPermissions(config).then(data => { + assert.deepEqual(data, repo.permissions); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '359478' } - ); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '359478' }); - assert.calledWith(githubMock.repos.get, { - owner: 'screwdriver-cd', - repo: 'models' - }); + assert.calledWith(githubMock.repos.get, { + owner: 'screwdriver-cd', + repo: 'models' }); + }); }); it('promises to get permissions without querying github when scmRepo is passed', () => { - const configWithScmRepo = Object.assign({}, config); + const configWithScmRepo = { ...config }; configWithScmRepo.scmRepo = { branch: 'branch', @@ -544,17 +527,16 @@ describe('index', function () { githubMock.repos.get.resolves({ data: repo }); - return scm.getPermissions(configWithScmRepo) - .then((data) => { - assert.deepEqual(data, repo.permissions); + return scm.getPermissions(configWithScmRepo).then(data => { + assert.deepEqual(data, repo.permissions); - assert.notCalled(githubMock.request); + assert.notCalled(githubMock.request); - assert.calledWith(githubMock.repos.get, { - owner: 'screwdriver-cd', - repo: 'models' - }); + assert.calledWith(githubMock.repos.get, { + owner: 'screwdriver-cd', + repo: 'models' }); + }); }); it('returns an error when github command fails', () => { @@ -562,16 +544,15 @@ describe('index', function () { githubMock.repos.get.rejects(err); - return scm.getPermissions(config) + return scm + .getPermissions(config) .then(() => { assert.fail('This should not fail the test'); }) - .catch((error) => { + .catch(error => { assert.deepEqual(error, err); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '359478' } - ); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '359478' }); }); }); @@ -581,20 +562,19 @@ describe('index', function () { // in the lookupScmUri() githubMock.request.rejects(err); - return scm.getPermissions(config) - .then((result) => { + return scm + .getPermissions(config) + .then(result => { assert.deepEqual(result, { admin: false, push: false, pull: false }); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '359478' } - ); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '359478' }); assert.notCalled(githubMock.repos.get); assert.calledWith( winstonMock.info, "User's account suspended for github.com:359478:master, " + - 'it will be removed from pipeline admins.' + 'it will be removed from pipeline admins.' ); }) .catch(() => { @@ -619,39 +599,31 @@ describe('index', function () { }; beforeEach(() => { - githubMock.orgs.getMembershipForAuthenticatedUser.resolves( - { data: permission } - ); + githubMock.orgs.getMembershipForAuthenticatedUser.resolves({ data: permission }); }); it('promises to get organization permissions', () => { - githubMock.orgs.getMembershipForAuthenticatedUser.resolves( - { data: permission } - ); + githubMock.orgs.getMembershipForAuthenticatedUser.resolves({ data: permission }); - return scm.getOrgPermissions(config) - .then((data) => { - assert.deepEqual(data, result); - assert.calledWith(githubMock.orgs.getMembershipForAuthenticatedUser, { - org: config.organization - }); + return scm.getOrgPermissions(config).then(data => { + assert.deepEqual(data, result); + assert.calledWith(githubMock.orgs.getMembershipForAuthenticatedUser, { + org: config.organization }); + }); }); it('promises to get organization permissions when state is not active', () => { permission.state = 'inactive'; result.admin = false; - githubMock.orgs.getMembershipForAuthenticatedUser.resolves( - { data: permission } - ); + githubMock.orgs.getMembershipForAuthenticatedUser.resolves({ data: permission }); - return scm.getOrgPermissions(config) - .then((data) => { - assert.deepEqual(data, result); - assert.calledWith(githubMock.orgs.getMembershipForAuthenticatedUser, { - org: config.organization - }); + return scm.getOrgPermissions(config).then(data => { + assert.deepEqual(data, result); + assert.calledWith(githubMock.orgs.getMembershipForAuthenticatedUser, { + org: config.organization }); + }); }); it('returns an error when github command fails', () => { @@ -659,11 +631,12 @@ describe('index', function () { githubMock.orgs.getMembershipForAuthenticatedUser.rejects(err); - return scm.getOrgPermissions(config) + return scm + .getOrgPermissions(config) .then(() => { assert.fail('This should not fail the test'); }) - .catch((error) => { + .catch(error => { assert.deepEqual(error, err); assert.calledWith(githubMock.orgs.getMembershipForAuthenticatedUser, { org: config.organization @@ -683,23 +656,23 @@ describe('index', function () { githubMock.request.resolves({ data: testResponse }); - return scm.lookupScmUri({ - scmUri, - token: 'sometoken' - }).then((repoData) => { - assert.deepEqual(repoData, { - branch: 'targetBranch', - host: 'github.com', - repo: 'models', - owner: 'screwdriver-cd', - rootDir: '', - privateRepo: false - }); + return scm + .lookupScmUri({ + scmUri, + token: 'sometoken' + }) + .then(repoData => { + assert.deepEqual(repoData, { + branch: 'targetBranch', + host: 'github.com', + repo: 'models', + owner: 'screwdriver-cd', + rootDir: '', + privateRepo: false + }); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '23498' } - ); - }); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '23498' }); + }); }); it('looks up a repo by SCM URI with rootDir', () => { @@ -710,23 +683,23 @@ describe('index', function () { githubMock.request.resolves({ data: testResponse }); - return scm.lookupScmUri({ - scmUri: 'github.com:23498:targetBranch:src/app/component', - token: 'sometoken' - }).then((repoData) => { - assert.deepEqual(repoData, { - branch: 'targetBranch', - host: 'github.com', - repo: 'models', - owner: 'screwdriver-cd', - rootDir: 'src/app/component', - privateRepo: false - }); + return scm + .lookupScmUri({ + scmUri: 'github.com:23498:targetBranch:src/app/component', + token: 'sometoken' + }) + .then(repoData => { + assert.deepEqual(repoData, { + branch: 'targetBranch', + host: 'github.com', + repo: 'models', + owner: 'screwdriver-cd', + rootDir: 'src/app/component', + privateRepo: false + }); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '23498' } - ); - }); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '23498' }); + }); }); it('rejects when github command fails', () => { @@ -734,18 +707,21 @@ describe('index', function () { githubMock.request.rejects(testError); - return scm.lookupScmUri({ - scmUri, - token: 'sometoken' - }).then(() => { - assert.fail('This should not fail the test'); - }, (error) => { - assert.deepEqual(error, testError); - - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '23498' } + return scm + .lookupScmUri({ + scmUri, + token: 'sometoken' + }) + .then( + () => { + assert.fail('This should not fail the test'); + }, + error => { + assert.deepEqual(error, testError); + + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '23498' }); + } ); - }); }); }); @@ -771,52 +747,47 @@ describe('index', function () { pipelineId: 675 }; - githubMock.request.resolves({ data: { - full_name: 'screwdriver-cd/models' - } }); + githubMock.request.resolves({ + data: { + full_name: 'screwdriver-cd/models' + } + }); githubMock.repos.createCommitStatus.resolves({ data }); }); it('promises to update commit status on success', () => - scm.updateCommitStatus(config) - .then((result) => { - assert.deepEqual(result, data); + scm.updateCommitStatus(config).then(result => { + assert.deepEqual(result, data); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '14052' } - ); - assert.calledWith(githubMock.repos.createCommitStatus, { - owner: 'screwdriver-cd', - repo: 'models', - sha: config.sha, - state: 'success', - description: 'Everything looks good!', - context: 'Screwdriver/675/main', - target_url: 'https://foo.bar' - }); - }) - ); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '14052' }); + assert.calledWith(githubMock.repos.createCommitStatus, { + owner: 'screwdriver-cd', + repo: 'models', + sha: config.sha, + state: 'success', + description: 'Everything looks good!', + context: 'Screwdriver/675/main', + target_url: 'https://foo.bar' + }); + })); it('promises to update commit status on pending', () => { config.buildStatus = 'PENDING'; - return scm.updateCommitStatus(config) - .then((result) => { - assert.deepEqual(result, data); + return scm.updateCommitStatus(config).then(result => { + assert.deepEqual(result, data); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '14052' } - ); - assert.calledWith(githubMock.repos.createCommitStatus, { - owner: 'screwdriver-cd', - repo: 'models', - sha: config.sha, - state: 'pending', - description: 'Parked it as Pending...', - context: 'Screwdriver/675/main', - target_url: 'https://foo.bar' - }); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '14052' }); + assert.calledWith(githubMock.repos.createCommitStatus, { + owner: 'screwdriver-cd', + repo: 'models', + sha: config.sha, + state: 'pending', + description: 'Parked it as Pending...', + context: 'Screwdriver/675/main', + target_url: 'https://foo.bar' }); + }); }); it('returns an error when update commit status to queued', () => { @@ -824,11 +795,12 @@ describe('index', function () { config.buildStatus = 'QUEUED'; - return scm.updateCommitStatus(config) + return scm + .updateCommitStatus(config) .then(() => { assert.fail('This should not fail the test'); }) - .catch((error) => { + .catch(error => { assert.strictEqual(error.message, errMsg); }); }); @@ -837,78 +809,72 @@ describe('index', function () { config.context = 'findbugs'; config.description = '923 issues found. Previous count: 914 issues.'; - return scm.updateCommitStatus(config) - .then((result) => { - assert.deepEqual(result, data); + return scm.updateCommitStatus(config).then(result => { + assert.deepEqual(result, data); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '14052' } - ); - assert.calledWith(githubMock.repos.createCommitStatus, { - owner: 'screwdriver-cd', - repo: 'models', - sha: config.sha, - state: 'success', - description: '923 issues found. Previous count: 914 issues.', - context: 'Screwdriver/675/findbugs', - target_url: 'https://foo.bar' - }); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '14052' }); + assert.calledWith(githubMock.repos.createCommitStatus, { + owner: 'screwdriver-cd', + repo: 'models', + sha: config.sha, + state: 'success', + description: '923 issues found. Previous count: 914 issues.', + context: 'Screwdriver/675/findbugs', + target_url: 'https://foo.bar' }); + }); }); it('sets context for PR when jobName passed in', () => { config.jobName = 'PR-15:test'; - return scm.updateCommitStatus(config) - .then((result) => { - assert.deepEqual(result, data); + return scm.updateCommitStatus(config).then(result => { + assert.deepEqual(result, data); - assert.calledWith(githubMock.repos.createCommitStatus, { - owner: 'screwdriver-cd', - repo: 'models', - sha: config.sha, - state: 'success', - description: 'Everything looks good!', - context: 'Screwdriver/675/PR:test', - target_url: 'https://foo.bar' - }); + assert.calledWith(githubMock.repos.createCommitStatus, { + owner: 'screwdriver-cd', + repo: 'models', + sha: config.sha, + state: 'success', + description: 'Everything looks good!', + context: 'Screwdriver/675/PR:test', + target_url: 'https://foo.bar' }); + }); }); it('sets context for regular job when jobName passed in', () => { config.jobName = 'main'; - return scm.updateCommitStatus(config) - .then(() => { - assert.calledWith(githubMock.repos.createCommitStatus, { - owner: 'screwdriver-cd', - repo: 'models', - sha: config.sha, - state: 'success', - description: 'Everything looks good!', - context: 'Screwdriver/675/main', - target_url: 'https://foo.bar' - }); + return scm.updateCommitStatus(config).then(() => { + assert.calledWith(githubMock.repos.createCommitStatus, { + owner: 'screwdriver-cd', + repo: 'models', + sha: config.sha, + state: 'success', + description: 'Everything looks good!', + context: 'Screwdriver/675/main', + target_url: 'https://foo.bar' }); + }); }); it('promises to update commit status on failure', () => { config.buildStatus = 'FAILURE'; - return scm.updateCommitStatus(config) - .then((result) => { - assert.deepEqual(result, data); + return scm.updateCommitStatus(config).then(result => { + assert.deepEqual(result, data); - assert.calledWith(githubMock.repos.createCommitStatus, { - owner: 'screwdriver-cd', - repo: 'models', - sha: config.sha, - state: 'failure', - description: 'Did not work as expected.', - context: 'Screwdriver/675/main', - target_url: 'https://foo.bar' - }); + assert.calledWith(githubMock.repos.createCommitStatus, { + owner: 'screwdriver-cd', + repo: 'models', + sha: config.sha, + state: 'failure', + description: 'Did not work as expected.', + context: 'Screwdriver/675/main', + target_url: 'https://foo.bar' }); + }); }); it('catches and discards Github errors when it has a 422 error code', () => { @@ -931,8 +897,9 @@ describe('index', function () { config.buildStatus = 'FAILURE'; - return scm.updateCommitStatus(config) - .then((result) => { + return scm + .updateCommitStatus(config) + .then(result => { assert.deepEqual(result, undefined); assert.calledWith(githubMock.repos.createCommitStatus, { owner: 'screwdriver-cd', @@ -956,11 +923,12 @@ describe('index', function () { githubMock.repos.createCommitStatus.rejects(err); - return scm.updateCommitStatus(config) + return scm + .updateCommitStatus(config) .then(() => { assert.fail('This should not fail the test'); }) - .catch((error) => { + .catch(error => { assert.deepEqual(error, err); assert.calledWith(githubMock.repos.createCommitStatus, { @@ -988,23 +956,24 @@ describe('index', function () { jobName: 'main' }; - githubMock.request.resolves({ data: { - full_name: 'screwdriver-cd/models' - } }); + githubMock.request.resolves({ + data: { + full_name: 'screwdriver-cd/models' + } + }); githubMock.repos.createCommitStatus.resolves({ data: {} }); - return scm.updateCommitStatus(config) - .then(() => { - // Because averageTime isn't deterministic on how long it will take, - // will need to check each value separately. - const stats = scm.stats(); + return scm.updateCommitStatus(config).then(() => { + // Because averageTime isn't deterministic on how long it will take, + // will need to check each value separately. + const stats = scm.stats(); - assert.strictEqual(stats['github:github.com'].requests.total, 2); - assert.strictEqual(stats['github:github.com'].requests.timeouts, 0); - assert.strictEqual(stats['github:github.com'].requests.success, 2); - assert.strictEqual(stats['github:github.com'].requests.failure, 0); - assert.strictEqual(stats['github:github.com'].breaker.isClosed, true); - }); + assert.strictEqual(stats['github:github.com'].requests.total, 2); + assert.strictEqual(stats['github:github.com'].requests.timeouts, 0); + assert.strictEqual(stats['github:github.com'].requests.success, 2); + assert.strictEqual(stats['github:github.com'].requests.failure, 0); + assert.strictEqual(stats['github:github.com'].breaker.isClosed, true); + }); }); }); @@ -1056,30 +1025,30 @@ jobs: }; beforeEach(() => { - githubMock.request.resolves({ data: { - full_name: 'screwdriver-cd/models' - } }); + githubMock.request.resolves({ + data: { + full_name: 'screwdriver-cd/models' + } + }); }); it('promises to get content when a ref is passed', () => { githubMock.repos.getContent.resolves({ data: returnData }); - return scm.getFile(config) - .then((data) => { - assert.deepEqual(data, expectedYaml); + return scm.getFile(config).then(data => { + assert.deepEqual(data, expectedYaml); - assert.calledWith(githubMock.repos.getContent, { - owner: 'screwdriver-cd', - repo: 'models', - path: config.path, - ref: config.ref - }); + assert.calledWith(githubMock.repos.getContent, { + owner: 'screwdriver-cd', + repo: 'models', + path: config.path, + ref: config.ref }); + }); }); - it('promises to get content without querying github' + - 'when a ref and scmRepo is passed', () => { - const configWithScmRepo = Object.assign({}, config); + it('promises to get content without querying github when a ref and scmRepo is passed', () => { + const configWithScmRepo = { ...config }; githubMock.repos.getContent.resolves({ data: returnData }); configWithScmRepo.scmRepo = { @@ -1088,44 +1057,43 @@ jobs: name: 'screwdriver-cd/models' }; - return scm.getFile(configWithScmRepo) - .then((data) => { - assert.deepEqual(data, expectedYaml); + return scm.getFile(configWithScmRepo).then(data => { + assert.deepEqual(data, expectedYaml); - assert.calledWith(githubMock.repos.getContent, { - owner: 'screwdriver-cd', - repo: 'models', - path: config.path, - ref: config.ref - }); - assert.notCalled(githubMock.request); + assert.calledWith(githubMock.repos.getContent, { + owner: 'screwdriver-cd', + repo: 'models', + path: config.path, + ref: config.ref }); + assert.notCalled(githubMock.request); + }); }); it('promises to get content when a ref is not passed', () => { githubMock.repos.getContent.resolves({ data: returnData }); - return scm.getFile(configNoRef) - .then((data) => { - assert.deepEqual(data, expectedYaml); - assert.calledWith(githubMock.repos.getContent, { - owner: 'screwdriver-cd', - repo: 'models', - path: configNoRef.path, - ref: 'master' - }); + return scm.getFile(configNoRef).then(data => { + assert.deepEqual(data, expectedYaml); + assert.calledWith(githubMock.repos.getContent, { + owner: 'screwdriver-cd', + repo: 'models', + path: configNoRef.path, + ref: 'master' }); + }); }); it('promises to get content when rootDir exists', () => { githubMock.repos.getContent.resolves({ data: returnData }); - return scm.getFile({ - scmUri: 'github.com:146:master:src/app/component', - path: 'screwdriver.yaml', - token: 'somerandomtoken' - }) - .then((data) => { + return scm + .getFile({ + scmUri: 'github.com:146:master:src/app/component', + path: 'screwdriver.yaml', + token: 'somerandomtoken' + }) + .then(data => { assert.deepEqual(data, expectedYaml); assert.calledWith(githubMock.repos.getContent, { owner: 'screwdriver-cd', @@ -1143,17 +1111,16 @@ jobs: githubMock.repos.getContent.rejects(err); - return scm.getFile(config) - .then((data) => { - assert.deepEqual(data, ''); + return scm.getFile(config).then(data => { + assert.deepEqual(data, ''); - assert.calledWith(githubMock.repos.getContent, { - owner: 'screwdriver-cd', - repo: 'models', - path: config.path, - ref: config.ref - }); + assert.calledWith(githubMock.repos.getContent, { + owner: 'screwdriver-cd', + repo: 'models', + path: config.path, + ref: config.ref }); + }); }); it('returns error when path is not a file', () => { @@ -1161,10 +1128,11 @@ jobs: githubMock.repos.getContent.resolves({ data: returnInvalidData }); - return scm.getFile(config) - .then(() => { + return scm.getFile(config).then( + () => { assert.fail('This should not fail the test'); - }, (err) => { + }, + err => { assert.strictEqual(err.message, expectedErrorMessage); assert.calledWith(githubMock.repos.getContent, { @@ -1173,7 +1141,8 @@ jobs: path: config.path, ref: config.ref }); - }); + } + ); }); it('returns an error when github command fails', () => { @@ -1183,11 +1152,12 @@ jobs: githubMock.repos.getContent.rejects(err); - return scm.getFile(config) + return scm + .getFile(config) .then(() => { assert.fail('This should not fail the test'); }) - .catch((error) => { + .catch(error => { assert.calledWith(githubMock.repos.getContent, { owner: 'screwdriver-cd', repo: 'models', @@ -1208,17 +1178,14 @@ jobs: it('returns changed files for a push event payload', () => { type = 'repo'; - return scm.getChangedFiles({ - type, - token, - payload: testPayloadPush - }) - .then((result) => { - assert.deepEqual(result, [ - 'README.md', - 'package.json', - 'screwdriver.yaml' - ]); + return scm + .getChangedFiles({ + type, + token, + payload: testPayloadPush + }) + .then(result => { + assert.deepEqual(result, ['README.md', 'package.json', 'screwdriver.yaml']); }); }); @@ -1227,26 +1194,29 @@ jobs: githubMock.request.resolves({ data: { full_name: 'iAm/theCaptain' } }); githubMock.pulls.get.resolves({ data: testPrGet }); - return scm.getChangedFiles({ - type: 'pr', - token, - payload: null, - scmUri: 'github.com:28476:master', - prNum: 1 - }).then((result) => { - assert.deepEqual(result, ['README.md', 'folder/folder2/hi']); - }); + return scm + .getChangedFiles({ + type: 'pr', + token, + payload: null, + scmUri: 'github.com:28476:master', + prNum: 1 + }) + .then(result => { + assert.deepEqual(result, ['README.md', 'folder/folder2/hi']); + }); }); it('returns empty array for an event payload that is not type repo or pr', () => { type = 'ping'; - return scm.getChangedFiles({ - type, - token, - payload: testPayloadOpen - }) - .then((result) => { + return scm + .getChangedFiles({ + type, + token, + payload: testPayloadOpen + }) + .then(result => { assert.deepEqual(result, []); }); }); @@ -1254,12 +1224,13 @@ jobs: it('returns empty array for an event payload which does not have changed files', () => { type = 'repo'; - return scm.getChangedFiles({ - type, - token, - payload: testPayloadPushBadHead - }) - .then((result) => { + return scm + .getChangedFiles({ + type, + token, + payload: testPayloadPushBadHead + }) + .then(result => { assert.deepEqual(result, []); }); }); @@ -1275,29 +1246,34 @@ jobs: githubMock.request.resolves({ data: testResponse }); githubMock.pulls.get.resolves({ data: testPrGet }); - return scm.waitPrMergeability({ - token, - scmUri: 'github.com:28476:master', - prNum: 1 - }, 0).then((result) => { - assert.deepEqual(result, { - success: true, - pullRequestInfo: { - baseBranch: 'master', - createTime: '2011-01-26T19:01:12Z', - mergeable: true, - name: 'PR-1', - prBranchName: 'new-topic', - prSource: 'branch', - ref: 'pull/1/merge', - sha: '6dcb09b5b57875f334f61aebed695e2e4193db5e', - title: 'new-feature', - url: 'https://github.com/octocat/Hello-World/pull/1', - userProfile: 'https://github.com/octocat', - username: 'octocat' - } + return scm + .waitPrMergeability( + { + token, + scmUri: 'github.com:28476:master', + prNum: 1 + }, + 0 + ) + .then(result => { + assert.deepEqual(result, { + success: true, + pullRequestInfo: { + baseBranch: 'master', + createTime: '2011-01-26T19:01:12Z', + mergeable: true, + name: 'PR-1', + prBranchName: 'new-topic', + prSource: 'branch', + ref: 'pull/1/merge', + sha: '6dcb09b5b57875f334f61aebed695e2e4193db5e', + title: 'new-feature', + url: 'https://github.com/octocat/Hello-World/pull/1', + userProfile: 'https://github.com/octocat', + username: 'octocat' + } + }); }); - }); }); it('returns mergeable when polling succeded on second time', () => { @@ -1305,58 +1281,68 @@ jobs: githubMock.pulls.get.onFirstCall().resolves({ data: testPrGetNullMergeable }); githubMock.pulls.get.resolves({ data: testPrGet }); - return scm.waitPrMergeability({ - token, - scmUri: 'github.com:28476:master', - prNum: 1 - }, 0).then((result) => { - assert.deepEqual(result, { - success: true, - pullRequestInfo: { - baseBranch: 'master', - createTime: '2011-01-26T19:01:12Z', - mergeable: true, - name: 'PR-1', - prBranchName: 'new-topic', - prSource: 'branch', - ref: 'pull/1/merge', - sha: '6dcb09b5b57875f334f61aebed695e2e4193db5e', - title: 'new-feature', - url: 'https://github.com/octocat/Hello-World/pull/1', - userProfile: 'https://github.com/octocat', - username: 'octocat' - } + return scm + .waitPrMergeability( + { + token, + scmUri: 'github.com:28476:master', + prNum: 1 + }, + 0 + ) + .then(result => { + assert.deepEqual(result, { + success: true, + pullRequestInfo: { + baseBranch: 'master', + createTime: '2011-01-26T19:01:12Z', + mergeable: true, + name: 'PR-1', + prBranchName: 'new-topic', + prSource: 'branch', + ref: 'pull/1/merge', + sha: '6dcb09b5b57875f334f61aebed695e2e4193db5e', + title: 'new-feature', + url: 'https://github.com/octocat/Hello-World/pull/1', + userProfile: 'https://github.com/octocat', + username: 'octocat' + } + }); }); - }); }); it('returns undefined when polling never succeeded', () => { githubMock.request.resolves({ data: testResponse }); githubMock.pulls.get.resolves({ data: testPrGetNullMergeable }); - return scm.waitPrMergeability({ - token, - scmUri: 'github.com:28476:master', - prNum: 1 - }, 0).then((result) => { - assert.deepEqual(result, { - success: false, - pullRequestInfo: { - baseBranch: 'master', - createTime: '2011-01-26T19:01:12Z', - mergeable: null, - name: 'PR-1', - prBranchName: 'new-topic', - prSource: 'branch', - ref: 'pull/1/merge', - sha: '6dcb09b5b57875f334f61aebed695e2e4193db5e', - title: 'new-feature', - url: 'https://github.com/octocat/Hello-World/pull/1', - userProfile: 'https://github.com/octocat', - username: 'octocat' - } + return scm + .waitPrMergeability( + { + token, + scmUri: 'github.com:28476:master', + prNum: 1 + }, + 0 + ) + .then(result => { + assert.deepEqual(result, { + success: false, + pullRequestInfo: { + baseBranch: 'master', + createTime: '2011-01-26T19:01:12Z', + mergeable: null, + name: 'PR-1', + prBranchName: 'new-topic', + prSource: 'branch', + ref: 'pull/1/merge', + sha: '6dcb09b5b57875f334f61aebed695e2e4193db5e', + title: 'new-feature', + url: 'https://github.com/octocat/Hello-World/pull/1', + userProfile: 'https://github.com/octocat', + username: 'octocat' + } + }); }); - }); }); }); @@ -1390,83 +1376,78 @@ jobs: it('parses a payload for a push event payload', () => { testHeaders['x-github-event'] = 'push'; - return scm.parseHook(testHeaders, testPayloadPush) - .then((result) => { - assert.deepEqual(result, { - action: 'push', - branch: 'master', - checkoutUrl: 'git@github.com:baxterthehacker/public-repo.git', - sha: '0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c', - type: 'repo', - username: 'baxterthehacker2', - commitAuthors: ['baxterthehacker'], - lastCommitMessage: 'lastcommitmessage', - hookId: '3c77bf80-9a2f-11e6-80d6-72f7fe03ea29', - scmContext: 'github:github.com', - ref: 'refs/heads/master' - }); + return scm.parseHook(testHeaders, testPayloadPush).then(result => { + assert.deepEqual(result, { + action: 'push', + branch: 'master', + checkoutUrl: 'git@github.com:baxterthehacker/public-repo.git', + sha: '0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c', + type: 'repo', + username: 'baxterthehacker2', + commitAuthors: ['baxterthehacker'], + lastCommitMessage: 'lastcommitmessage', + hookId: '3c77bf80-9a2f-11e6-80d6-72f7fe03ea29', + scmContext: 'github:github.com', + ref: 'refs/heads/master' }); + }); }); it('parses a payload for a delete event payload', () => { testHeaders['x-github-event'] = 'push'; testHeaders['x-hub-signature'] = 'sha1=f2589b49939e662188aed20967779a3e500149af'; - return scm.parseHook(testHeaders, testPayloadPushDeleted) - .then((result) => { - assert.equal(result, null); - }); + return scm.parseHook(testHeaders, testPayloadPushDeleted).then(result => { + assert.equal(result, null); + }); }); it('parses a payload for a release event payload', () => { testHeaders['x-github-event'] = 'release'; testHeaders['x-hub-signature'] = 'sha1=bb5a13e806648dcd8910a4fdbe07f7ed943cb45a'; - return scm.parseHook(testHeaders, testPayloadRelease) - .then((result) => { - assert.deepEqual(result, { - action: 'release', - branch: 'master', - checkoutUrl: 'git@github.com:Codertocat/Hello-World.git', - type: 'repo', - username: 'Codertocat', - hookId: '3c77bf80-9a2f-11e6-80d6-72f7fe03ea29', - scmContext: 'github:github.com', - ref: '0.0.1', - releaseId: '11248810', - releaseName: '', - releaseAuthor: 'Codertocat' - }); + return scm.parseHook(testHeaders, testPayloadRelease).then(result => { + assert.deepEqual(result, { + action: 'release', + branch: 'master', + checkoutUrl: 'git@github.com:Codertocat/Hello-World.git', + type: 'repo', + username: 'Codertocat', + hookId: '3c77bf80-9a2f-11e6-80d6-72f7fe03ea29', + scmContext: 'github:github.com', + ref: '0.0.1', + releaseId: '11248810', + releaseName: '', + releaseAuthor: 'Codertocat' }); + }); }); it('resolves null for a release event payload with an unsupported action', () => { testHeaders['x-github-event'] = 'release'; testHeaders['x-hub-signature'] = 'sha1=0ecd27db793b3a4129705c5314d8511c5d90e33e'; - return scm.parseHook(testHeaders, testPayloadReleaseBadAction) - .then((result) => { - assert.isNull(result); - }); + return scm.parseHook(testHeaders, testPayloadReleaseBadAction).then(result => { + assert.isNull(result); + }); }); it('parses a payload for a tag event payload', () => { testHeaders['x-github-event'] = 'create'; testHeaders['x-hub-signature'] = 'sha1=bd5a3a851e9333d871daeaa61b03a742b700addf'; - return scm.parseHook(testHeaders, testPayloadTag) - .then((result) => { - assert.deepEqual(result, { - action: 'tag', - branch: 'master', - checkoutUrl: 'git@github.com:Codertocat/Hello-World.git', - type: 'repo', - username: 'Codertocat', - hookId: '3c77bf80-9a2f-11e6-80d6-72f7fe03ea29', - scmContext: 'github:github.com', - ref: 'simple-tag' - }); + return scm.parseHook(testHeaders, testPayloadTag).then(result => { + assert.deepEqual(result, { + action: 'tag', + branch: 'master', + checkoutUrl: 'git@github.com:Codertocat/Hello-World.git', + type: 'repo', + username: 'Codertocat', + hookId: '3c77bf80-9a2f-11e6-80d6-72f7fe03ea29', + scmContext: 'github:github.com', + ref: 'simple-tag' }); + }); }); it('resolves null for a create branch event payload', () => { @@ -1474,99 +1455,91 @@ jobs: testHeaders['x-hub-signature'] = 'sha1=37f2e1af8e0962fa9efc3192a6a22ba08f07c2b5'; testPayloadTag.ref_type = 'branch'; - return scm.parseHook(testHeaders, testPayloadTag) - .then((result) => { - assert.isNull(result); - }); + return scm.parseHook(testHeaders, testPayloadTag).then(result => { + assert.isNull(result); + }); }); it('resolves null for a push repository tag event payload', () => { testHeaders['x-github-event'] = 'push'; testHeaders['x-hub-signature'] = 'sha1=c3d5ae557c6f37a24d5887f1d642a6674d8f11fb'; - return scm.parseHook(testHeaders, testPayloadPushTag) - .then((result) => { - assert.isNull(result); - }); + return scm.parseHook(testHeaders, testPayloadPushTag).then(result => { + assert.isNull(result); + }); }); it('resolves null for a pull request payload with an unsupported action', () => { testHeaders['x-hub-signature'] = 'sha1=4fe5c8f4a7e4b76a4bd46b4693e87dadf9bec110'; - return scm.parseHook(testHeaders, testPayloadBadAction) - .then((result) => { - assert.isNull(result); - }); + return scm.parseHook(testHeaders, testPayloadBadAction).then(result => { + assert.isNull(result); + }); }); it('parses a payload for a pull request event payload', () => { testHeaders['x-hub-signature'] = 'sha1=41d0508ffed278fde2fd5a84fd75c109a7039f90'; - return scm.parseHook(testHeaders, testPayloadOpen) - .then((result) => { - commonPullRequestParse.action = 'opened'; - assert.deepEqual(result, commonPullRequestParse); - }); + return scm.parseHook(testHeaders, testPayloadOpen).then(result => { + commonPullRequestParse.action = 'opened'; + assert.deepEqual(result, commonPullRequestParse); + }); }); it('parses a payload for a forked pull request event payload', () => { testHeaders['x-hub-signature'] = 'sha1=3b5d95f319ab1cdc8b5753495df12ce74b8075d6'; - return scm.parseHook(testHeaders, testPayloadOpenFork) - .then((result) => { - commonPullRequestParse.prSource = 'fork'; - commonPullRequestParse.action = 'opened'; - assert.deepEqual(result, commonPullRequestParse); - }); + return scm.parseHook(testHeaders, testPayloadOpenFork).then(result => { + commonPullRequestParse.prSource = 'fork'; + commonPullRequestParse.action = 'opened'; + assert.deepEqual(result, commonPullRequestParse); + }); }); it('parses a payload for a pull request being closed', () => { testHeaders['x-hub-signature'] = 'sha1=2d51c3a4eaab65832c119ec3db951de54ec38736'; - return scm.parseHook(testHeaders, testPayloadClose) - .then((result) => { - commonPullRequestParse.action = 'closed'; - assert.deepEqual(result, commonPullRequestParse); - }); + return scm.parseHook(testHeaders, testPayloadClose).then(result => { + commonPullRequestParse.action = 'closed'; + assert.deepEqual(result, commonPullRequestParse); + }); }); it('parses a payload for a pull request being synchronized', () => { testHeaders['x-hub-signature'] = 'sha1=583afb7551c9bc412f7496bc840b027931e97846'; - return scm.parseHook(testHeaders, testPayloadSync) - .then((result) => { - commonPullRequestParse.action = 'synchronized'; - assert.deepEqual(result, commonPullRequestParse); - }); + return scm.parseHook(testHeaders, testPayloadSync).then(result => { + commonPullRequestParse.action = 'synchronized'; + assert.deepEqual(result, commonPullRequestParse); + }); }); it('resolves null when parsing an unsupported event payload', () => { testHeaders['x-github-event'] = 'ping'; testHeaders['x-hub-signature'] = 'sha1=1b51a3f9f548fdacab52c0e83f9a63f8cbb4b591'; - return scm.parseHook(testHeaders, testPayloadPing) - .then((result) => { - assert.isNull(result); - }); + return scm.parseHook(testHeaders, testPayloadPing).then(result => { + assert.isNull(result); + }); }); it('rejects when ssh host is not valid', () => { testHeaders['x-hub-signature'] = 'sha1=1b51a3f9f548fdacab52c0e83f9a63f8cbb4b591'; - return scm.parseHook(testHeaders, testPayloadPingBadSshHost) - .then((result) => { - assert.isNull(result); - }); + return scm.parseHook(testHeaders, testPayloadPingBadSshHost).then(result => { + assert.isNull(result); + }); }); it('rejects when signature is not valid', () => { testHeaders['x-hub-signature'] = 'sha1=25cebb8fff2c10ec8d0712e3ab0163218d375492'; - return scm.parseHook(testHeaders, testPayloadPing) + return scm + .parseHook(testHeaders, testPayloadPing) .then(() => { assert.fail('This should not fail the tests'); }) - .catch((err) => { + .catch(err => { assert.equal(err.message, 'Invalid x-hub-signature'); }); }); @@ -1594,49 +1567,64 @@ jobs: it('parses a complete ssh url', () => { githubMock.repos.get.resolves({ data: repoData }); - return scm.parseUrl({ - checkoutUrl, - token - }).then((result) => { - assert.strictEqual(result, 'github.com:8675309:boat'); + return scm + .parseUrl({ + checkoutUrl, + token + }) + .then(result => { + assert.strictEqual(result, 'github.com:8675309:boat'); - assert.calledWith(githubMock.repos.get, sinon.match(repoInfo)); - assert.calledWith(githubMock.repos.get, sinon.match({ - branch: 'boat' - })); - }); + assert.calledWith(githubMock.repos.get, sinon.match(repoInfo)); + assert.calledWith( + githubMock.repos.get, + sinon.match({ + branch: 'boat' + }) + ); + }); }); it('parses a ssh url with rootDir passed in', () => { githubMock.repos.get.resolves({ data: repoData }); - return scm.parseUrl({ - checkoutUrl, - token, - rootDir: 'src/app/component' - }).then((result) => { - assert.strictEqual(result, 'github.com:8675309:boat:src/app/component'); - assert.calledWith(githubMock.repos.get, sinon.match(repoInfo)); - assert.calledWith(githubMock.repos.get, sinon.match({ - branch: 'boat' - })); - }); + return scm + .parseUrl({ + checkoutUrl, + token, + rootDir: 'src/app/component' + }) + .then(result => { + assert.strictEqual(result, 'github.com:8675309:boat:src/app/component'); + assert.calledWith(githubMock.repos.get, sinon.match(repoInfo)); + assert.calledWith( + githubMock.repos.get, + sinon.match({ + branch: 'boat' + }) + ); + }); }); it('parses a complete ssh url with rootDir', () => { githubMock.repos.get.resolves({ data: repoData }); - return scm.parseUrl({ - checkoutUrl: 'git@github.com:iAm/theCaptain.git#boat:path/to/water', - token, - rootDir: '' - }).then((result) => { - assert.strictEqual(result, 'github.com:8675309:boat:path/to/water'); - assert.calledWith(githubMock.repos.get, sinon.match(repoInfo)); - assert.calledWith(githubMock.repos.get, sinon.match({ - rootDir: 'path/to/water' - })); - }); + return scm + .parseUrl({ + checkoutUrl: 'git@github.com:iAm/theCaptain.git#boat:path/to/water', + token, + rootDir: '' + }) + .then(result => { + assert.strictEqual(result, 'github.com:8675309:boat:path/to/water'); + assert.calledWith(githubMock.repos.get, sinon.match(repoInfo)); + assert.calledWith( + githubMock.repos.get, + sinon.match({ + rootDir: 'path/to/water' + }) + ); + }); }); it('parses a ssh url, defaulting the branch to default branch', () => { @@ -1644,27 +1632,34 @@ jobs: repoInfo.branch = undefined; githubMock.repos.get.resolves({ data: repoData }); - return scm.parseUrl({ - checkoutUrl, - token - }).then((result) => { - assert.strictEqual(result, 'github.com:8675309:main'); - assert.calledWith(githubMock.repos.get, sinon.match(repoInfo)); - }); + return scm + .parseUrl({ + checkoutUrl, + token + }) + .then(result => { + assert.strictEqual(result, 'github.com:8675309:main'); + assert.calledWith(githubMock.repos.get, sinon.match(repoInfo)); + }); }); it('rejects when unable to match', () => { const invalidCheckoutUrl = 'invalidCheckoutUrl'; // eslint-disable-next-line no-underscore-dangle - return scm._parseUrl({ - checkoutUrl: invalidCheckoutUrl, - token - }).then(() => { - assert.fail('This should not fail the test'); - }, (err) => { - assert.match(err.message, /Invalid scmUrl/); - }); + return scm + ._parseUrl({ + checkoutUrl: invalidCheckoutUrl, + token + }) + .then( + () => { + assert.fail('This should not fail the test'); + }, + err => { + assert.match(err.message, /Invalid scmUrl/); + } + ); }); it('rejects when repo does not exist', () => { @@ -1674,34 +1669,46 @@ jobs: githubMock.repos.get.rejects(notFoundError); - return scm.parseUrl({ - checkoutUrl, - token - }).then(() => { - assert.fail('This should not fail the test'); - }, (err) => { - assert.match(err.message, 'Cannot find repository'); - }); + return scm + .parseUrl({ + checkoutUrl, + token + }) + .then( + () => { + assert.fail('This should not fail the test'); + }, + err => { + assert.match(err.message, 'Cannot find repository'); + } + ); }); it('rejects when failing to communicate with github', () => { - const expectedError = new Error('errorCommunicatingWithGithub'); + const expectedError = 'errorCommunicatingWithGithub'; githubMock.repos.get.rejects(expectedError); - return scm.parseUrl({ - checkoutUrl, - token - }).then(() => { - assert.fail('This should not fail the test'); - }, (err) => { - assert.deepEqual(err, expectedError); - - assert.calledWith(githubMock.repos.get, sinon.match(repoInfo)); - assert.calledWith(githubMock.repos.get, sinon.match({ - branch: 'boat' - })); - }); + return scm + .parseUrl({ + checkoutUrl, + token + }) + .then( + () => { + assert.fail('This should not fail the test'); + }, + err => { + assert.deepEqual(err.message, expectedError); + assert.calledWith(githubMock.repos.get, sinon.match(repoInfo)); + assert.calledWith( + githubMock.repos.get, + sinon.match({ + branch: 'boat' + }) + ); + } + ); }); it('rejects when passed checkoutUrl of another host', () => { @@ -1709,14 +1716,19 @@ jobs: checkoutUrl = 'git@github.screwdriver.cd:iAm/theCaptain.git#boat'; - return scm.parseUrl({ - checkoutUrl, - token - }).then(() => { - assert.fail('This should not fail the test'); - }, (err) => { - assert.match(err.message, message); - }); + return scm + .parseUrl({ + checkoutUrl, + token + }) + .then( + () => { + assert.fail('This should not fail the test'); + }, + err => { + assert.match(err.message, message); + } + ); }); }); @@ -1724,55 +1736,63 @@ jobs: const username = 'notmrkent'; it('decorates a github user', () => { - githubMock.users.getByUsername.resolves({ data: { - login: username, - id: 2042, - avatar_url: 'https://avatars.githubusercontent.com/u/2042?v=3', - html_url: `https://github.com/${username}`, - name: 'Klark Cent' - } }); - - return scm.decorateAuthor({ - token: 'tokenfordecorateauthor', - username - }).then((data) => { - assert.deepEqual(data, { - avatar: 'https://avatars.githubusercontent.com/u/2042?v=3', - name: 'Klark Cent', - url: `https://github.com/${username}`, - username - }); + githubMock.users.getByUsername.resolves({ + data: { + login: username, + id: 2042, + avatar_url: 'https://avatars.githubusercontent.com/u/2042?v=3', + html_url: `https://github.com/${username}`, + name: 'Klark Cent' + } + }); - assert.calledWith(githubMock.users.getByUsername, { + return scm + .decorateAuthor({ + token: 'tokenfordecorateauthor', username + }) + .then(data => { + assert.deepEqual(data, { + avatar: 'https://avatars.githubusercontent.com/u/2042?v=3', + name: 'Klark Cent', + url: `https://github.com/${username}`, + username + }); + + assert.calledWith(githubMock.users.getByUsername, { + username + }); }); - }); }); it('defaults to username when display name does not exist', () => { - githubMock.users.getByUsername.resolves({ data: { - login: username, - id: 2042, - avatar_url: 'https://avatars.githubusercontent.com/u/2042?v=3', - html_url: `https://github.com/${username}`, - name: null - } }); - - return scm.decorateAuthor({ - token: 'tokenfordecorateauthor', - username - }).then((data) => { - assert.deepEqual(data, { - avatar: 'https://avatars.githubusercontent.com/u/2042?v=3', - name: username, - url: `https://github.com/${username}`, - username - }); + githubMock.users.getByUsername.resolves({ + data: { + login: username, + id: 2042, + avatar_url: 'https://avatars.githubusercontent.com/u/2042?v=3', + html_url: `https://github.com/${username}`, + name: null + } + }); - assert.calledWith(githubMock.users.getByUsername, { + return scm + .decorateAuthor({ + token: 'tokenfordecorateauthor', username + }) + .then(data => { + assert.deepEqual(data, { + avatar: 'https://avatars.githubusercontent.com/u/2042?v=3', + name: username, + url: `https://github.com/${username}`, + username + }); + + assert.calledWith(githubMock.users.getByUsername, { + username + }); }); - }); }); it('rejects when failing to communicate with github', () => { @@ -1780,18 +1800,23 @@ jobs: githubMock.users.getByUsername.rejects(testError); - return scm.decorateAuthor({ - token: 'randomtoken', - username - }).then(() => { - assert.fail('This should not fail the test'); - }, (err) => { - assert.deepEqual(err, testError); - - assert.calledWith(githubMock.users.getByUsername, { + return scm + .decorateAuthor({ + token: 'randomtoken', username - }); - }); + }) + .then( + () => { + assert.fail('This should not fail the test'); + }, + err => { + assert.deepEqual(err, testError); + + assert.calledWith(githubMock.users.getByUsername, { + username + }); + } + ); }); }); @@ -1804,108 +1829,116 @@ jobs: const username = 'notbrucewayne'; beforeEach(() => { - githubMock.users.getByUsername.resolves({ data: { - login: username, - id: 1234567, - avatar_url: 'https://avatars.githubusercontent.com/u/1234567?v=3', - html_url: `https://internal-ghe.mycompany.com/${username}`, - name: 'Batman Wayne' - } }); + githubMock.users.getByUsername.resolves({ + data: { + login: username, + id: 1234567, + avatar_url: 'https://avatars.githubusercontent.com/u/1234567?v=3', + html_url: `https://internal-ghe.mycompany.com/${username}`, + name: 'Batman Wayne' + } + }); - githubMock.request.resolves({ data: { - full_name: `${repoOwner}/${repoName}` - } }); + githubMock.request.resolves({ + data: { + full_name: `${repoOwner}/${repoName}` + } + }); }); it('decorates a commit', () => { - githubMock.repos.getCommit.resolves({ data: { - commit: { - message: 'some commit message that is here' - }, - author: { - login: username - }, - html_url: 'https://link.to/commitDiff' - } }); - - return scm.decorateCommit({ - scmUri, - sha, - token: 'tokenfordecoratecommit' - }).then((data) => { - assert.deepEqual(data, { - author: { - avatar: 'https://avatars.githubusercontent.com/u/1234567?v=3', - name: 'Batman Wayne', - url: 'https://internal-ghe.mycompany.com/notbrucewayne', - username: 'notbrucewayne' + githubMock.repos.getCommit.resolves({ + data: { + commit: { + message: 'some commit message that is here' }, - committer: { - avatar: 'https://cd.screwdriver.cd/assets/unknown_user.png', - name: 'n/a', - username: 'n/a', - url: 'https://cd.screwdriver.cd/' + author: { + login: username }, - message: 'some commit message that is here', - url: 'https://link.to/commitDiff' - }); + html_url: 'https://link.to/commitDiff' + } + }); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: scmId } - ); - assert.calledWith(githubMock.repos.getCommit, { - owner: repoOwner, - repo: repoName, - ref: sha - }); - assert.calledWith(githubMock.users.getByUsername, { - username + return scm + .decorateCommit({ + scmUri, + sha, + token: 'tokenfordecoratecommit' + }) + .then(data => { + assert.deepEqual(data, { + author: { + avatar: 'https://avatars.githubusercontent.com/u/1234567?v=3', + name: 'Batman Wayne', + url: 'https://internal-ghe.mycompany.com/notbrucewayne', + username: 'notbrucewayne' + }, + committer: { + avatar: 'https://cd.screwdriver.cd/assets/unknown_user.png', + name: 'n/a', + username: 'n/a', + url: 'https://cd.screwdriver.cd/' + }, + message: 'some commit message that is here', + url: 'https://link.to/commitDiff' + }); + + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: scmId }); + assert.calledWith(githubMock.repos.getCommit, { + owner: repoOwner, + repo: repoName, + ref: sha + }); + assert.calledWith(githubMock.users.getByUsername, { + username + }); }); - }); }); it('defaults author data to empty if author is missing', () => { - githubMock.repos.getCommit.resolves({ data: { - commit: { - message: 'some commit message that is here' - }, - author: null, - html_url: 'https://link.to/commitDiff' - } }); + githubMock.repos.getCommit.resolves({ + data: { + commit: { + message: 'some commit message that is here' + }, + author: null, + html_url: 'https://link.to/commitDiff' + } + }); githubMock.users.getByUsername.resolves(); - return scm.decorateCommit({ - scmUri, - sha, - token: 'tokenfordecoratecommit' - }).then((data) => { - assert.deepEqual(data, { - author: { - avatar: 'https://cd.screwdriver.cd/assets/unknown_user.png', - name: 'n/a', - url: 'https://cd.screwdriver.cd/', - username: 'n/a' - }, - committer: { - avatar: 'https://cd.screwdriver.cd/assets/unknown_user.png', - name: 'n/a', - url: 'https://cd.screwdriver.cd/', - username: 'n/a' - }, - message: 'some commit message that is here', - url: 'https://link.to/commitDiff' - }); + return scm + .decorateCommit({ + scmUri, + sha, + token: 'tokenfordecoratecommit' + }) + .then(data => { + assert.deepEqual(data, { + author: { + avatar: 'https://cd.screwdriver.cd/assets/unknown_user.png', + name: 'n/a', + url: 'https://cd.screwdriver.cd/', + username: 'n/a' + }, + committer: { + avatar: 'https://cd.screwdriver.cd/assets/unknown_user.png', + name: 'n/a', + url: 'https://cd.screwdriver.cd/', + username: 'n/a' + }, + message: 'some commit message that is here', + url: 'https://link.to/commitDiff' + }); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: scmId } - ); - assert.calledWith(githubMock.repos.getCommit, { - owner: repoOwner, - repo: repoName, - ref: sha + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: scmId }); + assert.calledWith(githubMock.repos.getCommit, { + owner: repoOwner, + repo: repoName, + ref: sha + }); + assert.callCount(githubMock.users.getByUsername, 0); }); - assert.callCount(githubMock.users.getByUsername, 0); - }); }); it('rejects when failing to communicate with github', () => { @@ -1913,21 +1946,26 @@ jobs: githubMock.repos.getCommit.rejects(testError); - return scm.decorateCommit({ - scmUri, - sha, - token: 'tokenforfailingtodecorate' - }).then(() => { - assert.fail('This should not fail the test'); - }, (err) => { - assert.deepEqual(err, testError); - - assert.calledWith(githubMock.repos.getCommit, { - owner: 'banana', - repo: 'peel', - ref: sha - }); - }); + return scm + .decorateCommit({ + scmUri, + sha, + token: 'tokenforfailingtodecorate' + }) + .then( + () => { + assert.fail('This should not fail the test'); + }, + err => { + assert.deepEqual(err, testError); + + assert.calledWith(githubMock.repos.getCommit, { + owner: 'banana', + repo: 'peel', + ref: sha + }); + } + ); }); }); @@ -1935,51 +1973,55 @@ jobs: it('decorates a scm uri', () => { const scmUri = 'github.com:102498:boat'; - githubMock.request.resolves({ data: { - full_name: 'iAm/theCaptain', - private: false - } }); - - return scm.decorateUrl({ - scmUri, - token: 'mytokenfortesting' - }).then((data) => { - assert.deepEqual(data, { - branch: 'boat', - name: 'iAm/theCaptain', - url: 'https://github.com/iAm/theCaptain/tree/boat', - rootDir: '', + githubMock.request.resolves({ + data: { + full_name: 'iAm/theCaptain', private: false - }); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '102498' } - ); + } }); + + return scm + .decorateUrl({ + scmUri, + token: 'mytokenfortesting' + }) + .then(data => { + assert.deepEqual(data, { + branch: 'boat', + name: 'iAm/theCaptain', + url: 'https://github.com/iAm/theCaptain/tree/boat', + rootDir: '', + private: false + }); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '102498' }); + }); }); it('decorates a scm uri with rootDir', () => { const scmUri = 'github.com:102498:boat:src/app/component'; - githubMock.request.resolves({ data: { - full_name: 'iAm/theCaptain', - private: false - } }); - - return scm.decorateUrl({ - scmUri, - token: 'mytokenfortesting' - }).then((data) => { - assert.deepEqual(data, { - branch: 'boat', - name: 'iAm/theCaptain', - url: 'https://github.com/iAm/theCaptain/tree/boat/src/app/component', - rootDir: 'src/app/component', + githubMock.request.resolves({ + data: { + full_name: 'iAm/theCaptain', private: false - }); - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '102498' } - ); + } }); + + return scm + .decorateUrl({ + scmUri, + token: 'mytokenfortesting' + }) + .then(data => { + assert.deepEqual(data, { + branch: 'boat', + name: 'iAm/theCaptain', + url: 'https://github.com/iAm/theCaptain/tree/boat/src/app/component', + rootDir: 'src/app/component', + private: false + }); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '102498' }); + }); }); it('decorates a scm uri without querying github when scmRepo is passed', () => { @@ -1990,21 +2032,23 @@ jobs: name: 'iAm/theCaptain' }; - return scm.decorateUrl({ - scmUri, - scmRepo, - token: 'mytokenfortesting' - }).then((data) => { - assert.deepEqual(data, { - branch: 'boat', - name: 'iAm/theCaptain', - url: 'https://github.com/iAm/theCaptain/tree/boat', - rootDir: '', - private: false - }); + return scm + .decorateUrl({ + scmUri, + scmRepo, + token: 'mytokenfortesting' + }) + .then(data => { + assert.deepEqual(data, { + branch: 'boat', + name: 'iAm/theCaptain', + url: 'https://github.com/iAm/theCaptain/tree/boat', + rootDir: '', + private: false + }); - assert.notCalled(githubMock.request); - }); + assert.notCalled(githubMock.request); + }); }); it('rejects when github lookup fails', () => { @@ -2013,24 +2057,27 @@ jobs: githubMock.request.rejects(testError); - return scm.decorateUrl({ - scmUri, - token: 'mytokenfortesting' - }).then(() => { - assert.fail('This should not fail the test'); - }, (err) => { - assert.deepEqual(err, testError); - - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '102498' } + return scm + .decorateUrl({ + scmUri, + token: 'mytokenfortesting' + }) + .then( + () => { + assert.fail('This should not fail the test'); + }, + err => { + assert.deepEqual(err, testError); + + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '102498' }); + } ); - }); }); }); describe('generateDeployKey', () => { it('returns a public and private key pair object', () => - scm.generateDeployKey().then((keys) => { + scm.generateDeployKey().then(keys => { assert.isObject(keys); assert.property(keys, 'pubKey'); assert.property(keys, 'key'); @@ -2058,7 +2105,7 @@ jobs: githubMock.repos.createDeployKey.resolves({ data: pubKey }); generateDeployKeyStub.returns(Promise.resolve({ pubKey, key: privKey })); - return scm.addDeployKey(addDepKeyConfig).then((privateKey) => { + return scm.addDeployKey(addDepKeyConfig).then(privateKey => { assert.isString(privateKey); assert.deepEqual(privateKey, privKey); }); @@ -2066,8 +2113,8 @@ jobs: }); describe('getBellConfiguration', () => { - it('returns a default configuration', () => ( - scm.getBellConfiguration().then((config) => { + it('returns a default configuration', () => + scm.getBellConfiguration().then(config => { assert.deepEqual(config, { 'github:github.com': { clientId: 'abcdefg', @@ -2076,15 +2123,10 @@ jobs: isSecure: false, provider: 'github', cookie: 'github-github.com', - scope: [ - 'admin:repo_hook', - 'read:org', - 'repo:status' - ] + scope: ['admin:repo_hook', 'read:org', 'repo:status'] } }); - }) - )); + })); it('returns configuration for github enterprise', () => { scm = new GithubScm({ @@ -2094,7 +2136,7 @@ jobs: secret: 'somesecret' }); - return scm.getBellConfiguration().then((config) => { + return scm.getBellConfiguration().then(config => { assert.deepEqual(config, { 'github:github.screwdriver.cd': { clientId: 'abcdefg', @@ -2106,11 +2148,7 @@ jobs: isSecure: false, provider: 'github', cookie: 'github-github.screwdriver.cd', - scope: [ - 'admin:repo_hook', - 'read:org', - 'repo:status' - ] + scope: ['admin:repo_hook', 'read:org', 'repo:status'] } }); }); @@ -2125,7 +2163,7 @@ jobs: privateRepo: true }); - return scm.getBellConfiguration().then((config) => { + return scm.getBellConfiguration().then(config => { assert.deepEqual(config, { 'github:github.screwdriver.cd': { clientId: 'abcdefg', @@ -2137,12 +2175,7 @@ jobs: isSecure: false, provider: 'github', cookie: 'github-github.screwdriver.cd', - scope: [ - 'admin:repo_hook', - 'read:org', - 'repo:status', - 'repo' - ] + scope: ['admin:repo_hook', 'read:org', 'repo:status', 'repo'] } }); }); @@ -2158,13 +2191,19 @@ jobs: }; beforeEach(() => { - githubMock.request.resolves({ data: { - full_name: 'dolores/violentdelights' - } }); - githubMock.repos.listWebhooks.resolves({ data: [{ - config: { url: 'https://somewhere.in/the/interwebs' }, - id: 783150 - }] }); + githubMock.request.resolves({ + data: { + full_name: 'dolores/violentdelights' + } + }); + githubMock.repos.listWebhooks.resolves({ + data: [ + { + config: { url: 'https://somewhere.in/the/interwebs' }, + id: 783150 + } + ] + }); }); it('add a hook', () => { @@ -2172,9 +2211,7 @@ jobs: githubMock.repos.createWebhook.resolves({ data: [] }); return scm.addWebhook(webhookConfig).then(() => { - assert.calledWith(githubMock.request, 'GET /repositories/:id', - { id: '1263' } - ); + assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '1263' }); assert.calledWith(githubMock.repos.createWebhook, { active: true, config: { @@ -2254,7 +2291,7 @@ jobs: githubMock.repos.listWebhooks.rejects(testError); - return scm.addWebhook(webhookConfig).then(assert.fail, (err) => { + return scm.addWebhook(webhookConfig).then(assert.fail, err => { assert.equal(err, testError); }); }); @@ -2265,7 +2302,7 @@ jobs: githubMock.repos.listWebhooks.resolves({ data: [] }); githubMock.repos.createWebhook.rejects(testError); - return scm.addWebhook(webhookConfig).then(assert.fail, (err) => { + return scm.addWebhook(webhookConfig).then(assert.fail, err => { assert.equal(err, testError); }); }); @@ -2275,7 +2312,7 @@ jobs: githubMock.repos.updateWebhook.rejects(testError); - return scm.addWebhook(webhookConfig).then(assert.fail, (err) => { + return scm.addWebhook(webhookConfig).then(assert.fail, err => { assert.equal(err, testError); }); }); @@ -2289,36 +2326,40 @@ jobs: }; beforeEach(() => { - githubMock.request.resolves({ data: { - full_name: 'repoOwner/repoName' - } }); + githubMock.request.resolves({ + data: { + full_name: 'repoOwner/repoName' + } + }); }); it('returns a list of opened pull requests', () => { githubMock.pulls.list.resolves({ - data: [{ - number: 1, - title: 'Test 1', - user: { - login: 'collab1', - html_url: '/collab1' - }, - created_at: '2018-10-09T21:35:31Z', - html_url: '/pull/1' - }, - { - number: 2, - title: 'Test 2', - user: { - login: 'collab2', - html_url: '/collab2' + data: [ + { + number: 1, + title: 'Test 1', + user: { + login: 'collab1', + html_url: '/collab1' + }, + created_at: '2018-10-09T21:35:31Z', + html_url: '/pull/1' }, - created_at: '2018-10-10T21:35:31Z', - html_url: '/pull/2' - }] + { + number: 2, + title: 'Test 2', + user: { + login: 'collab2', + html_url: '/collab2' + }, + created_at: '2018-10-10T21:35:31Z', + html_url: '/pull/2' + } + ] }); - return scm._getOpenedPRs(config).then((data) => { + return scm._getOpenedPRs(config).then(data => { assert.deepEqual(data, [ { name: 'PR-1', @@ -2354,7 +2395,7 @@ jobs: githubMock.request.rejects(testError); - return scm._getOpenedPRs(config).then(assert.fail, (err) => { + return scm._getOpenedPRs(config).then(assert.fail, err => { assert.instanceOf(err, Error); assert.strictEqual(testError.message, err.message); }); @@ -2365,7 +2406,7 @@ jobs: githubMock.pulls.list.rejects(testError); - return scm._getOpenedPRs(config).then(assert.fail, (err) => { + return scm._getOpenedPRs(config).then(assert.fail, err => { assert.instanceOf(err, Error); assert.strictEqual(testError.message, err.message); }); @@ -2382,33 +2423,31 @@ jobs: const sha = '6dcb09b5b57875f334f61aebed695e2e4193db5e'; beforeEach(() => { - githubMock.request.resolves({ data: { - full_name: 'repoOwner/repoName' - } }); + githubMock.request.resolves({ + data: { + full_name: 'repoOwner/repoName' + } + }); }); it('returns a pull request with the given prNum', () => { - githubMock.pulls.get.resolves( - { data: testPrGet } - ); + githubMock.pulls.get.resolves({ data: testPrGet }); - return scm._getPrInfo(config).then((data) => { - assert.deepEqual(data, - { - name: 'PR-1', - ref: 'pull/1/merge', - sha, - url: 'https://github.com/octocat/Hello-World/pull/1', - username: 'octocat', - title: 'new-feature', - createTime: '2011-01-26T19:01:12Z', - userProfile: 'https://github.com/octocat', - prBranchName: 'new-topic', - baseBranch: 'master', - mergeable: true, - prSource: 'branch' - } - ); + return scm._getPrInfo(config).then(data => { + assert.deepEqual(data, { + name: 'PR-1', + ref: 'pull/1/merge', + sha, + url: 'https://github.com/octocat/Hello-World/pull/1', + username: 'octocat', + title: 'new-feature', + createTime: '2011-01-26T19:01:12Z', + userProfile: 'https://github.com/octocat', + prBranchName: 'new-topic', + baseBranch: 'master', + mergeable: true, + prSource: 'branch' + }); assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '111' }); assert.calledWith(githubMock.pulls.get, { owner: 'repoOwner', @@ -2419,34 +2458,30 @@ jobs: }); it('returns a pull request with the given prNum and scmRepo', () => { - const configWithScmRepo = Object.assign({}, config); + const configWithScmRepo = { ...config }; - githubMock.pulls.get.resolves( - { data: testPrGet } - ); + githubMock.pulls.get.resolves({ data: testPrGet }); configWithScmRepo.scmRepo = { branch: 'branch', url: 'https://github.com/repoOwner/repoName/tree/branch', name: 'repoOwner/repoName' }; - return scm._getPrInfo(configWithScmRepo).then((data) => { - assert.deepEqual(data, - { - name: 'PR-1', - ref: 'pull/1/merge', - sha, - url: 'https://github.com/octocat/Hello-World/pull/1', - username: 'octocat', - title: 'new-feature', - createTime: '2011-01-26T19:01:12Z', - userProfile: 'https://github.com/octocat', - prBranchName: 'new-topic', - baseBranch: 'master', - mergeable: true, - prSource: 'branch' - } - ); + return scm._getPrInfo(configWithScmRepo).then(data => { + assert.deepEqual(data, { + name: 'PR-1', + ref: 'pull/1/merge', + sha, + url: 'https://github.com/octocat/Hello-World/pull/1', + username: 'octocat', + title: 'new-feature', + createTime: '2011-01-26T19:01:12Z', + userProfile: 'https://github.com/octocat', + prBranchName: 'new-topic', + baseBranch: 'master', + mergeable: true, + prSource: 'branch' + }); assert.notCalled(githubMock.request); assert.calledWith(githubMock.pulls.get, { owner: 'repoOwner', @@ -2461,7 +2496,7 @@ jobs: githubMock.request.rejects(testError); - return scm._getPrInfo(config).then(assert.fail, (err) => { + return scm._getPrInfo(config).then(assert.fail, err => { assert.instanceOf(err, Error); assert.strictEqual(testError.message, err.message); }); @@ -2472,7 +2507,7 @@ jobs: githubMock.pulls.get.rejects(testError); - return scm._getPrInfo(config).then(assert.fail, (err) => { + return scm._getPrInfo(config).then(assert.fail, err => { assert.instanceOf(err, Error); assert.strictEqual(testError.message, err.message); }); @@ -2490,24 +2525,22 @@ jobs: }; beforeEach(() => { - githubMock.request.resolves({ data: { - full_name: 'repoOwner/repoName' - } }); + githubMock.request.resolves({ + data: { + full_name: 'repoOwner/repoName' + } + }); }); it('returns some metadata about the comment', () => { - githubMock.issues.createComment.resolves( - { data: testPrCreateComment } - ); + githubMock.issues.createComment.resolves({ data: testPrCreateComment }); - return scm._addPrComment(config).then((data) => { - assert.deepEqual(data, - { - commentId: '1', - createTime: '2011-04-14T16:00:49Z', - username: 'octocat' - } - ); + return scm._addPrComment(config).then(data => { + assert.deepEqual(data, { + commentId: '1', + createTime: '2011-04-14T16:00:49Z', + username: 'octocat' + }); assert.calledWith(githubMock.request, 'GET /repositories/:id', { id: '111' }); assert.calledWith(githubMock.issues.createComment, { owner: 'repoOwner', @@ -2523,7 +2556,7 @@ jobs: githubMock.request.rejects(testError); - return scm._addPrComment(config).then(assert.fail, (err) => { + return scm._addPrComment(config).then(assert.fail, err => { assert.instanceOf(err, Error); assert.strictEqual(testError.message, err.message); }); @@ -2534,12 +2567,15 @@ jobs: githubMock.issues.createComment.rejects(testError); - return scm._addPrComment(config).then((data) => { - assert.isNull(data); - }).catch((err) => { - assert.deepEqual(err, testError); - assert.calledWith(githubMock.issues.createComment, config); - }); + return scm + ._addPrComment(config) + .then(data => { + assert.isNull(data); + }) + .catch(err => { + assert.deepEqual(err, testError); + assert.calledWith(githubMock.issues.createComment, config); + }); }); }); @@ -2578,55 +2614,49 @@ jobs: it('returns true for a pull request event payload', () => { testHeaders['x-hub-signature'] = 'sha1=41d0508ffed278fde2fd5a84fd75c109a7039f90'; - return scm.canHandleWebhook(testHeaders, testPayloadOpen) - .then((result) => { - assert.strictEqual(result, true); - }); + return scm.canHandleWebhook(testHeaders, testPayloadOpen).then(result => { + assert.strictEqual(result, true); + }); }); it('returns true for a pull request being closed', () => { testHeaders['x-hub-signature'] = 'sha1=2d51c3a4eaab65832c119ec3db951de54ec38736'; - return scm.canHandleWebhook(testHeaders, testPayloadClose) - .then((result) => { - assert.strictEqual(result, true); - }); + return scm.canHandleWebhook(testHeaders, testPayloadClose).then(result => { + assert.strictEqual(result, true); + }); }); it('returns true for a pull request being synchronized', () => { testHeaders['x-hub-signature'] = 'sha1=583afb7551c9bc412f7496bc840b027931e97846'; - return scm.canHandleWebhook(testHeaders, testPayloadSync) - .then((result) => { - assert.strictEqual(result, true); - }); + return scm.canHandleWebhook(testHeaders, testPayloadSync).then(result => { + assert.strictEqual(result, true); + }); }); it('returns true for a push event payload', () => { testHeaders['x-github-event'] = 'push'; - return scm.canHandleWebhook(testHeaders, testPayloadPush) - .then((result) => { - assert.strictEqual(result, true); - }); + return scm.canHandleWebhook(testHeaders, testPayloadPush).then(result => { + assert.strictEqual(result, true); + }); }); it('returns false when signature is not valid', () => { testHeaders['x-hub-signature'] = 'sha1=25cebb8fff2c10ec8d0712e3ab0163218d375492'; - return scm.canHandleWebhook(testHeaders, testPayloadPing) - .then((result) => { - assert.strictEqual(result, false); - }); + return scm.canHandleWebhook(testHeaders, testPayloadPing).then(result => { + assert.strictEqual(result, false); + }); }); it('returns false when the github event is not valid', () => { testHeaders['x-github-event'] = 'REEEEEEEE'; - return scm.canHandleWebhook(testHeaders, testPayloadPush) - .then((result) => { - assert.strictEqual(result, false); - }); + return scm.canHandleWebhook(testHeaders, testPayloadPush).then(result => { + assert.strictEqual(result, false); + }); }); it('returns false when different github payload', () => { @@ -2639,10 +2669,9 @@ jobs: testHeaders['x-hub-signature'] = 'sha1=41d0508ffed278fde2fd5a84fd75c109a7039f90'; - return scm.canHandleWebhook(testHeaders, testPayloadOpen) - .then((result) => { - assert.strictEqual(result, false); - }); + return scm.canHandleWebhook(testHeaders, testPayloadOpen).then(result => { + assert.strictEqual(result, false); + }); }); }); @@ -2653,34 +2682,42 @@ jobs: }; beforeEach(() => { - githubMock.request.resolves({ data: { - full_name: 'dolores/violentdelights' - } }); - githubMock.repos.listBranches.resolves({ data: [{ - name: 'master', - commit: { - sha: '6dcb09b5b57875f334f61aebed695e2e4193db5e', - url: 'https://api.github.com/repos/octocat/Hello-World/commits/c5b97' - }, - protected: true, - protection_url: 'https://api.github.com/protect' - }] }); + githubMock.request.resolves({ + data: { + full_name: 'dolores/violentdelights' + } + }); + githubMock.repos.listBranches.resolves({ + data: [ + { + name: 'master', + commit: { + sha: '6dcb09b5b57875f334f61aebed695e2e4193db5e', + url: 'https://api.github.com/repos/octocat/Hello-World/commits/c5b97' + }, + protected: true, + protection_url: 'https://api.github.com/protect' + } + ] + }); }); - it('gets branches', (done) => { - scm.getBranchList(branchListConfig).then((b) => { - assert.calledWith(githubMock.repos.listBranches, { - owner: 'dolores', - repo: 'violentdelights', - page: 1, - per_page: 100 - }); - assert.deepEqual(b, [{ name: 'master' }]); - done(); - }).catch(done); + it('gets branches', done => { + scm.getBranchList(branchListConfig) + .then(b => { + assert.calledWith(githubMock.repos.listBranches, { + owner: 'dolores', + repo: 'violentdelights', + page: 1, + per_page: 100 + }); + assert.deepEqual(b, [{ name: 'master' }]); + done(); + }) + .catch(done); }); - it('gets a lot of branches', (done) => { + it('gets a lot of branches', done => { const fakeBranches = []; for (let i = 0; i < 300; i += 1) {