From 8a388db71c3c87bb1ceed41b09d0e1bf096b411f Mon Sep 17 00:00:00 2001 From: Pedro Pombeiro Date: Fri, 16 Feb 2018 21:35:49 +0100 Subject: [PATCH] Simplify JS code --- bot_scripts/assign-approved-pr-to-test.js | 143 ++++++++---------- bot_scripts/assign-new-pr-to-review.js | 19 +-- .../assign-to-bounty-awaiting-for-approval.js | 13 +- .../bounty-awaiting-approval-slack-ping.js | 17 +-- bot_scripts/greet-new-contributor.js | 26 ++-- bot_scripts/trigger-automation-test-build.js | 44 +++--- index.js | 29 ++-- lib/github-helpers.js | 10 +- 8 files changed, 141 insertions(+), 160 deletions(-) diff --git a/bot_scripts/assign-approved-pr-to-test.js b/bot_scripts/assign-approved-pr-to-test.js index 15acb39..b7d006d 100644 --- a/bot_scripts/assign-approved-pr-to-test.js +++ b/bot_scripts/assign-approved-pr-to-test.js @@ -24,12 +24,8 @@ module.exports = robot => { robot.on('schedule.repository', context => checkOpenPullRequests(robot, context)) } -async function getProjectFromName (github, ownerName, repoName, projectBoardName) { - const ghprojectsPayload = await github.projects.getRepoProjects({ - owner: ownerName, - repo: repoName, - state: 'open' - }) +async function getProjectFromName (github, repoInfo, projectBoardName) { + const ghprojectsPayload = await github.projects.getRepoProjects({ ...repoInfo, state: 'open' }) return ghprojectsPayload.data.find(p => p.name === projectBoardName) } @@ -37,13 +33,12 @@ async function getProjectFromName (github, ownerName, repoName, projectBoardName async function checkOpenPullRequests (robot, context) { const { github, payload } = context const repo = payload.repository - const ownerName = repo.owner.login - const repoName = repo.name + const repoInfo = { owner: payload.repository.owner.login, repo: payload.repository.name } const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const projectBoardConfig = config ? config['project-board'] : null if (!projectBoardConfig) { - robot.log.debug(`${botName} - Project board not configured in repo ${ownerName}/${repoName}, ignoring`) + robot.log.debug(`${botName} - Project board not configured in repo ${repoInfo.owner}/${repoInfo.repo}, ignoring`) return } @@ -57,15 +52,15 @@ async function checkOpenPullRequests (robot, context) { let project try { // Find 'Pipeline for QA' project - project = await getProjectFromName(github, ownerName, repoName, projectBoardConfig.name) + project = await getProjectFromName(github, repoInfo, projectBoardConfig.name) if (!project) { - robot.log.error(`${botName} - Couldn't find project ${projectBoardConfig.name} in repo ${ownerName}/${repoName}`) + robot.log.error(`${botName} - Couldn't find project ${projectBoardConfig.name} in repo ${repoInfo.owner}/${repoInfo.repo}`) return } robot.log.debug(`${botName} - Fetched ${project.name} project (${project.id})`) } catch (err) { - robot.log.error(`${botName} - Couldn't fetch the github projects for repo: ${err}`, ownerName, repoName) + robot.log.error(`${botName} - Couldn't fetch the github projects for repo: ${err}`, repoInfo) return } @@ -75,85 +70,57 @@ async function checkOpenPullRequests (robot, context) { const ghcolumnsPayload = await github.projects.getProjectColumns({ project_id: project.id }) ghcolumns = ghcolumnsPayload.data } catch (err) { - robot.log.error(`${botName} - Couldn't fetch the github columns for project: ${err}`, ownerName, repoName, project.id) + robot.log.error(`${botName} - Couldn't fetch the github columns for project: ${err}`, repoInfo, project.id) return } - const contributorColumn = ghcolumns.find(c => c.name === contributorColumnName) - if (!contributorColumn) { - robot.log.error(`${botName} - Couldn't find ${contributorColumnName} column in project ${project.name}`) - return - } - - const reviewColumn = ghcolumns.find(c => c.name === reviewColumnName) - if (!reviewColumn) { - robot.log.error(`${botName} - Couldn't find ${reviewColumnName} column in project ${project.name}`) - return - } - - const testColumn = ghcolumns.find(c => c.name === testColumnName) - if (!testColumn) { - robot.log.error(`${botName} - Couldn't find ${testColumnName} column in project ${project.name}`) - return - } - - robot.log.debug(`${botName} - Fetched ${contributorColumn.name} (${contributorColumn.id}), ${reviewColumn.name} (${reviewColumn.id}), ${testColumn.name} (${testColumn.id}) columns`) - try { - // Gather all open PRs in this repo - const allPullRequests = await github.paginate( - github.pullRequests.getAll({owner: ownerName, repo: repoName, per_page: 100}), - res => res.data - ) + const contributorColumn = findColumnByName(ghcolumns, contributorColumnName) + const reviewColumn = findColumnByName(ghcolumns, reviewColumnName) + const testColumn = findColumnByName(ghcolumns, testColumnName) - // And make sure they are assigned to the correct project column - for (const pullRequest of allPullRequests) { - try { - await assignPullRequestToCorrectColumn(github, robot, repo, pullRequest, contributorColumn, reviewColumn, testColumn, config.slack.notification.room) - } catch (err) { - robot.log.error(`${botName} - Unhandled exception while processing PR: ${err}`, ownerName, repoName) + robot.log.debug(`${botName} - Fetched ${contributorColumn.name} (${contributorColumn.id}), ${reviewColumn.name} (${reviewColumn.id}), ${testColumn.name} (${testColumn.id}) columns`) + + try { + // Gather all open PRs in this repo + const allPullRequests = await github.paginate( + github.pullRequests.getAll({ ...repoInfo, per_page: 100 }), + res => res.data + ) + + // And make sure they are assigned to the correct project column + for (const pullRequest of allPullRequests) { + try { + const columns = { contributor: contributorColumn, review: reviewColumn, test: testColumn } + await assignPullRequestToCorrectColumn(github, robot, repo, pullRequest, columns, config.slack.notification.room) + } catch (err) { + robot.log.error(`${botName} - Unhandled exception while processing PR: ${err}`, repoInfo) + } } + } catch (err) { + robot.log.error(`${botName} - Couldn't fetch the github pull requests for repo: ${err}`, repoInfo) } } catch (err) { - robot.log.error(`${botName} - Couldn't fetch the github pull requests for repo: ${err}`, ownerName, repoName) + robot.log.error(err.message, project.name) } } -async function assignPullRequestToCorrectColumn (github, robot, repo, pullRequest, contributorColumn, reviewColumn, testColumn, room) { - const repoOwner = repo.owner.login - const repoName = repo.name - const prNumber = pullRequest.number +async function assignPullRequestToCorrectColumn (github, robot, repo, pullRequest, columns, room) { + const prInfo = { owner: repo.owner.login, repo: repo.name, number: pullRequest.number } let state = null try { - state = await gitHubHelpers.getReviewApprovalState(github, robot, repoOwner, repoName, prNumber) + state = await gitHubHelpers.getReviewApprovalState(github, robot, prInfo) } catch (err) { - robot.log.error(`${botName} - Couldn't calculate the PR approval state: ${err}`, repoOwner, repoName, prNumber) + robot.log.error(`${botName} - Couldn't calculate the PR approval state: ${err}`, prInfo) } - let srcColumns, dstColumn - switch (state) { - case 'awaiting_reviewers': - srcColumns = [contributorColumn, testColumn] - dstColumn = reviewColumn - break - case 'changes_requested': - srcColumns = [reviewColumn, testColumn] - dstColumn = contributorColumn - break - case 'failed': - srcColumns = [reviewColumn, testColumn] - dstColumn = contributorColumn - break - case 'approved': - srcColumns = [contributorColumn, reviewColumn] - dstColumn = testColumn - break - default: - return + const { srcColumns, dstColumn } = getColumns(state, columns) + if (!dstColumn) { + return } - robot.log.debug(`${botName} - Handling Pull Request #${prNumber} on repo ${repoOwner}/${repoName}. PR should be in ${dstColumn.name} column`) + robot.log.debug(`${botName} - Handling Pull Request #${prInfo.number} on repo ${prInfo.owner}/${prInfo.repo}. PR should be in ${dstColumn.name} column`) // Look for PR card in source column(s) let existingGHCard = null @@ -181,12 +148,12 @@ async function assignPullRequestToCorrectColumn (github, robot, repo, pullReques } if (process.env.DRY_RUN || process.env.DRY_RUN_PR_TO_TEST) { - robot.log.info(`${botName} - Would have moved card ${existingGHCard.id} to ${dstColumn.name} for PR #${prNumber}`) + robot.log.info(`${botName} - Would have moved card ${existingGHCard.id} to ${dstColumn.name} for PR #${prInfo.number}`) } else { // Found in the source column, let's move it to the destination column await github.projects.moveProjectCard({id: existingGHCard.id, position: 'bottom', column_id: dstColumn.id}) - robot.log.info(`${botName} - Moved card ${existingGHCard.id} to ${dstColumn.name} for PR #${prNumber}`) + robot.log.info(`${botName} - Moved card ${existingGHCard.id} to ${dstColumn.name} for PR #${prInfo.number}`) } slackHelper.sendMessage(robot, room, `Assigned PR to ${dstColumn.name} column\n${pullRequest.html_url}`) @@ -211,7 +178,7 @@ async function assignPullRequestToCorrectColumn (github, robot, repo, pullReques } if (process.env.DRY_RUN || process.env.DRY_RUN_PR_TO_TEST) { - robot.log.info(`Would have created card in ${dstColumn.name} column for PR #${prNumber}`) + robot.log.info(`Would have created card in ${dstColumn.name} column for PR #${prInfo.number}`) } else { // It wasn't in either the source nor the destination columns, let's create a new card for it in the destination column const ghcardPayload = await github.projects.createProjectCard({ @@ -220,7 +187,7 @@ async function assignPullRequestToCorrectColumn (github, robot, repo, pullReques content_id: pullRequest.id }) - robot.log.info(`${botName} - Created card ${ghcardPayload.data.id} in ${dstColumn.name} for PR #${prNumber}`) + robot.log.info(`${botName} - Created card ${ghcardPayload.data.id} in ${dstColumn.name} for PR #${prInfo.number}`) } } catch (err) { // We normally arrive here because there is already a card for the PR in another column @@ -228,3 +195,27 @@ async function assignPullRequestToCorrectColumn (github, robot, repo, pullReques } } } + +function getColumns (state, columns) { + switch (state) { + case 'awaiting_reviewers': + return { srcColumns: [columns.contributor, columns.test], dstColumn: columns.review } + case 'changes_requested': + return { srcColumns: [columns.review, columns.test], dstColumn: columns.contributor } + case 'failed': + return { srcColumns: [columns.review, columns.test], dstColumn: columns.contributor } + case 'approved': + return { srcColumns: [columns.contributor, columns.review], dstColumn: columns.test } + default: + return { srcColumns: [], dstColumn: null } + } +} + +function findColumnByName (ghcolumns, columnName) { + const column = ghcolumns.find(c => c.name === columnName) + if (!column) { + throw new Error(`${botName} - Couldn't find ${columnName} column`) + } + + return column +} diff --git a/bot_scripts/assign-new-pr-to-review.js b/bot_scripts/assign-new-pr-to-review.js index fe3c309..cefb8ae 100644 --- a/bot_scripts/assign-new-pr-to-review.js +++ b/bot_scripts/assign-new-pr-to-review.js @@ -10,9 +10,9 @@ // PombeirP const defaultConfig = require('../lib/config') +const slackHelper = require('../lib/slack') const getConfig = require('probot-config') -const slackHelper = require('../lib/slack') const botName = 'assign-new-pr-to-review' @@ -29,8 +29,7 @@ module.exports = (robot) => { async function assignPullRequestToReview (context, robot) { const { github, payload } = context const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) - const ownerName = payload.repository.owner.login - const repoName = payload.repository.name + const repoInfo = { owner: payload.repository.owner.login, repo: payload.repository.name } const prNumber = payload.pull_request.number const projectBoardConfig = config ? config['project-board'] : null @@ -38,7 +37,7 @@ async function assignPullRequestToReview (context, robot) { return } - robot.log(`${botName} - Handling Pull Request #${prNumber} on repo ${ownerName}/${repoName}`) + robot.log(`${botName} - Handling Pull Request #${prNumber} on repo ${repoInfo.owner}/${repoInfo.repo}`) // Fetch repo projects // TODO: The repo project and project column info should be cached @@ -47,16 +46,12 @@ async function assignPullRequestToReview (context, robot) { const projectBoardName = projectBoardConfig.name const reviewColumnName = projectBoardConfig['review-column-name'] try { - const ghprojectsPayload = await github.projects.getRepoProjects({ - owner: ownerName, - repo: repoName, - state: 'open' - }) + const ghprojectsPayload = await github.projects.getRepoProjects({ ...repoInfo, state: 'open' }) // Find 'Pipeline for QA' project const project = ghprojectsPayload.data.find(p => p.name === projectBoardName) if (!project) { - robot.log.error(`${botName} - Couldn't find project ${projectBoardName} in repo ${ownerName}/${repoName}`) + robot.log.error(`${botName} - Couldn't find project ${projectBoardName} in repo ${repoInfo.owner}/${repoInfo.repo}`) return } @@ -74,11 +69,11 @@ async function assignPullRequestToReview (context, robot) { robot.log.debug(`${botName} - Fetched ${column.name} column (${column.id})`) } catch (err) { - robot.log.error(`${botName} - Couldn't fetch the github columns for project: ${err}`, ownerName, repoName, project.id) + robot.log.error(`${botName} - Couldn't fetch the github columns for project: ${err}`, repoInfo, project.id) return } } catch (err) { - robot.log.error(`${botName} - Couldn't fetch the github projects for repo: ${err}`, ownerName, repoName) + robot.log.error(`${botName} - Couldn't fetch the github projects for repo: ${err}`, repoInfo) return } diff --git a/bot_scripts/assign-to-bounty-awaiting-for-approval.js b/bot_scripts/assign-to-bounty-awaiting-for-approval.js index 0139621..374f79f 100644 --- a/bot_scripts/assign-to-bounty-awaiting-for-approval.js +++ b/bot_scripts/assign-to-bounty-awaiting-for-approval.js @@ -36,8 +36,7 @@ module.exports = (robot) => { async function assignIssueToBountyAwaitingForApproval (context, robot, assign) { const { github, payload } = context - const ownerName = payload.repository.owner.login - const repoName = payload.repository.name + const repoInfo = { owner: payload.repository.owner.login, repo: payload.repository.name } const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const projectBoardConfig = config ? config['bounty-project-board'] : null @@ -52,9 +51,9 @@ async function assignIssueToBountyAwaitingForApproval (context, robot, assign) { } if (assign) { - robot.log(`${botName} - Handling labeling of #${payload.issue.number} with ${payload.label.name} on repo ${ownerName}/${repoName}`) + robot.log(`${botName} - Handling labeling of #${payload.issue.number} with ${payload.label.name} on repo ${repoInfo.owner}/${repoInfo.repo}`) } else { - robot.log(`${botName} - Handling unlabeling of #${payload.issue.number} with ${payload.label.name} on repo ${ownerName}/${repoName}`) + robot.log(`${botName} - Handling unlabeling of #${payload.issue.number} with ${payload.label.name} on repo ${repoInfo.owner}/${repoInfo.repo}`) } // Fetch org projects @@ -64,7 +63,7 @@ async function assignIssueToBountyAwaitingForApproval (context, robot, assign) { const projectBoardName = projectBoardConfig.name const approvalColumnName = projectBoardConfig['awaiting-approval-column-name'] try { - const orgName = ownerName + const orgName = repoInfo.owner const ghprojectsPayload = await github.projects.getOrgProjects({ org: orgName, @@ -92,11 +91,11 @@ async function assignIssueToBountyAwaitingForApproval (context, robot, assign) { robot.log.debug(`${botName} - Fetched ${column.name} column (${column.id})`) } catch (err) { - robot.log.error(`${botName} - Couldn't fetch the github columns for project: ${err}`, ownerName, repoName, project.id) + robot.log.error(`${botName} - Couldn't fetch the github columns for project: ${err}`, repoInfo, project.id) return } } catch (err) { - robot.log.error(`${botName} - Couldn't fetch the github projects for repo: ${err}`, ownerName, repoName) + robot.log.error(`${botName} - Couldn't fetch the github projects for repo: ${err}`, repoInfo) return } diff --git a/bot_scripts/bounty-awaiting-approval-slack-ping.js b/bot_scripts/bounty-awaiting-approval-slack-ping.js index 50c9e48..4f0e6e8 100644 --- a/bot_scripts/bounty-awaiting-approval-slack-ping.js +++ b/bot_scripts/bounty-awaiting-approval-slack-ping.js @@ -33,19 +33,18 @@ function registerForNewBounties (robot) { async function notifyCollaborators (context, robot) { const { github, payload } = context - const ownerName = payload.repository.owner.login - const repoName = payload.repository.name + const repoInfo = { owner: payload.repository.owner.login, repo: payload.repository.name } const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const bountyProjectBoardConfig = config ? config['bounty-project-board'] : null const gitHubTeamConfig = config ? config['github-team'] : null if (!bountyProjectBoardConfig) { - robot.log.debug(`${botName} - Bounty project board not configured in repo ${ownerName}/${repoName}, ignoring`) + robot.log.debug(`${botName} - Bounty project board not configured in repo ${repoInfo.owner}/${repoInfo.repo}, ignoring`) return } if (!gitHubTeamConfig) { - robot.log.debug(`${botName} - GitHub team not configured in repo ${ownerName}/${repoName}, ignoring`) + robot.log.debug(`${botName} - GitHub team not configured in repo ${repoInfo.owner}/${repoInfo.repo}, ignoring`) return } @@ -55,9 +54,9 @@ async function notifyCollaborators (context, robot) { return null } - robot.log(`${botName} - issue #${payload.issue.number} on ${ownerName}/${repoName} was labeled as a bounty awaiting approval. Pinging slack...`) + robot.log(`${botName} - issue #${payload.issue.number} on ${repoInfo.owner}/${repoInfo.repo} was labeled as a bounty awaiting approval. Pinging slack...`) - const slackCollaborators = await getSlackCollaborators(ownerName, repoName, github, robot, gitHubTeamConfig) + const slackCollaborators = await getSlackCollaborators(repoInfo, github, robot, gitHubTeamConfig) // Mention the project board owner as well, if configured const bountyProjectBoardOwner = bountyProjectBoardConfig['owner'] @@ -82,15 +81,15 @@ function randomInt (low, high) { } // Get the Slack IDs of the collaborators of this repo. -async function getSlackCollaborators (ownerName, repoName, github, robot, gitHubTeamConfig) { +async function getSlackCollaborators (repoInfo, github, robot, gitHubTeamConfig) { const teamSlug = gitHubTeamConfig['slug'] if (!teamSlug) { - robot.log.debug(`${botName} - GitHub team slug not configured in repo ${ownerName}/${repoName}, ignoring`) + robot.log.debug(`${botName} - GitHub team slug not configured in repo ${repoInfo.owner}/${repoInfo.repo}, ignoring`) return } // Grab a list of collaborators to this repo, as an array of GitHub login usernames - const teams = await github.paginate(github.orgs.getTeams({org: ownerName}), res => res.data) + const teams = await github.paginate(github.orgs.getTeams({ org: repoInfo.owner }), res => res.data) const team = teams.find(t => t.slug === teamSlug) if (!team) { robot.log.debug(`${botName} - GitHub team with slug ${teamSlug} was not found. Ignoring`) diff --git a/bot_scripts/greet-new-contributor.js b/bot_scripts/greet-new-contributor.js index 562816c..eefcf01 100644 --- a/bot_scripts/greet-new-contributor.js +++ b/bot_scripts/greet-new-contributor.js @@ -43,21 +43,19 @@ function executeTemplate (templateString, templateVars) { async function greetNewContributor (context, robot) { const { github, payload } = context const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) - const ownerName = payload.repository.owner.login - const repoName = payload.repository.name - const prNumber = payload.pull_request.number + const repoInfo = { owner: payload.repository.owner.login, repo: payload.repository.name } + const prInfo = { ...repoInfo, number: payload.pull_request.number } const welcomeBotConfig = config ? config['welcome-bot'] : null if (!welcomeBotConfig) { return } - robot.log(`${botName} - Handling Pull Request #${prNumber} on repo ${ownerName}/${repoName}`) + robot.log(`${botName} - Handling Pull Request #${prInfo.number} on repo ${repoInfo.owner}/${repoInfo.repo}`) try { const ghissuesPayload = await github.issues.getForRepo({ - owner: ownerName, - repo: repoName, + ...repoInfo, state: 'all', creator: payload.pull_request.user.login }) @@ -65,30 +63,28 @@ async function greetNewContributor (context, robot) { const userPullRequests = ghissuesPayload.data.filter(issue => issue.pull_request) if (userPullRequests.length === 1) { try { - const welcomeMessage = executeTemplate(welcomeBotConfig['message-template'], { user: payload.pull_request.user.login, 'pr-number': prNumber, 'repo-name': repoName }) + const welcomeMessage = executeTemplate(welcomeBotConfig['message-template'], { user: payload.pull_request.user.login, 'pr-number': prInfo.number, 'repo-name': repoInfo.repo }) if (process.env.DRY_RUN) { - robot.log(`${botName} - Would have created comment in GHI`, ownerName, repoName, prNumber, welcomeMessage) + robot.log(`${botName} - Would have created comment in GHI`, prInfo, welcomeMessage) } else { await github.issues.createComment({ - owner: ownerName, - repo: repoName, - number: prNumber, + ...prInfo, body: welcomeMessage }) } // Send message to Slack - slackHelper.sendMessage(robot, config.slack.notification.room, `Greeted ${payload.pull_request.user.login} on his first PR in the ${repoName} repo\n${payload.pull_request.html_url}`) + slackHelper.sendMessage(robot, config.slack.notification.room, `Greeted ${payload.pull_request.user.login} on his first PR in the ${repoInfo.repo} repo\n${payload.pull_request.html_url}`) } catch (err) { if (err.code !== 404) { - robot.log.error(`${botName} - Couldn't create comment on PR: ${err}`, ownerName, repoName) + robot.log.error(`${botName} - Couldn't create comment on PR: ${err}`, repoInfo) } } } else { - robot.log.debug(`${botName} - This is not the user's first PR on the repo, ignoring`, ownerName, repoName, payload.pull_request.user.login) + robot.log.debug(`${botName} - This is not the user's first PR on the repo, ignoring`, repoInfo, payload.pull_request.user.login) } } catch (err) { - robot.log.error(`${botName} - Couldn't fetch the user's github issues for repo: ${err}`, ownerName, repoName) + robot.log.error(`${botName} - Couldn't fetch the user's github issues for repo: ${err}`, repoInfo) } } diff --git a/bot_scripts/trigger-automation-test-build.js b/bot_scripts/trigger-automation-test-build.js index f84df5d..df76d45 100644 --- a/bot_scripts/trigger-automation-test-build.js +++ b/bot_scripts/trigger-automation-test-build.js @@ -42,6 +42,7 @@ async function processChangedProjectCard (robot, context) { return } + const repoInfo = { owner: repo.owner.login, name: repo.name } const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const projectBoardConfig = config ? config['project-board'] : null const automatedTestsConfig = config ? config['automated-tests'] : null @@ -81,12 +82,10 @@ async function processChangedProjectCard (robot, context) { return a[a.length + index] } - let project try { const projectId = last(inTestColumn.project_url.split('/'), -1) const projectPayload = await github.projects.getProject({ id: projectId }) - - project = projectPayload.data + const project = projectPayload.data if (project.name !== projectBoardName) { robot.log.trace(`${botName} - Card column name doesn't match watched column name, exiting`, project.name, projectBoardName) return @@ -99,52 +98,52 @@ async function processChangedProjectCard (robot, context) { const prNumber = last(payload.project_card.content_url.split('/'), -1) const fullJobName = automatedTestsConfig['job-full-name'] - await processPullRequest(github, robot, repo.owner.login, repo.name, prNumber, fullJobName) + await processPullRequest(github, robot, { ...repoInfo, number: prNumber }, fullJobName) } -async function processPullRequest (github, robot, repoOwner, repoName, prNumber, fullJobName) { +async function processPullRequest (github, robot, prInfo, fullJobName) { // Remove the PR from the pending PR list, if it is there - pendingPullRequests.delete(prNumber) + pendingPullRequests.delete(prInfo.number) try { - const state = await gitHubHelpers.getReviewApprovalState(github, robot, repoOwner, repoName, prNumber) + const state = await gitHubHelpers.getReviewApprovalState(github, robot, prInfo) switch (state) { case 'unstable': case 'awaiting_reviewers': case 'changes_requested': - pendingPullRequests.set(prNumber, { github: github, repoOwner: repoOwner, repoName: repoName, fullJobName: fullJobName }) - robot.log.debug(`${botName} - State is '${state}', adding to backlog to check periodically`, prNumber) + pendingPullRequests.set(prInfo.number, { github: github, prInfo, fullJobName: fullJobName }) + robot.log.debug(`${botName} - State is '${state}', adding to backlog to check periodically`, prInfo) return case 'failed': - robot.log.debug(`${botName} - State is '${state}', exiting`, prNumber) + robot.log.debug(`${botName} - State is '${state}', exiting`, prInfo) return case 'approved': - robot.log.debug(`${botName} - State is '${state}', proceeding`, prNumber) + robot.log.debug(`${botName} - State is '${state}', proceeding`, prInfo) break default: - robot.log.warn(`${botName} - State is '${state}', ignoring`, prNumber) + robot.log.warn(`${botName} - State is '${state}', ignoring`, prInfo) return } } catch (err) { - robot.log.error(`Couldn't calculate the PR approval state: ${err}`, repoOwner, repoName, prNumber) + robot.log.error(`Couldn't calculate the PR approval state: ${err}`, prInfo) return } try { - const args = { parameters: { pr_id: prNumber, apk: `--apk=${prNumber}.apk` } } + const args = { parameters: { pr_id: prInfo.number, apk: `--apk=${prInfo.number}.apk` } } if (process.env.DRY_RUN) { - robot.log(`${botName} - Would start ${fullJobName} job in Jenkins`, prNumber, args) + robot.log(`${botName} - Would start ${fullJobName} job in Jenkins`, prInfo, args) } else { - robot.log(`${botName} - Starting ${fullJobName} job in Jenkins`, prNumber, args) + robot.log(`${botName} - Starting ${fullJobName} job in Jenkins`, prInfo, args) const buildId = await jenkins.job.build(fullJobName, args) - robot.log(`${botName} - Started job in Jenkins`, prNumber, buildId) + robot.log(`${botName} - Started job in Jenkins`, prInfo, buildId) } } catch (error) { - robot.log.error(`${botName} - Error while triggering Jenkins build. Will retry later`, prNumber, error) + robot.log.error(`${botName} - Error while triggering Jenkins build. Will retry later`, prInfo, error) - pendingPullRequests.set(prNumber, { github: github, repoOwner: repoOwner, repoName: repoName, fullJobName: fullJobName }) + pendingPullRequests.set(prInfo.number, { github: github, prInfo: prInfo, fullJobName: fullJobName }) } } @@ -153,11 +152,8 @@ async function checkPendingPullRequests (robot) { robot.log.trace(`${botName} - Processing ${_pendingPullRequests.size} pending PRs`) - for (const kvp of _pendingPullRequests.entries()) { - const prNumber = kvp[0] - const { github, repoOwner, repoName, fullJobName } = kvp[1] - - await processPullRequest(github, robot, repoOwner, repoName, prNumber, fullJobName) + for (const { github, prInfo, fullJobName } of _pendingPullRequests.values()) { + await processPullRequest(github, robot, prInfo, fullJobName) } robot.log.trace(`${botName} - Finished processing ${_pendingPullRequests.size} pending PRs`) diff --git a/index.js b/index.js index a97e81c..eaa2120 100644 --- a/index.js +++ b/index.js @@ -3,18 +3,7 @@ const Slack = require('./lib/slack') module.exports = async (robot) => { console.log('Yay, the app was loaded!') - Slack(robot, slack => {}) - - await new Promise(resolve => { - robot.on('slack.connected', event => { - robot.log.info(`Connected to Slack`) - - // Copy Slack RTM and Slack Web clients to the robot object - robot['slack'] = event.payload.slack - robot['slackWeb'] = event.payload.slackWeb - resolve() - }) - }) + await setupSlack(robot) robot['gitHubIdMapper'] = require('./lib/github-id-mapper')(robot) @@ -32,3 +21,19 @@ module.exports = async (robot) => { // To get your app running against GitHub, see: // https://probot.github.io/docs/development/ } + +async function setupSlack (robot) { + Slack(robot, slack => {}) + + await new Promise(resolve => { + robot.on('slack.connected', event => { + robot.log.info(`Connected to Slack`) + + // Copy Slack RTM and Slack Web clients to the robot object + robot['slack'] = event.payload.slack + robot['slackWeb'] = event.payload.slackWeb + + resolve() + }) + }) +} diff --git a/lib/github-helpers.js b/lib/github-helpers.js index f8393d6..5de97b4 100644 --- a/lib/github-helpers.js +++ b/lib/github-helpers.js @@ -11,10 +11,10 @@ module.exports.getPullRequestReviewStates = _getPullRequestReviewStates module.exports.getReviewApprovalState = _getReviewApprovalState module.exports.getProjectCardForIssue = _getProjectCardForIssue -async function _getPullRequestReviewStates (github, repoOwner, repoName, prNumber) { +async function _getPullRequestReviewStates (github, prInfo) { let finalReviewsMap = new Map() const ghreviews = await github.paginate( - github.pullRequests.getReviews({owner: repoOwner, repo: repoName, number: prNumber, per_page: 100}), + github.pullRequests.getReviews({ ...prInfo, per_page: 100 }), res => res.data) for (var review of ghreviews) { switch (review.state) { @@ -29,9 +29,9 @@ async function _getPullRequestReviewStates (github, repoOwner, repoName, prNumbe return Array.from(finalReviewsMap.values()) } -async function _getReviewApprovalState (github, robot, repoOwner, repoName, prNumber) { +async function _getReviewApprovalState (github, robot, prInfo) { // Get detailed pull request - const pullRequestPayload = await github.pullRequests.get({owner: repoOwner, repo: repoName, number: prNumber}) + const pullRequestPayload = await github.pullRequests.get(prInfo) const pullRequest = pullRequestPayload.data if (pullRequest.mergeable !== null && pullRequest.mergeable !== undefined && !pullRequest.mergeable) { robot.log.debug(`pullRequest.mergeable is ${pullRequest.mergeable}, considering as failed`) @@ -55,7 +55,7 @@ async function _getReviewApprovalState (github, robot, repoOwner, repoName, prNu const threshold = 2 // Minimum number of approvers - const finalReviews = await _getPullRequestReviewStates(github, repoOwner, repoName, pullRequest.number) + const finalReviews = await _getPullRequestReviewStates(github, prInfo) robot.log.debug(finalReviews) const approvedReviews = finalReviews.filter(reviewState => reviewState === 'APPROVED')