Simplify JS code

This commit is contained in:
Pedro Pombeiro 2018-02-16 21:35:49 +01:00
parent a9eb8d117a
commit 8a388db71c
No known key found for this signature in database
GPG Key ID: A65DEB11E4BBC647
8 changed files with 141 additions and 160 deletions

View File

@ -24,12 +24,8 @@ module.exports = robot => {
robot.on('schedule.repository', context => checkOpenPullRequests(robot, context)) robot.on('schedule.repository', context => checkOpenPullRequests(robot, context))
} }
async function getProjectFromName (github, ownerName, repoName, projectBoardName) { async function getProjectFromName (github, repoInfo, projectBoardName) {
const ghprojectsPayload = await github.projects.getRepoProjects({ const ghprojectsPayload = await github.projects.getRepoProjects({ ...repoInfo, state: 'open' })
owner: ownerName,
repo: repoName,
state: 'open'
})
return ghprojectsPayload.data.find(p => p.name === projectBoardName) return ghprojectsPayload.data.find(p => p.name === projectBoardName)
} }
@ -37,13 +33,12 @@ async function getProjectFromName (github, ownerName, repoName, projectBoardName
async function checkOpenPullRequests (robot, context) { async function checkOpenPullRequests (robot, context) {
const { github, payload } = context const { github, payload } = context
const repo = payload.repository const repo = payload.repository
const ownerName = repo.owner.login const repoInfo = { owner: payload.repository.owner.login, repo: payload.repository.name }
const repoName = repo.name
const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml'))
const projectBoardConfig = config ? config['project-board'] : null const projectBoardConfig = config ? config['project-board'] : null
if (!projectBoardConfig) { 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 return
} }
@ -57,15 +52,15 @@ async function checkOpenPullRequests (robot, context) {
let project let project
try { try {
// Find 'Pipeline for QA' project // Find 'Pipeline for QA' project
project = await getProjectFromName(github, ownerName, repoName, projectBoardConfig.name) project = await getProjectFromName(github, repoInfo, projectBoardConfig.name)
if (!project) { 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 return
} }
robot.log.debug(`${botName} - Fetched ${project.name} project (${project.id})`) robot.log.debug(`${botName} - Fetched ${project.name} project (${project.id})`)
} catch (err) { } 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 return
} }
@ -75,85 +70,57 @@ async function checkOpenPullRequests (robot, context) {
const ghcolumnsPayload = await github.projects.getProjectColumns({ project_id: project.id }) const ghcolumnsPayload = await github.projects.getProjectColumns({ project_id: project.id })
ghcolumns = ghcolumnsPayload.data ghcolumns = ghcolumnsPayload.data
} catch (err) { } 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 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 { try {
// Gather all open PRs in this repo const contributorColumn = findColumnByName(ghcolumns, contributorColumnName)
const allPullRequests = await github.paginate( const reviewColumn = findColumnByName(ghcolumns, reviewColumnName)
github.pullRequests.getAll({owner: ownerName, repo: repoName, per_page: 100}), const testColumn = findColumnByName(ghcolumns, testColumnName)
res => res.data
)
// And make sure they are assigned to the correct project column robot.log.debug(`${botName} - Fetched ${contributorColumn.name} (${contributorColumn.id}), ${reviewColumn.name} (${reviewColumn.id}), ${testColumn.name} (${testColumn.id}) columns`)
for (const pullRequest of allPullRequests) {
try { try {
await assignPullRequestToCorrectColumn(github, robot, repo, pullRequest, contributorColumn, reviewColumn, testColumn, config.slack.notification.room) // Gather all open PRs in this repo
} catch (err) { const allPullRequests = await github.paginate(
robot.log.error(`${botName} - Unhandled exception while processing PR: ${err}`, ownerName, repoName) 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) { } 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) { async function assignPullRequestToCorrectColumn (github, robot, repo, pullRequest, columns, room) {
const repoOwner = repo.owner.login const prInfo = { owner: repo.owner.login, repo: repo.name, number: pullRequest.number }
const repoName = repo.name
const prNumber = pullRequest.number
let state = null let state = null
try { try {
state = await gitHubHelpers.getReviewApprovalState(github, robot, repoOwner, repoName, prNumber) state = await gitHubHelpers.getReviewApprovalState(github, robot, prInfo)
} catch (err) { } 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 const { srcColumns, dstColumn } = getColumns(state, columns)
switch (state) { if (!dstColumn) {
case 'awaiting_reviewers': return
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
} }
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) // Look for PR card in source column(s)
let existingGHCard = null 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) { 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 { } else {
// Found in the source column, let's move it to the destination column // 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}) 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}`) 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) { 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 { } else {
// It wasn't in either the source nor the destination columns, let's create a new card for it in the destination column // 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({ const ghcardPayload = await github.projects.createProjectCard({
@ -220,7 +187,7 @@ async function assignPullRequestToCorrectColumn (github, robot, repo, pullReques
content_id: pullRequest.id 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) { } catch (err) {
// We normally arrive here because there is already a card for the PR in another column // 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
}

View File

@ -10,9 +10,9 @@
// PombeirP // PombeirP
const defaultConfig = require('../lib/config') const defaultConfig = require('../lib/config')
const slackHelper = require('../lib/slack')
const getConfig = require('probot-config') const getConfig = require('probot-config')
const slackHelper = require('../lib/slack')
const botName = 'assign-new-pr-to-review' const botName = 'assign-new-pr-to-review'
@ -29,8 +29,7 @@ module.exports = (robot) => {
async function assignPullRequestToReview (context, robot) { async function assignPullRequestToReview (context, robot) {
const { github, payload } = context const { github, payload } = context
const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml'))
const ownerName = payload.repository.owner.login const repoInfo = { owner: payload.repository.owner.login, repo: payload.repository.name }
const repoName = payload.repository.name
const prNumber = payload.pull_request.number const prNumber = payload.pull_request.number
const projectBoardConfig = config ? config['project-board'] : null const projectBoardConfig = config ? config['project-board'] : null
@ -38,7 +37,7 @@ async function assignPullRequestToReview (context, robot) {
return 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 // Fetch repo projects
// TODO: The repo project and project column info should be cached // 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 projectBoardName = projectBoardConfig.name
const reviewColumnName = projectBoardConfig['review-column-name'] const reviewColumnName = projectBoardConfig['review-column-name']
try { try {
const ghprojectsPayload = await github.projects.getRepoProjects({ const ghprojectsPayload = await github.projects.getRepoProjects({ ...repoInfo, state: 'open' })
owner: ownerName,
repo: repoName,
state: 'open'
})
// Find 'Pipeline for QA' project // Find 'Pipeline for QA' project
const project = ghprojectsPayload.data.find(p => p.name === projectBoardName) const project = ghprojectsPayload.data.find(p => p.name === projectBoardName)
if (!project) { 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 return
} }
@ -74,11 +69,11 @@ async function assignPullRequestToReview (context, robot) {
robot.log.debug(`${botName} - Fetched ${column.name} column (${column.id})`) robot.log.debug(`${botName} - Fetched ${column.name} column (${column.id})`)
} catch (err) { } 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 return
} }
} catch (err) { } 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 return
} }

View File

@ -36,8 +36,7 @@ module.exports = (robot) => {
async function assignIssueToBountyAwaitingForApproval (context, robot, assign) { async function assignIssueToBountyAwaitingForApproval (context, robot, assign) {
const { github, payload } = context const { github, payload } = context
const ownerName = payload.repository.owner.login const repoInfo = { owner: payload.repository.owner.login, repo: payload.repository.name }
const repoName = payload.repository.name
const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml'))
const projectBoardConfig = config ? config['bounty-project-board'] : null const projectBoardConfig = config ? config['bounty-project-board'] : null
@ -52,9 +51,9 @@ async function assignIssueToBountyAwaitingForApproval (context, robot, assign) {
} }
if (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 { } 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 // Fetch org projects
@ -64,7 +63,7 @@ async function assignIssueToBountyAwaitingForApproval (context, robot, assign) {
const projectBoardName = projectBoardConfig.name const projectBoardName = projectBoardConfig.name
const approvalColumnName = projectBoardConfig['awaiting-approval-column-name'] const approvalColumnName = projectBoardConfig['awaiting-approval-column-name']
try { try {
const orgName = ownerName const orgName = repoInfo.owner
const ghprojectsPayload = await github.projects.getOrgProjects({ const ghprojectsPayload = await github.projects.getOrgProjects({
org: orgName, org: orgName,
@ -92,11 +91,11 @@ async function assignIssueToBountyAwaitingForApproval (context, robot, assign) {
robot.log.debug(`${botName} - Fetched ${column.name} column (${column.id})`) robot.log.debug(`${botName} - Fetched ${column.name} column (${column.id})`)
} catch (err) { } 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 return
} }
} catch (err) { } 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 return
} }

View File

@ -33,19 +33,18 @@ function registerForNewBounties (robot) {
async function notifyCollaborators (context, robot) { async function notifyCollaborators (context, robot) {
const { github, payload } = context const { github, payload } = context
const ownerName = payload.repository.owner.login const repoInfo = { owner: payload.repository.owner.login, repo: payload.repository.name }
const repoName = payload.repository.name
const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml'))
const bountyProjectBoardConfig = config ? config['bounty-project-board'] : null const bountyProjectBoardConfig = config ? config['bounty-project-board'] : null
const gitHubTeamConfig = config ? config['github-team'] : null const gitHubTeamConfig = config ? config['github-team'] : null
if (!bountyProjectBoardConfig) { 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 return
} }
if (!gitHubTeamConfig) { 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 return
} }
@ -55,9 +54,9 @@ async function notifyCollaborators (context, robot) {
return null 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 // Mention the project board owner as well, if configured
const bountyProjectBoardOwner = bountyProjectBoardConfig['owner'] const bountyProjectBoardOwner = bountyProjectBoardConfig['owner']
@ -82,15 +81,15 @@ function randomInt (low, high) {
} }
// Get the Slack IDs of the collaborators of this repo. // 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'] const teamSlug = gitHubTeamConfig['slug']
if (!teamSlug) { 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 return
} }
// Grab a list of collaborators to this repo, as an array of GitHub login usernames // 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) const team = teams.find(t => t.slug === teamSlug)
if (!team) { if (!team) {
robot.log.debug(`${botName} - GitHub team with slug ${teamSlug} was not found. Ignoring`) robot.log.debug(`${botName} - GitHub team with slug ${teamSlug} was not found. Ignoring`)

View File

@ -43,21 +43,19 @@ function executeTemplate (templateString, templateVars) {
async function greetNewContributor (context, robot) { async function greetNewContributor (context, robot) {
const { github, payload } = context const { github, payload } = context
const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml')) const config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml'))
const ownerName = payload.repository.owner.login const repoInfo = { owner: payload.repository.owner.login, repo: payload.repository.name }
const repoName = payload.repository.name const prInfo = { ...repoInfo, number: payload.pull_request.number }
const prNumber = payload.pull_request.number
const welcomeBotConfig = config ? config['welcome-bot'] : null const welcomeBotConfig = config ? config['welcome-bot'] : null
if (!welcomeBotConfig) { if (!welcomeBotConfig) {
return 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 { try {
const ghissuesPayload = await github.issues.getForRepo({ const ghissuesPayload = await github.issues.getForRepo({
owner: ownerName, ...repoInfo,
repo: repoName,
state: 'all', state: 'all',
creator: payload.pull_request.user.login creator: payload.pull_request.user.login
}) })
@ -65,30 +63,28 @@ async function greetNewContributor (context, robot) {
const userPullRequests = ghissuesPayload.data.filter(issue => issue.pull_request) const userPullRequests = ghissuesPayload.data.filter(issue => issue.pull_request)
if (userPullRequests.length === 1) { if (userPullRequests.length === 1) {
try { 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) { 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 { } else {
await github.issues.createComment({ await github.issues.createComment({
owner: ownerName, ...prInfo,
repo: repoName,
number: prNumber,
body: welcomeMessage body: welcomeMessage
}) })
} }
// Send message to Slack // 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) { } catch (err) {
if (err.code !== 404) { 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 { } 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) { } 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)
} }
} }

View File

@ -42,6 +42,7 @@ async function processChangedProjectCard (robot, context) {
return 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 config = await getConfig(context, 'github-bot.yml', defaultConfig(robot, '.github/github-bot.yml'))
const projectBoardConfig = config ? config['project-board'] : null const projectBoardConfig = config ? config['project-board'] : null
const automatedTestsConfig = config ? config['automated-tests'] : null const automatedTestsConfig = config ? config['automated-tests'] : null
@ -81,12 +82,10 @@ async function processChangedProjectCard (robot, context) {
return a[a.length + index] return a[a.length + index]
} }
let project
try { try {
const projectId = last(inTestColumn.project_url.split('/'), -1) const projectId = last(inTestColumn.project_url.split('/'), -1)
const projectPayload = await github.projects.getProject({ id: projectId }) const projectPayload = await github.projects.getProject({ id: projectId })
const project = projectPayload.data
project = projectPayload.data
if (project.name !== projectBoardName) { if (project.name !== projectBoardName) {
robot.log.trace(`${botName} - Card column name doesn't match watched column name, exiting`, project.name, projectBoardName) robot.log.trace(`${botName} - Card column name doesn't match watched column name, exiting`, project.name, projectBoardName)
return return
@ -99,52 +98,52 @@ async function processChangedProjectCard (robot, context) {
const prNumber = last(payload.project_card.content_url.split('/'), -1) const prNumber = last(payload.project_card.content_url.split('/'), -1)
const fullJobName = automatedTestsConfig['job-full-name'] 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 // Remove the PR from the pending PR list, if it is there
pendingPullRequests.delete(prNumber) pendingPullRequests.delete(prInfo.number)
try { try {
const state = await gitHubHelpers.getReviewApprovalState(github, robot, repoOwner, repoName, prNumber) const state = await gitHubHelpers.getReviewApprovalState(github, robot, prInfo)
switch (state) { switch (state) {
case 'unstable': case 'unstable':
case 'awaiting_reviewers': case 'awaiting_reviewers':
case 'changes_requested': case 'changes_requested':
pendingPullRequests.set(prNumber, { github: github, repoOwner: repoOwner, repoName: repoName, fullJobName: fullJobName }) pendingPullRequests.set(prInfo.number, { github: github, prInfo, fullJobName: fullJobName })
robot.log.debug(`${botName} - State is '${state}', adding to backlog to check periodically`, prNumber) robot.log.debug(`${botName} - State is '${state}', adding to backlog to check periodically`, prInfo)
return return
case 'failed': case 'failed':
robot.log.debug(`${botName} - State is '${state}', exiting`, prNumber) robot.log.debug(`${botName} - State is '${state}', exiting`, prInfo)
return return
case 'approved': case 'approved':
robot.log.debug(`${botName} - State is '${state}', proceeding`, prNumber) robot.log.debug(`${botName} - State is '${state}', proceeding`, prInfo)
break break
default: default:
robot.log.warn(`${botName} - State is '${state}', ignoring`, prNumber) robot.log.warn(`${botName} - State is '${state}', ignoring`, prInfo)
return return
} }
} catch (err) { } 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 return
} }
try { 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) { 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 { } 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) 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) { } 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`) robot.log.trace(`${botName} - Processing ${_pendingPullRequests.size} pending PRs`)
for (const kvp of _pendingPullRequests.entries()) { for (const { github, prInfo, fullJobName } of _pendingPullRequests.values()) {
const prNumber = kvp[0] await processPullRequest(github, robot, prInfo, fullJobName)
const { github, repoOwner, repoName, fullJobName } = kvp[1]
await processPullRequest(github, robot, repoOwner, repoName, prNumber, fullJobName)
} }
robot.log.trace(`${botName} - Finished processing ${_pendingPullRequests.size} pending PRs`) robot.log.trace(`${botName} - Finished processing ${_pendingPullRequests.size} pending PRs`)

View File

@ -3,18 +3,7 @@ const Slack = require('./lib/slack')
module.exports = async (robot) => { module.exports = async (robot) => {
console.log('Yay, the app was loaded!') console.log('Yay, the app was loaded!')
Slack(robot, slack => {}) await setupSlack(robot)
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()
})
})
robot['gitHubIdMapper'] = require('./lib/github-id-mapper')(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: // To get your app running against GitHub, see:
// https://probot.github.io/docs/development/ // 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()
})
})
}

View File

@ -11,10 +11,10 @@ module.exports.getPullRequestReviewStates = _getPullRequestReviewStates
module.exports.getReviewApprovalState = _getReviewApprovalState module.exports.getReviewApprovalState = _getReviewApprovalState
module.exports.getProjectCardForIssue = _getProjectCardForIssue module.exports.getProjectCardForIssue = _getProjectCardForIssue
async function _getPullRequestReviewStates (github, repoOwner, repoName, prNumber) { async function _getPullRequestReviewStates (github, prInfo) {
let finalReviewsMap = new Map() let finalReviewsMap = new Map()
const ghreviews = await github.paginate( 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) res => res.data)
for (var review of ghreviews) { for (var review of ghreviews) {
switch (review.state) { switch (review.state) {
@ -29,9 +29,9 @@ async function _getPullRequestReviewStates (github, repoOwner, repoName, prNumbe
return Array.from(finalReviewsMap.values()) return Array.from(finalReviewsMap.values())
} }
async function _getReviewApprovalState (github, robot, repoOwner, repoName, prNumber) { async function _getReviewApprovalState (github, robot, prInfo) {
// Get detailed pull request // 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 const pullRequest = pullRequestPayload.data
if (pullRequest.mergeable !== null && pullRequest.mergeable !== undefined && !pullRequest.mergeable) { if (pullRequest.mergeable !== null && pullRequest.mergeable !== undefined && !pullRequest.mergeable) {
robot.log.debug(`pullRequest.mergeable is ${pullRequest.mergeable}, considering as failed`) 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 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) robot.log.debug(finalReviews)
const approvedReviews = finalReviews.filter(reviewState => reviewState === 'APPROVED') const approvedReviews = finalReviews.filter(reviewState => reviewState === 'APPROVED')