1
1
use crate :: PgDbClient ;
2
2
use crate :: bors:: comment:: { build_failed_comment, try_build_succeeded_comment} ;
3
3
use crate :: bors:: event:: { WorkflowRunCompleted , WorkflowRunStarted } ;
4
+ use crate :: bors:: handlers:: TRY_BRANCH_NAME ;
4
5
use crate :: bors:: handlers:: is_bors_observed_branch;
5
6
use crate :: bors:: handlers:: labels:: handle_label_trigger;
6
7
use crate :: bors:: merge_queue:: AUTO_BRANCH_NAME ;
@@ -184,21 +185,26 @@ async fn maybe_complete_build(
184
185
let has_failure = db_workflow_runs
185
186
. iter ( )
186
187
. any ( |check| matches ! ( check. status, WorkflowStatus :: Failure ) ) ;
187
-
188
- let ( status, trigger) = if has_failure {
189
- ( BuildStatus :: Failure , LabelTrigger :: TryBuildFailed )
190
- } else {
191
- ( BuildStatus :: Success , LabelTrigger :: TryBuildSucceeded )
188
+ let build_succeeded = !has_failure;
189
+ let pr_num = pr. number ;
190
+ let branch = payload. branch . as_str ( ) ;
191
+
192
+ let ( status, trigger) = match ( branch, build_succeeded) {
193
+ ( TRY_BRANCH_NAME , true ) => ( BuildStatus :: Success , LabelTrigger :: TryBuildSucceeded ) ,
194
+ ( TRY_BRANCH_NAME , false ) => ( BuildStatus :: Failure , LabelTrigger :: TryBuildFailed ) ,
195
+ ( AUTO_BRANCH_NAME , true ) => ( BuildStatus :: Success , LabelTrigger :: AutoBuildSucceeded ) ,
196
+ ( AUTO_BRANCH_NAME , false ) => ( BuildStatus :: Failure , LabelTrigger :: AutoBuildFailed ) ,
197
+ _ => unreachable ! ( "Branch should be bors observed branch" ) ,
192
198
} ;
193
- db. update_build_status ( & build, status) . await ?;
194
199
195
- handle_label_trigger ( repo, pr. number , trigger) . await ?;
200
+ db. update_build_status ( & build, status) . await ?;
201
+ handle_label_trigger ( repo, pr_num, trigger) . await ?;
196
202
197
203
if let Some ( check_run_id) = build. check_run_id {
198
- let ( status, conclusion) = if has_failure {
199
- ( CheckRunStatus :: Completed , Some ( CheckRunConclusion :: Failure ) )
200
- } else {
204
+ let ( status, conclusion) = if build_succeeded {
201
205
( CheckRunStatus :: Completed , Some ( CheckRunConclusion :: Success ) )
206
+ } else {
207
+ ( CheckRunStatus :: Completed , Some ( CheckRunConclusion :: Failure ) )
202
208
} ;
203
209
204
210
if let Err ( error) = repo
@@ -212,10 +218,21 @@ async fn maybe_complete_build(
212
218
213
219
db_workflow_runs. sort_by ( |a, b| a. name . cmp ( & b. name ) ) ;
214
220
215
- let message = if !has_failure {
216
- tracing:: info!( "Build succeeded" ) ;
217
- try_build_succeeded_comment ( & db_workflow_runs, payload. commit_sha , & build)
221
+ let comment_opt = if build_succeeded {
222
+ tracing:: info!( "Build succeeded for PR {pr_num}" ) ;
223
+
224
+ if branch == TRY_BRANCH_NAME {
225
+ Some ( try_build_succeeded_comment (
226
+ & db_workflow_runs,
227
+ payload. commit_sha ,
228
+ & build,
229
+ ) )
230
+ } else {
231
+ None
232
+ }
218
233
} else {
234
+ tracing:: info!( "Build failed for PR {pr_num}" ) ;
235
+
219
236
// Download failed jobs
220
237
let mut workflow_runs: Vec < FailedWorkflowRun > = vec ! [ ] ;
221
238
for workflow_run in db_workflow_runs {
@@ -235,10 +252,12 @@ async fn maybe_complete_build(
235
252
} )
236
253
}
237
254
238
- tracing:: info!( "Build failed" ) ;
239
- build_failed_comment ( repo. repository ( ) , workflow_runs)
255
+ Some ( build_failed_comment ( repo. repository ( ) , workflow_runs) )
240
256
} ;
241
- repo. client . post_comment ( pr. number , message) . await ?;
257
+
258
+ if let Some ( comment) = comment_opt {
259
+ repo. client . post_comment ( pr_num, comment) . await ?;
260
+ }
242
261
243
262
// Trigger merge queue when an auto build completes
244
263
if payload. branch == AUTO_BRANCH_NAME {
@@ -273,10 +292,24 @@ async fn get_failed_jobs(
273
292
274
293
#[ cfg( test) ]
275
294
mod tests {
276
- use crate :: database:: WorkflowStatus ;
295
+ use octocrab:: params:: checks:: { CheckRunConclusion , CheckRunStatus } ;
296
+
297
+ use crate :: bors:: merge_queue:: AUTO_BUILD_CHECK_RUN_NAME ;
277
298
use crate :: database:: operations:: get_all_workflows;
299
+ use crate :: database:: { BuildStatus , WorkflowStatus } ;
278
300
use crate :: tests:: BorsTester ;
279
- use crate :: tests:: mocks:: { Branch , WorkflowEvent , WorkflowRunData , run_test} ;
301
+ use crate :: tests:: mocks:: {
302
+ BorsBuilder , Branch , GitHubState , WorkflowEvent , WorkflowRunData , default_pr_number,
303
+ run_test,
304
+ } ;
305
+
306
+ fn gh_state_with_merge_queue ( ) -> GitHubState {
307
+ GitHubState :: default ( ) . with_default_config (
308
+ r#"
309
+ merge_queue_enabled = true
310
+ "# ,
311
+ )
312
+ }
280
313
281
314
#[ sqlx:: test]
282
315
async fn workflow_started_unknown_build ( pool : sqlx:: PgPool ) {
@@ -425,4 +458,156 @@ mod tests {
425
458
} )
426
459
. await ;
427
460
}
461
+
462
+ #[ sqlx:: test]
463
+ async fn auto_build_success_updates_check_run ( pool : sqlx:: PgPool ) {
464
+ BorsBuilder :: new ( pool)
465
+ . github ( gh_state_with_merge_queue ( ) )
466
+ . run_test ( async |tester| {
467
+ tester. post_comment ( "@bors r+" ) . await ?;
468
+ tester. expect_comments ( 1 ) . await ;
469
+ tester. process_merge_queue ( ) . await ;
470
+ tester. expect_comments ( 1 ) . await ;
471
+
472
+ tester. workflow_full_success ( tester. auto_branch ( ) ) . await ?;
473
+ tester. expect_comments ( 1 ) . await ;
474
+ tester. expect_check_run (
475
+ & tester. default_pr ( ) . await . get_gh_pr ( ) . head_sha ,
476
+ AUTO_BUILD_CHECK_RUN_NAME ,
477
+ AUTO_BUILD_CHECK_RUN_NAME ,
478
+ CheckRunStatus :: Completed ,
479
+ Some ( CheckRunConclusion :: Success ) ,
480
+ ) ;
481
+ Ok ( ( ) )
482
+ } )
483
+ . await ;
484
+ }
485
+
486
+ #[ sqlx:: test]
487
+ async fn auto_build_success_labels ( pool : sqlx:: PgPool ) {
488
+ let github = GitHubState :: default ( ) . with_default_config (
489
+ r#"
490
+ merge_queue_enabled = true
491
+
492
+ [labels]
493
+ succeeded = ["+foo", "+bar", "-baz"]
494
+ "# ,
495
+ ) ;
496
+
497
+ BorsBuilder :: new ( pool)
498
+ . github ( github)
499
+ . run_test ( async |tester| {
500
+ tester. post_comment ( "@bors r+" ) . await ?;
501
+ tester. expect_comments ( 1 ) . await ;
502
+ tester. process_merge_queue ( ) . await ;
503
+ tester. expect_comments ( 1 ) . await ;
504
+
505
+ let repo = tester. default_repo ( ) ;
506
+ repo. lock ( )
507
+ . get_pr ( default_pr_number ( ) )
508
+ . check_added_labels ( & [ ] ) ;
509
+ tester. workflow_full_success ( tester. auto_branch ( ) ) . await ?;
510
+ tester. expect_comments ( 1 ) . await ;
511
+
512
+ let pr = repo. lock ( ) . get_pr ( default_pr_number ( ) ) . clone ( ) ;
513
+ pr. check_added_labels ( & [ "foo" , "bar" ] ) ;
514
+ pr. check_removed_labels ( & [ "baz" ] ) ;
515
+ Ok ( ( ) )
516
+ } )
517
+ . await ;
518
+ }
519
+
520
+ #[ sqlx:: test]
521
+ async fn auto_build_failed_labels ( pool : sqlx:: PgPool ) {
522
+ let github = GitHubState :: default ( ) . with_default_config (
523
+ r#"
524
+ merge_queue_enabled = true
525
+
526
+ [labels]
527
+ failed = ["+foo", "+bar", "-baz"]
528
+ "# ,
529
+ ) ;
530
+
531
+ BorsBuilder :: new ( pool)
532
+ . github ( github)
533
+ . run_test ( async |tester| {
534
+ tester. post_comment ( "@bors r+" ) . await ?;
535
+ tester. expect_comments ( 1 ) . await ;
536
+ tester. process_merge_queue ( ) . await ;
537
+ tester. expect_comments ( 1 ) . await ;
538
+
539
+ let repo = tester. default_repo ( ) ;
540
+ repo. lock ( )
541
+ . get_pr ( default_pr_number ( ) )
542
+ . check_added_labels ( & [ ] ) ;
543
+
544
+ tester. workflow_full_failure ( tester. auto_branch ( ) ) . await ?;
545
+ tester
546
+ . wait_for_default_pr ( |pr| {
547
+ pr. auto_build . as_ref ( ) . unwrap ( ) . status == BuildStatus :: Failure
548
+ } )
549
+ . await ?;
550
+ tester. expect_comments ( 1 ) . await ;
551
+
552
+ let pr = repo. lock ( ) . get_pr ( default_pr_number ( ) ) . clone ( ) ;
553
+ pr. check_added_labels ( & [ "foo" , "bar" ] ) ;
554
+ pr. check_removed_labels ( & [ "baz" ] ) ;
555
+
556
+ Ok ( ( ) )
557
+ } )
558
+ . await ;
559
+ }
560
+
561
+ #[ sqlx:: test]
562
+ async fn auto_build_failed_comment ( pool : sqlx:: PgPool ) {
563
+ BorsBuilder :: new ( pool)
564
+ . github ( gh_state_with_merge_queue ( ) )
565
+ . run_test ( async |tester| {
566
+ tester. post_comment ( "@bors r+" ) . await ?;
567
+ tester. expect_comments ( 1 ) . await ;
568
+ tester. process_merge_queue ( ) . await ;
569
+ tester. expect_comments ( 1 ) . await ;
570
+
571
+ let repo = tester. default_repo ( ) ;
572
+ repo. lock ( )
573
+ . get_pr ( default_pr_number ( ) )
574
+ . check_added_labels ( & [ ] ) ;
575
+
576
+ tester. workflow_full_failure ( tester. auto_branch ( ) ) . await ?;
577
+ tester. wait_for_default_pr ( |pr| {
578
+ pr. auto_build . as_ref ( ) . unwrap ( ) . status == BuildStatus :: Failure
579
+ } ) . await ?;
580
+ insta:: assert_snapshot!(
581
+ tester. get_comment( ) . await ?,
582
+ @":broken_heart: Test failed ([Workflow1](https://github.com/workflows/Workflow1/1))"
583
+ ) ;
584
+
585
+ Ok ( ( ) )
586
+ } )
587
+ . await ;
588
+ }
589
+
590
+ #[ sqlx:: test]
591
+ async fn auto_build_failure_updates_check_run ( pool : sqlx:: PgPool ) {
592
+ BorsBuilder :: new ( pool)
593
+ . github ( gh_state_with_merge_queue ( ) )
594
+ . run_test ( async |tester| {
595
+ tester. post_comment ( "@bors r+" ) . await ?;
596
+ tester. expect_comments ( 1 ) . await ;
597
+ tester. process_merge_queue ( ) . await ;
598
+ tester. expect_comments ( 1 ) . await ;
599
+
600
+ tester. workflow_full_failure ( tester. auto_branch ( ) ) . await ?;
601
+ tester. expect_comments ( 1 ) . await ;
602
+ tester. expect_check_run (
603
+ & tester. default_pr ( ) . await . get_gh_pr ( ) . head_sha ,
604
+ AUTO_BUILD_CHECK_RUN_NAME ,
605
+ AUTO_BUILD_CHECK_RUN_NAME ,
606
+ CheckRunStatus :: Completed ,
607
+ Some ( CheckRunConclusion :: Failure ) ,
608
+ ) ;
609
+ Ok ( ( ) )
610
+ } )
611
+ . await ;
612
+ }
428
613
}
0 commit comments