import { Probot } from 'probot' ; import { Octokit } from '@octokit/rest' ; import { logger } from 'gcf-utils' ; import { ConfigChecker , getConfig } from '@google-automations/bot-config-utils' ; import schema from './config-schema.json' ; import { ConfigurationOptions , WELL_KNOWN_CONFIGURATION_FILE , DEFAULT_CONFIGURATION , } from './config-constants' ; import { findPendingReleasePullRequests , triggerKokoroJob , markTriggered , markFailed , TRIGGERED_LABEL , PUBLISHED_LABEL , ALLOWED_ORGANIZATIONS , PullRequest , TAGGED_LABEL , cleanupPublished , } from './release-trigger' ; async function doTrigger ( octokit , pullRequest , token ) { const owner = pullRequest . base . repo . owner ?. login ; if ( ! owner ) { logger . error ( `no owner for ${ pullRequest . number }` ) ; return ; } try { await triggerKokoroJob ( pullRequest . html_url , token ) ; } catch ( e ) { await markFailed ( octokit , { owner , repo : pullRequest . base . repo . name , number : pullRequest . number , } ) ; } finally { await markTriggered ( octokit , { owner , repo : pullRequest . base . repo . name , number : pullRequest . number , } ) ; } } export = ( app ) => { app . on ( 'release.published' , async ( context ) => { const repository = context . payload . repository ; const repoUrl = repository . full_name ; const owner = repository . owner . login ; const repo = repository . name ; if ( ! ALLOWED_ORGANIZATIONS . includes ( owner ) ) { logger . info ( `release-trigger not allowed for owner: ${ owner }` ) ; return ; } const remoteConfiguration = await getConfig < ConfigurationOptions > ( context . octokit , owner , repo , WELL_KNOWN_CONFIGURATION_FILE , { schema : schema } ) ; if ( ! remoteConfiguration ) { logger . info ( `release-trigger not configured for ${ repoUrl }` ) ; return ; } const configuration = { ... DEFAULT_CONFIGURATION , ... remoteConfiguration , } ; if ( ! configuration . enabled ) { logger . info ( `release-trigger not enabled for ${ repoUrl }` ) ; return ; } const releasePullRequests = await findPendingReleasePullRequests ( context . octokit , { owner : repository . owner . login , repo : repository . name } ) ; const { token } = ( await context . octokit . auth ( { type : 'installation' } ) ) as { token : string ; } ; for ( const pullRequest of releasePullRequests ) { if ( ! pullRequest . labels . some ( label => { return label . name === TAGGED_LABEL ; } ) ) { logger . info ( 'ignore pull non-tagged pull request' ) ; continue ; } await doTrigger ( context . octokit , pullRequest , token ) ; } } ) ; app . on ( 'pull_request.labeled' , async ( context ) => { const repository = context . payload . repository ; const repoUrl = repository . full_name ; const owner = repository . owner . login ; const repo = repository . name ; if ( ! ALLOWED_ORGANIZATIONS . includes ( owner ) ) { logger . info ( `release-trigger not allowed for owner: ${ owner }` ) ; return ; } const remoteConfiguration = await getConfig < ConfigurationOptions > ( context . octokit , owner , repo , WELL_KNOWN_CONFIGURATION_FILE , { schema : schema } ) ; if ( ! remoteConfiguration ) { logger . info ( `release-trigger not configured for ${ repoUrl }` ) ; return ; } const configuration = { ... DEFAULT_CONFIGURATION , ... remoteConfiguration , } ; if ( ! configuration . enabled ) { logger . info ( `release-trigger not enabled for ${ repoUrl }` ) ; return ; } const label = context . payload . label ?. name ; if ( label !== PUBLISHED_LABEL ) { logger . info ( `ignoring non-published label: ${ label }` ) ; return ; } await cleanupPublished ( context . octokit , { owner , repo , number : context . payload . pull_request . number , } ) ; } ) ; app . on ( 'pull_request.unlabeled' , async ( context ) => { const repository = context . payload . repository ; const repoUrl = repository . full_name ; const owner = repository . owner . login ; const repo = repository . name ; if ( ! ALLOWED_ORGANIZATIONS . includes ( owner ) ) { logger . info ( `release-trigger not allowed for owner: ${ owner }` ) ; return ; } const remoteConfiguration = await getConfig < ConfigurationOptions > ( context . octokit , owner , repo , WELL_KNOWN_CONFIGURATION_FILE , { schema : schema } ) ; if ( ! remoteConfiguration ) { logger . info ( `release-trigger not configured for ${ repoUrl }` ) ; return ; } const configuration = { ... DEFAULT_CONFIGURATION , ... remoteConfiguration , } ; if ( ! configuration . enabled ) { logger . info ( `release-trigger not enabled for ${ repoUrl }` ) ; return ; } const label = context . payload . label ?. name ; if ( label !== TRIGGERED_LABEL ) { logger . info ( `ignoring non-autorelease label: ${ label }` ) ; return ; } if ( ! context . payload . pull_request . labels . some ( label => { return label . name === TAGGED_LABEL ; } ) ) { logger . info ( 'ignore pull non-tagged pull request' ) ; return ; } const { token } = ( await context . octokit . auth ( { type : 'installation' } ) ) as { token : string ; } ; await doTrigger ( context . octokit , context . payload . pull_request , token ) ; } ) ; app . on ( [ 'pull_request.opened' , 'pull_request.synchronize' ] , async ( context ) => { const { owner , repo } = context . repo ( ) ; if ( ! ALLOWED_ORGANIZATIONS . includes ( owner ) ) { logger . info ( `release-trigger not allowed for owner: ${ owner }` ) ; return ; } const configChecker = new ConfigChecker < ConfigurationOptions > ( schema , WELL_KNOWN_CONFIGURATION_FILE ) ; await configChecker . validateConfigChanges ( context . octokit , owner , repo , context . payload . pull_request . head . sha , context . payload . pull_request . number ) ; } ) ; } ;