1
1
import { Octokit } from '@octokit/rest' ;
2
- import { GitHubPr , Review } from "./github" ;
2
+ import { GitHubComment , GitHubPr , Review } from "./github" ;
3
3
4
4
export const PR_FROM_MAIN_ERROR = 'Pull requests from `main` branch of a fork cannot be accepted. Please reopen this contribution from another branch on your fork. For more information, see https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md#step-4-pull-request.' ;
5
5
@@ -96,25 +96,29 @@ export class PullRequestLinterBase {
96
96
const pr = await this . pr ( ) ;
97
97
98
98
for ( const label of actions . removeLabels ?? [ ] ) {
99
- this . removeLabel ( label , pr ) ;
99
+ await this . removeLabel ( label , pr ) ;
100
100
}
101
101
102
102
for ( const label of actions . addLabels ?? [ ] ) {
103
- this . addLabel ( label , pr ) ;
103
+ await this . addLabel ( label , pr ) ;
104
+ }
105
+
106
+ for ( const comment of actions . deleteComments ?? [ ] ) {
107
+ await this . deleteComment ( comment ) ;
104
108
}
105
109
106
110
if ( actions . dismissPreviousReview || actions . requestChanges ) {
107
111
if ( actions . dismissPreviousReview && actions . requestChanges ) {
108
112
throw new Error ( `It does not make sense to supply both dismissPreviousReview and requestChanges: ${ JSON . stringify ( actions ) } ` ) ;
109
113
}
110
114
111
- const existingReviews = await this . findExistingPRLinterReview ( ) ;
115
+ const existingReviews = await this . findExistingPRLinterReviews ( ) ;
112
116
113
117
if ( actions . dismissPreviousReview ) {
114
- this . dismissPRLinterReviews ( existingReviews , 'passing' ) ;
118
+ await this . dismissPRLinterReviews ( existingReviews , 'passing' ) ;
115
119
}
116
120
if ( actions . requestChanges ) {
117
- this . createOrUpdatePRLinterReview ( actions . requestChanges . failures , actions . requestChanges . exemptionRequest , existingReviews ) ;
121
+ await this . createOrUpdatePRLinterReview ( actions . requestChanges . failures , actions . requestChanges . exemptionRequest , existingReviews ) ;
118
122
}
119
123
}
120
124
}
@@ -150,7 +154,14 @@ export class PullRequestLinterBase {
150
154
151
155
for ( const existingReview of existingReviews ?? [ ] ) {
152
156
try {
153
- console . log ( 'Dismissing review' ) ;
157
+ console . log ( `👉 Dismissing review ${ existingReview . id } ` ) ;
158
+ // Make sure to update the old review texts. Dismissing won't do that,
159
+ // and having multiple messages in place is confusing.
160
+ await this . client . pulls . updateReview ( {
161
+ ...this . prParams ,
162
+ review_id : existingReview . id ,
163
+ body : '(This review is outdated)' ,
164
+ } ) ;
154
165
await this . client . pulls . dismissReview ( {
155
166
...this . prParams ,
156
167
review_id : existingReview . id ,
@@ -167,11 +178,19 @@ export class PullRequestLinterBase {
167
178
* Finds existing review, if present
168
179
* @returns Existing review, if present
169
180
*/
170
- private async findExistingPRLinterReview ( ) : Promise < Review [ ] > {
181
+ private async findExistingPRLinterReviews ( ) : Promise < Review [ ] > {
171
182
const reviews = await this . client . paginate ( this . client . pulls . listReviews , this . prParams ) ;
172
183
return reviews . filter ( ( review ) => review . user ?. login === this . linterLogin && review . state !== 'DISMISSED' ) ;
173
184
}
174
185
186
+ /**
187
+ * Return all existing comments made by the PR linter
188
+ */
189
+ public async findExistingPRLinterComments ( ) : Promise < GitHubComment [ ] > {
190
+ const comments = await this . client . paginate ( this . client . issues . listComments , this . issueParams ) ;
191
+ return comments . filter ( ( x ) => x . user ?. login === this . linterLogin && x . body ?. includes ( 'pull request linter' ) ) ;
192
+ }
193
+
175
194
/**
176
195
* Creates a new review and comment for first run with failure or creates a new comment with new failures for existing reviews.
177
196
*
@@ -199,22 +218,22 @@ export class PullRequestLinterBase {
199
218
const body = paras . join ( '\n\n' ) ;
200
219
201
220
// Dismiss every review except the last one
202
- this . dismissPRLinterReviews ( ( existingReviews ?? [ ] ) . slice ( 0 , - 1 ) , 'stale' ) ;
221
+ await this . dismissPRLinterReviews ( ( existingReviews ?? [ ] ) . slice ( 0 , - 1 ) , 'stale' ) ;
203
222
204
223
// Update the last review
205
224
const existingReview = ( existingReviews ?? [ ] ) . slice ( - 1 ) [ 0 ] ;
206
225
207
226
if ( ! existingReview ) {
208
- console . log ( 'Creating review' ) ;
227
+ console . log ( '👉 Creating new request-changes review' ) ;
209
228
await this . client . pulls . createReview ( {
210
229
...this . prParams ,
211
230
event : 'REQUEST_CHANGES' ,
212
231
body,
213
232
} ) ;
214
233
} else if ( existingReview . body !== body && existingReview . state === 'CHANGES_REQUESTED' ) {
215
234
// State is good but body is wrong
216
- console . log ( ' Updating review' ) ;
217
- this . client . pulls . updateReview ( {
235
+ console . log ( `👉 Updating existing request-changes review: ${ existingReview . id } ` ) ;
236
+ await this . client . pulls . updateReview ( {
218
237
...this . prParams ,
219
238
review_id : existingReview . id ,
220
239
body,
@@ -230,8 +249,8 @@ export class PullRequestLinterBase {
230
249
+ '(this setting is enabled by default for personal accounts, and cannot be enabled for organization owned accounts). '
231
250
+ 'The reason for this is that our automation needs to synchronize your branch with our main after it has been approved, '
232
251
+ 'and we cannot do that if we cannot push to your branch.'
233
- console . log ( 'Closing pull request' ) ;
234
252
253
+ console . log ( '👉 Closing pull request' ) ;
235
254
await this . client . issues . createComment ( {
236
255
...this . issueParams ,
237
256
body : errorMessageBody ,
@@ -244,14 +263,27 @@ export class PullRequestLinterBase {
244
263
}
245
264
}
246
265
266
+ /**
267
+ * Delete a comment
268
+ */
269
+ private async deleteComment ( comment : GitHubComment ) {
270
+ console . log ( `👉 Deleting comment ${ comment . id } ` ) ;
271
+ await this . client . issues . deleteComment ( {
272
+ ...this . issueParams ,
273
+ comment_id : comment . id ,
274
+ } ) ;
275
+ }
276
+
247
277
private formatErrors ( errors : string [ ] ) {
248
278
return errors . map ( e => ` ❌ ${ e } ` ) . join ( '\n' ) ;
249
279
}
250
280
251
- private addLabel ( label : string , pr : Pick < GitHubPr , 'labels' | 'number' > ) {
281
+ private async addLabel ( label : string , pr : Pick < GitHubPr , 'labels' | 'number' > ) {
252
282
// already has label, so no-op
253
283
if ( pr . labels . some ( l => l . name === label ) ) { return ; }
254
- this . client . issues . addLabels ( {
284
+
285
+ console . log ( `👉 Add label ${ label } ` ) ;
286
+ await this . client . issues . addLabels ( {
255
287
issue_number : pr . number ,
256
288
owner : this . prParams . owner ,
257
289
repo : this . prParams . repo ,
@@ -261,10 +293,12 @@ export class PullRequestLinterBase {
261
293
} ) ;
262
294
}
263
295
264
- private removeLabel ( label : string , pr : Pick < GitHubPr , 'labels' | 'number' > ) {
296
+ private async removeLabel ( label : string , pr : Pick < GitHubPr , 'labels' | 'number' > ) {
265
297
// does not have label, so no-op
266
298
if ( ! pr . labels . some ( l => l . name === label ) ) { return ; }
267
- this . client . issues . removeLabel ( {
299
+
300
+ console . log ( `👉 Remove label ${ label } ` ) ;
301
+ await this . client . issues . removeLabel ( {
268
302
issue_number : pr . number ,
269
303
owner : this . prParams . owner ,
270
304
repo : this . prParams . repo ,
@@ -294,6 +328,11 @@ export interface LinterActions {
294
328
*/
295
329
removeLabels ?: string [ ] ;
296
330
331
+ /**
332
+ * Delete the given comments
333
+ */
334
+ deleteComments ?: GitHubComment [ ] ;
335
+
297
336
/**
298
337
* Post a "request changes" review
299
338
*/
@@ -313,6 +352,7 @@ export function mergeLinterActions(a: LinterActions, b: LinterActions): LinterAc
313
352
addLabels : nonEmpty ( [ ...( a . addLabels ?? [ ] ) , ...( b . addLabels ?? [ ] ) ] ) ,
314
353
removeLabels : nonEmpty ( [ ...( a . removeLabels ?? [ ] ) , ...( b . removeLabels ?? [ ] ) ] ) ,
315
354
requestChanges : b . requestChanges ?? a . requestChanges ,
355
+ deleteComments : nonEmpty ( [ ...( a . deleteComments ?? [ ] ) , ...( b . deleteComments ?? [ ] ) ] ) ,
316
356
dismissPreviousReview : b . dismissPreviousReview ?? a . dismissPreviousReview ,
317
357
} ;
318
358
}
0 commit comments