1
1
import { IncomingHttpHeaders } from 'http' ;
2
2
import { Webhooks } from '@octokit/webhooks' ;
3
3
import { sendActionRequest } from '../sqs' ;
4
- import { CheckRunEvent } from '@octokit/webhooks-types' ;
4
+ import { CheckRunEvent , WorkflowJobEvent } from '@octokit/webhooks-types' ;
5
5
import { getParameterValue } from '../ssm' ;
6
6
7
- // Event type not available yet in SDK
8
- export interface WorkflowJob {
9
- action : 'queued' | 'created' | 'completed' ;
10
- workflow_job : {
11
- id : number ;
12
- labels : [ string ] ;
13
- } ;
14
- repository : {
15
- id : number ;
16
- name : string ;
17
- full_name : string ;
18
- owner : {
19
- login : string ;
20
- } ;
21
- } ;
22
- organization : {
23
- login : string ;
24
- } ;
25
- installation ?: {
26
- id ?: number ;
27
- } ;
28
- }
29
-
30
- export const handle = async ( headers : IncomingHttpHeaders , payload : any ) : Promise < number > => {
7
+ export const handle = async ( headers : IncomingHttpHeaders , body : string ) : Promise < number > => {
31
8
// ensure header keys lower case since github headers can contain capitals.
32
9
for ( const key in headers ) {
33
10
headers [ key . toLowerCase ( ) ] = headers [ key ] ;
34
11
}
35
12
36
- const signature = headers [ 'x-hub-signature' ] as string ;
37
- if ( ! signature ) {
38
- console . error ( "Github event doesn't have signature. This webhook requires a secret to be configured." ) ;
39
- return 500 ;
40
- }
41
-
42
- const secret = await getParameterValue ( process . env . ENVIRONMENT as string , 'github_app_webhook_secret' ) ;
13
+ const githubEvent = headers [ 'x-github-event' ] as string ;
43
14
44
- const webhooks = new Webhooks ( {
45
- secret : secret ,
46
- } ) ;
47
- if ( ! ( await webhooks . verify ( payload as string , signature ) ) ) {
48
- console . error ( 'Unable to verify signature!' ) ;
49
- return 401 ;
15
+ let status = await verifySignature ( githubEvent , headers [ 'x-hub-signature' ] as string , body ) ;
16
+ if ( status != 200 ) {
17
+ return status ;
50
18
}
19
+ const payload = JSON . parse ( body ) ;
20
+ console . info ( `Received Github event ${ githubEvent } from ${ payload . repository . full_name } ` ) ;
51
21
52
- const githubEvent = headers [ 'x-github-event' ] as string ;
53
-
54
- console . debug ( `Received Github event: "${ githubEvent } "` ) ;
22
+ if ( isRepoNotAllowed ( payload . repository . full_name ) ) {
23
+ console . error ( `Received event from unauthorized repository ${ payload . repository . full_name } ` ) ;
24
+ return 403 ;
25
+ }
55
26
56
- let status = 200 ;
57
27
if ( githubEvent == 'workflow_job' ) {
58
- status = await handleWorkflowJob ( JSON . parse ( payload ) as WorkflowJob , githubEvent ) ;
28
+ status = await handleWorkflowJob ( payload as WorkflowJobEvent , githubEvent ) ;
59
29
} else if ( githubEvent == 'check_run' ) {
60
- status = await handleCheckRun ( JSON . parse ( payload ) as CheckRunEvent , githubEvent ) ;
30
+ status = await handleCheckRun ( payload as CheckRunEvent , githubEvent ) ;
61
31
} else {
62
- console . debug ( 'Ignore event ' + githubEvent ) ;
32
+ console . warn ( `Ignoring unsupported event ${ githubEvent } ` ) ;
63
33
}
64
34
65
35
return status ;
66
36
} ;
67
37
68
- async function handleWorkflowJob ( body : WorkflowJob , githubEvent : string ) : Promise < number > {
69
- if ( isRepoNotAllowed ( body ) ) {
70
- console . error ( `Received event from unauthorized repository ${ body . repository . full_name } ` ) ;
71
- return 403 ;
38
+ async function verifySignature ( githubEvent : string , signature : string , body : string ) : Promise < number > {
39
+ if ( ! signature ) {
40
+ console . error ( "Github event doesn't have signature. This webhook requires a secret to be configured." ) ;
41
+ return 500 ;
42
+ }
43
+
44
+ const secret = await getParameterValue ( process . env . ENVIRONMENT as string , 'github_app_webhook_secret' ) ;
45
+
46
+ const webhooks = new Webhooks ( {
47
+ secret : secret ,
48
+ } ) ;
49
+ if ( ! ( await webhooks . verify ( body , signature ) ) ) {
50
+ console . error ( 'Unable to verify signature!' ) ;
51
+ return 401 ;
72
52
}
53
+ return 200 ;
54
+ }
73
55
56
+ async function handleWorkflowJob ( body : WorkflowJobEvent , githubEvent : string ) : Promise < number > {
74
57
const disableCheckWorkflowJobLabelsEnv = process . env . DISABLE_CHECK_WORKFLOW_JOB_LABELS || 'false' ;
75
58
const disableCheckWorkflowJobLabels = JSON . parse ( disableCheckWorkflowJobLabelsEnv ) as boolean ;
76
59
if ( ! disableCheckWorkflowJobLabels && ! canRunJob ( body ) ) {
@@ -91,15 +74,11 @@ async function handleWorkflowJob(body: WorkflowJob, githubEvent: string): Promis
91
74
installationId : installationId ,
92
75
} ) ;
93
76
}
77
+ console . info ( `Successfully queued job for ${ body . repository . full_name } ` ) ;
94
78
return 200 ;
95
79
}
96
80
97
81
async function handleCheckRun ( body : CheckRunEvent , githubEvent : string ) : Promise < number > {
98
- if ( isRepoNotAllowed ( body ) ) {
99
- console . error ( `Received event from unauthorized repository ${ body . repository . full_name } ` ) ;
100
- return 403 ;
101
- }
102
-
103
82
let installationId = body . installation ?. id ;
104
83
if ( installationId == null ) {
105
84
installationId = 0 ;
@@ -113,17 +92,18 @@ async function handleCheckRun(body: CheckRunEvent, githubEvent: string): Promise
113
92
installationId : installationId ,
114
93
} ) ;
115
94
}
95
+ console . info ( `Successfully queued job for ${ body . repository . full_name } ` ) ;
116
96
return 200 ;
117
97
}
118
98
119
- function isRepoNotAllowed ( body : WorkflowJob | CheckRunEvent ) : boolean {
99
+ function isRepoNotAllowed ( repo_full_name : string ) : boolean {
120
100
const repositoryWhiteListEnv = process . env . REPOSITORY_WHITE_LIST || '[]' ;
121
101
const repositoryWhiteList = JSON . parse ( repositoryWhiteListEnv ) as Array < string > ;
122
102
123
- return repositoryWhiteList . length > 0 && ! repositoryWhiteList . includes ( body . repository . full_name ) ;
103
+ return repositoryWhiteList . length > 0 && ! repositoryWhiteList . includes ( repo_full_name ) ;
124
104
}
125
105
126
- function canRunJob ( job : WorkflowJob ) : boolean {
106
+ function canRunJob ( job : WorkflowJobEvent ) : boolean {
127
107
const runnerLabelsEnv = process . env . RUNNER_LABELS || '[]' ;
128
108
const runnerLabels = new Set ( JSON . parse ( runnerLabelsEnv ) as Array < string > ) ;
129
109
0 commit comments