status-github-bot/bot_scripts/bounty-awaiting-approval-sl...

121 lines
4.4 KiB
JavaScript

// Description:
// Script that listens for issues with the label 'bounty-awaiting-approval'
// and notifies the collaborators on Slack.
//
// Dependencies:
// github: "^13.1.0"
// hashset: "0.0.6"
// probot-config: "^0.1.0"
// probot-slack-status: "^0.2.2"
//
// Author:
// Max Tyrrell (ImFeelingDucky/mac/yung_mac)
const Slack = require('probot-slack-status')
const getConfig = require('probot-config')
const HashSet = require('hashset')
const defaultConfig = require('../lib/config')
const slackHelper = require('../lib/slack')
const botName = 'bounty-awaiting-approval-slack-ping'
module.exports = (robot, getSlackMentionFromGitHubId) => {
Slack(robot, (slack) => {
robot.log.trace(`${botName} - Connected to Slack`)
registerForNewBounties(robot, slack, getSlackMentionFromGitHubId)
})
}
function registerForNewBounties (robot, slackClient, getSlackMentionFromGitHubId) {
robot.on('issues.labeled', async context => {
// Make sure we don't listen to our own messages
if (context.isBot) return null
await notifyCollaborators(context, robot, slackClient, getSlackMentionFromGitHubId)
})
}
async function notifyCollaborators (context, robot, slackClient, getSlackMentionFromGitHubId) {
const { github, payload } = context
const ownerName = payload.repository.owner.login
const repoName = 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`)
return
}
if (!gitHubTeamConfig) {
robot.log.debug(`${botName} - GitHub team not configured in repo ${ownerName}/${repoName}, ignoring`)
return
}
const watchedLabelName = bountyProjectBoardConfig['awaiting-approval-label-name']
if (payload.label.name !== watchedLabelName) {
robot.log.debug(`${botName} - ${payload.label.name} doesn't match watched ${watchedLabelName} label. Ignoring`)
return null
}
robot.log(`${botName} - issue #${payload.issue.number} on ${ownerName}/${repoName} was labeled as a bounty awaiting approval. Pinging slack...`)
const slackCollaborators = await getSlackCollaborators(ownerName, repoName, github, robot, gitHubTeamConfig, getSlackMentionFromGitHubId)
// Mention the project board owner as well, if configured
const bountyProjectBoardOwner = bountyProjectBoardConfig['owner']
if (bountyProjectBoardOwner) {
const slackUserMention = getSlackMentionFromGitHubId(bountyProjectBoardOwner)
if (slackUserMention) {
slackCollaborators.push(slackUserMention)
}
}
// Send message to Slack
slackHelper.sendMessage(
robot,
slackClient,
config.slack.notification.room,
`New bounty awaiting approval: ${payload.issue.html_url}
/cc ${slackCollaborators.values().join(', ')}`
)
}
function randomInt (low, high) {
return Math.floor(Math.random() * (high - low) + low)
}
// Get the Slack IDs of the collaborators of this repo.
async function getSlackCollaborators (ownerName, repoName, github, robot, gitHubTeamConfig, getSlackMentionFromGitHubId) {
const teamSlug = gitHubTeamConfig['slug']
if (!teamSlug) {
robot.log.debug(`${botName} - GitHub team slug not configured in repo ${ownerName}/${repoName}, 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 team = teams.find(t => t.slug === teamSlug)
if (!team) {
robot.log.debug(`${botName} - GitHub team with slug ${teamSlug} was not found. Ignoring`)
return
}
const teamMembers = await github.paginate(github.orgs.getTeamMembers({id: team.id, per_page: 100}), res => res.data)
// Create an array of Slack usernames from GitHub usernames
const slackUsers = teamMembers.map(u => u.login).map(getSlackMentionFromGitHubId).filter(id => id)
const randomTeamMemberLimit = 2
const selectedSlackUsers = new HashSet()
while (selectedSlackUsers.length < randomTeamMemberLimit || selectedSlackUsers.length < slackUsers.length) {
const slackUser = slackUsers[randomInt(0, slackUsers.length)]
selectedSlackUsers.add(slackUser)
}
return selectedSlackUsers
}