@@ -9,9 +9,10 @@ import {
9
9
} from './index'
10
10
import { getPayloadFn } from './Check'
11
11
import createAuditService from '../service/AuditServiceCreator'
12
+ import { checkHandler as defaultCheckHandler } from '../handler/CheckHandler'
12
13
import { githubService as defaultGithubService } from '../service/GithubService'
13
14
import { pullRequestHandler as defaultPullRequestHandler } from '../handler/PullRequestHandler'
14
- import merge from 'lodash/merge '
15
+ import { findDeepInObj } from '../../common/util '
15
16
import { logger } from '../../common/debug'
16
17
const info = logger ( 'checkrunner' , 'info' )
17
18
const error = logger ( 'checkrunner' , 'error' )
@@ -27,12 +28,36 @@ function getTokens(dbRepo) {
27
28
return ( dbRepo . checks || [ ] ) . reduce ( ( agg , check ) => ( { [ check . type ] : check . token , ...agg } ) , { } )
28
29
}
29
30
31
+ /**
32
+ * Returns when this GH event was triggered based on payload.
33
+ *
34
+ * Necessary because there is no top-level timestamp in the payload for every event,
35
+ * we have to look into the event itself and check different properties. Not cool.
36
+ * So this naive implementation looks for properties /.+?_at/ with value /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/
37
+ * and parses them and returns the most current.
38
+ *
39
+ * This approach may now work well in 100% of the cases, but avoids that we forget to
40
+ * change it in the future when we support new events.
41
+ *
42
+ * @param payload
43
+ */
44
+ export function getTriggeredAt ( payload ) {
45
+ const endsWithAt = / ^ .+ ?_ a t $ /
46
+ const looksLikeDate = / \d { 4 } - \d { 2 } - \d { 2 } T \d { 2 } : \d { 2 } : \d { 2 } Z /
47
+ return findDeepInObj ( payload , key => endsWithAt . test ( key ) )
48
+ . filter ( ( [ _ , val ] ) => looksLikeDate . test ( val ) )
49
+ . map ( ( [ _ , val ] ) => Date . parse ( val ) )
50
+ . reduce ( ( mostCurrent , ts ) => Math . max ( mostCurrent , ts ) , 0 )
51
+ }
52
+
30
53
export default class CheckRunner {
31
54
constructor ( githubService = defaultGithubService ,
32
55
pullRequestHandler = defaultPullRequestHandler ,
56
+ checkHandler = defaultCheckHandler ,
33
57
auditService = createAuditService ( ) ) {
34
58
this . githubService = githubService
35
59
this . pullRequestHandler = pullRequestHandler
60
+ this . checkHandler = checkHandler
36
61
this . approval = new Approval ( this . githubService , this . pullRequestHandler , auditService )
37
62
this . autobranch = new Autobranch ( this . githubService )
38
63
this . commitMessage = new CommitMessage ( this . githubService )
@@ -109,40 +134,78 @@ export default class CheckRunner {
109
134
}
110
135
111
136
async handleGithubWebhook ( dbRepo , checkArgs ) {
112
- const { event} = checkArgs
137
+ const { event, payload , config } = checkArgs
113
138
const owner = dbRepo . json . owner . login
114
139
const name = dbRepo . json . name
115
140
const tokens = getTokens ( dbRepo )
116
- info ( `${ owner } /${ name } : Handling Github event ${ event } .${ checkArgs . payload . action } ` )
141
+ const start = Date . now ( )
142
+ const delay = start - getTriggeredAt ( payload )
143
+ info ( `${ owner } /${ name } : Handling Github event ${ event } .${ payload . action } ` )
117
144
118
145
if ( PullRequestLabels . isTriggeredBy ( event ) && tokens [ PullRequestLabels . TYPE ] ) {
119
146
info ( `${ owner } /${ name } : Executing check PullRequestLabels` )
120
- await this . pullRequestLabels . execute ( checkArgs . config , checkArgs . payload , tokens [ PullRequestLabels . TYPE ] )
147
+ await this . checkHandler . onExecutionStart ( dbRepo . id , PullRequestLabels . TYPE , delay )
148
+ try {
149
+ await this . pullRequestLabels . execute ( config , payload , tokens [ PullRequestLabels . TYPE ] )
150
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , PullRequestLabels . TYPE , Date . now ( ) - start , true )
151
+ } catch ( e ) {
152
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , PullRequestLabels . TYPE , Date . now ( ) - start , false )
153
+ }
121
154
}
122
155
123
156
if ( Specification . isTriggeredBy ( event ) && tokens [ Specification . TYPE ] ) {
124
157
info ( `${ owner } /${ name } : Executing check Specification` )
125
- await this . specification . execute ( checkArgs . config , checkArgs . payload , tokens [ Specification . TYPE ] )
158
+ await this . checkHandler . onExecutionStart ( dbRepo . id , Specification . TYPE , delay )
159
+ try {
160
+ await this . specification . execute ( config , payload , tokens [ Specification . TYPE ] )
161
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , Specification . TYPE , Date . now ( ) - start , true )
162
+ } catch ( e ) {
163
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , Specification . TYPE , Date . now ( ) - start , false )
164
+ }
126
165
}
127
166
128
167
if ( Approval . isTriggeredBy ( event ) && tokens [ Approval . TYPE ] ) {
129
168
info ( `${ owner } /${ name } : Executing check Approval` )
130
- await this . approval . execute ( checkArgs . config , event , checkArgs . payload , tokens [ Approval . TYPE ] , dbRepo . id )
169
+ await this . checkHandler . onExecutionStart ( dbRepo . id , Approval . TYPE , delay )
170
+ try {
171
+ await this . approval . execute ( config , event , payload , tokens [ Approval . TYPE ] , dbRepo . id )
172
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , Approval . TYPE , Date . now ( ) - start , true )
173
+ } catch ( e ) {
174
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , Approval . TYPE , Date . now ( ) - start , false )
175
+ }
131
176
}
132
177
133
178
if ( Autobranch . isTriggeredBy ( event ) && tokens [ Autobranch . TYPE ] ) {
134
179
info ( `${ owner } /${ name } : Executing check Autobranch` )
135
- await this . autobranch . execute ( checkArgs . config , checkArgs . payload , tokens [ Autobranch . TYPE ] )
180
+ await this . checkHandler . onExecutionStart ( dbRepo . id , Autobranch . TYPE , delay )
181
+ try {
182
+ await this . autobranch . execute ( config , payload , tokens [ Autobranch . TYPE ] )
183
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , Autobranch . TYPE , Date . now ( ) - start , true )
184
+ } catch ( e ) {
185
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , Autobranch . TYPE , Date . now ( ) - start , false )
186
+ }
136
187
}
137
188
138
189
if ( CommitMessage . isTriggeredBy ( event ) && tokens [ CommitMessage . TYPE ] ) {
139
190
info ( `${ owner } /${ name } : Executing check CommitMessage` )
140
- await this . commitMessage . execute ( checkArgs . config , checkArgs . payload , tokens [ CommitMessage . TYPE ] )
191
+ await this . checkHandler . onExecutionStart ( dbRepo . id , CommitMessage . TYPE , delay )
192
+ try {
193
+ await this . commitMessage . execute ( config , payload , tokens [ CommitMessage . TYPE ] )
194
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , CommitMessage . TYPE , Date . now ( ) - start , true )
195
+ } catch ( e ) {
196
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , CommitMessage . TYPE , Date . now ( ) - start , false )
197
+ }
141
198
}
142
199
143
200
if ( PullRequestTasks . isTriggeredBy ( event ) && tokens [ PullRequestTasks . TYPE ] ) {
144
201
info ( `${ owner } /${ name } : Executing check PullRequestTasks` )
145
- await this . pullRequestTasks . execute ( checkArgs . config , checkArgs . payload , tokens [ PullRequestTasks . TYPE ] )
202
+ await this . checkHandler . onExecutionStart ( dbRepo . id , PullRequestTasks . TYPE , delay )
203
+ try {
204
+ await this . pullRequestTasks . execute ( config , payload , tokens [ PullRequestTasks . TYPE ] )
205
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , PullRequestTasks . TYPE , Date . now ( ) - start , true )
206
+ } catch ( e ) {
207
+ await this . checkHandler . onExecutionEnd ( dbRepo . id , PullRequestTasks . TYPE , Date . now ( ) - start , false )
208
+ }
146
209
}
147
210
}
148
211
}
0 commit comments