2018-01-30 14:57:16 +00:00
// Description:
// Script that listens for issues with the label 'bounty-awaiting-approval'
// and notifies the collaborators on Slack.
//
// Dependencies:
// github: "^13.1.0"
2018-02-08 12:35:07 +00:00
// hashset: "0.0.6"
2018-01-30 14:57:16 +00:00
// probot-config: "^0.1.0"
//
// Author:
// Max Tyrrell (ImFeelingDucky/mac/yung_mac)
2018-02-08 12:09:59 +00:00
const getConfig = require ( 'probot-config' )
2018-02-08 12:35:07 +00:00
const HashSet = require ( 'hashset' )
2018-02-08 12:09:59 +00:00
2018-01-30 14:57:16 +00:00
const defaultConfig = require ( '../lib/config' )
const slackHelper = require ( '../lib/slack' )
2018-02-13 14:51:00 +00:00
const botName = 'bounty-awaiting-approval-slack-ping'
2018-01-30 14:57:16 +00:00
2018-02-14 23:57:46 +00:00
module . exports = ( robot ) => {
registerForNewBounties ( robot )
2018-01-30 14:57:16 +00:00
}
2018-02-14 23:57:46 +00:00
function registerForNewBounties ( robot ) {
2018-01-30 14:57:16 +00:00
robot . on ( 'issues.labeled' , async context => {
// Make sure we don't listen to our own messages
if ( context . isBot ) return null
2018-02-14 23:57:46 +00:00
await notifyCollaborators ( context , robot )
2018-01-30 14:57:16 +00:00
} )
}
2018-02-14 23:57:46 +00:00
async function notifyCollaborators ( context , robot ) {
2018-01-30 14:57:16 +00:00
const { github , payload } = context
2018-02-16 20:35:49 +00:00
const repoInfo = { owner : payload . repository . owner . login , repo : payload . repository . name }
2018-02-08 12:09:59 +00:00
const config = await getConfig ( context , 'github-bot.yml' , defaultConfig ( robot , '.github/github-bot.yml' ) )
2018-02-08 12:35:07 +00:00
const bountyProjectBoardConfig = config ? config [ 'bounty-project-board' ] : null
const gitHubTeamConfig = config ? config [ 'github-team' ] : null
2018-01-30 14:57:16 +00:00
2018-02-08 12:09:59 +00:00
if ( ! bountyProjectBoardConfig ) {
2018-02-16 20:35:49 +00:00
robot . log . debug ( ` ${ botName } - Bounty project board not configured in repo ${ repoInfo . owner } / ${ repoInfo . repo } , ignoring ` )
2018-02-08 12:35:07 +00:00
return
}
if ( ! gitHubTeamConfig ) {
2018-02-16 20:35:49 +00:00
robot . log . debug ( ` ${ botName } - GitHub team not configured in repo ${ repoInfo . owner } / ${ repoInfo . repo } , ignoring ` )
2018-02-08 09:11:11 +00:00
return
}
2018-02-08 12:09:59 +00:00
const watchedLabelName = bountyProjectBoardConfig [ 'awaiting-approval-label-name' ]
2018-01-30 14:57:16 +00:00
if ( payload . label . name !== watchedLabelName ) {
2018-03-14 13:24:11 +00:00
robot . log . debug ( ` ${ botName } - ' ${ payload . label . name } ' doesn't match watched ' ${ watchedLabelName } ' label. Ignoring ` )
2018-01-30 14:57:16 +00:00
return null
}
2018-02-16 20:35:49 +00:00
robot . log ( ` ${ botName } - issue # ${ payload . issue . number } on ${ repoInfo . owner } / ${ repoInfo . repo } was labeled as a bounty awaiting approval. Pinging slack... ` )
2018-01-30 14:57:16 +00:00
2018-02-16 20:35:49 +00:00
const slackCollaborators = await getSlackCollaborators ( repoInfo , github , robot , gitHubTeamConfig )
2018-02-08 12:35:07 +00:00
// Mention the project board owner as well, if configured
const bountyProjectBoardOwner = bountyProjectBoardConfig [ 'owner' ]
if ( bountyProjectBoardOwner ) {
2018-02-14 23:57:46 +00:00
const slackUserMention = robot . gitHubIdMapper . getSlackMentionFromGitHubId ( bountyProjectBoardOwner )
2018-02-08 12:35:07 +00:00
if ( slackUserMention ) {
slackCollaborators . push ( slackUserMention )
}
}
2018-01-30 14:57:16 +00:00
// Send message to Slack
slackHelper . sendMessage (
robot ,
config . slack . notification . room ,
2018-02-07 10:58:50 +00:00
` New bounty awaiting approval: ${ payload . issue . html _url }
2018-02-08 12:35:07 +00:00
/ c c $ { s l a c k C o l l a b o r a t o r s . v a l u e s ( ) . j o i n ( ' , ' ) } `
2018-01-30 14:57:16 +00:00
)
}
2018-02-08 12:35:07 +00:00
function randomInt ( low , high ) {
return Math . floor ( Math . random ( ) * ( high - low ) + low )
}
2018-02-06 11:17:58 +00:00
// Get the Slack IDs of the collaborators of this repo.
2018-02-16 20:35:49 +00:00
async function getSlackCollaborators ( repoInfo , github , robot , gitHubTeamConfig ) {
2018-02-08 12:35:07 +00:00
const teamSlug = gitHubTeamConfig [ 'slug' ]
if ( ! teamSlug ) {
2018-02-16 20:35:49 +00:00
robot . log . debug ( ` ${ botName } - GitHub team slug not configured in repo ${ repoInfo . owner } / ${ repoInfo . repo } , ignoring ` )
2018-02-08 12:35:07 +00:00
return
}
2018-01-30 14:57:16 +00:00
// Grab a list of collaborators to this repo, as an array of GitHub login usernames
2018-02-16 20:35:49 +00:00
const teams = await github . paginate ( github . orgs . getTeams ( { org : repoInfo . owner } ) , res => res . data )
2018-02-08 12:35:07 +00:00
const team = teams . find ( t => t . slug === teamSlug )
if ( ! team ) {
2018-02-13 14:51:00 +00:00
robot . log . debug ( ` ${ botName } - GitHub team with slug ${ teamSlug } was not found. Ignoring ` )
2018-02-08 12:35:07 +00:00
return
}
const teamMembers = await github . paginate ( github . orgs . getTeamMembers ( { id : team . id , per _page : 100 } ) , res => res . data )
2018-01-30 14:57:16 +00:00
// Create an array of Slack usernames from GitHub usernames
2018-02-14 23:57:46 +00:00
const gitHubUsers = teamMembers . map ( u => u . login )
const slackUsers = new HashSet ( )
for ( const gitHubUser of gitHubUsers ) {
const id = await robot . gitHubIdMapper . getSlackMentionFromGitHubId ( gitHubUser )
if ( id ) {
slackUsers . add ( id )
}
}
// Select 2 random Slack team members
2018-02-08 12:35:07 +00:00
const randomTeamMemberLimit = 2
const selectedSlackUsers = new HashSet ( )
2018-02-14 23:57:46 +00:00
while ( selectedSlackUsers . size ( ) < randomTeamMemberLimit || selectedSlackUsers . size ( ) < slackUsers . size ( ) ) {
const slackUser = slackUsers [ randomInt ( 0 , slackUsers . size ( ) ) ]
2018-02-08 12:35:07 +00:00
selectedSlackUsers . add ( slackUser )
}
return selectedSlackUsers
2018-01-30 14:57:16 +00:00
}