Skip to content

Commit cbe518d

Browse files
committed
Deal with auto build failure
- Post comment - Update check run
1 parent 4071b91 commit cbe518d

File tree

4 files changed

+139
-4
lines changed

4 files changed

+139
-4
lines changed

src/bors/comment.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,9 @@ pub fn auto_build_succeeded_comment(
209209
":sunny: Test successful - {urls}\nApproved by: `{approved_by}`\nPushing {merge_sha} to `{base_ref}`...",
210210
))
211211
}
212+
213+
pub fn auto_build_push_failed_comment(error: &str) -> Comment {
214+
Comment::new(format!(
215+
":eyes: Test was successful, but fast-forwarding failed: {error}"
216+
))
217+
}

src/bors/merge_queue.rs

Lines changed: 118 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use anyhow::anyhow;
2-
use octocrab::params::checks::{CheckRunOutput, CheckRunStatus};
2+
use octocrab::params::checks::{CheckRunConclusion, CheckRunOutput, CheckRunStatus};
33
use std::future::Future;
44
use std::sync::Arc;
55
use tokio::sync::mpsc;
66
use tracing::Instrument;
77

88
use crate::BorsContext;
9-
use crate::bors::comment::{auto_build_started_comment, auto_build_succeeded_comment};
9+
use crate::bors::comment::{
10+
auto_build_push_failed_comment, auto_build_started_comment, auto_build_succeeded_comment,
11+
};
1012
use crate::bors::{PullRequestStatus, RepositoryState};
1113
use crate::database::{BuildStatus, PullRequestModel};
1214
use crate::github::api::client::GithubRepositoryClient;
@@ -114,7 +116,36 @@ pub async fn merge_queue_tick(ctx: Arc<BorsContext>) -> anyhow::Result<()> {
114116
)
115117
.await?;
116118
}
117-
Err(_) => {}
119+
Err(error) => {
120+
tracing::error!(
121+
"Failed to push PR {pr_num} to base branch: {:?}",
122+
error
123+
);
124+
125+
if let Some(check_run_id) = auto_build.check_run_id {
126+
if let Err(error) = repo
127+
.client
128+
.update_check_run(
129+
check_run_id as u64,
130+
CheckRunStatus::Completed,
131+
Some(CheckRunConclusion::Failure),
132+
None,
133+
)
134+
.await
135+
{
136+
tracing::error!(
137+
"Could not update check run {check_run_id}: {error:?}"
138+
);
139+
}
140+
}
141+
142+
ctx.db
143+
.update_build_status(auto_build, BuildStatus::Failure)
144+
.await?;
145+
146+
let comment = auto_build_push_failed_comment(&error.to_string());
147+
repo.client.post_comment(pr.number, comment).await?;
148+
}
118149
};
119150

120151
// Break to give GitHub time to update the base branch.
@@ -315,7 +346,7 @@ pub fn start_merge_queue(ctx: Arc<BorsContext>) -> (MergeQueueSender, impl Futur
315346
#[cfg(test)]
316347
mod tests {
317348

318-
use octocrab::params::checks::CheckRunStatus;
349+
use octocrab::params::checks::{CheckRunConclusion, CheckRunStatus};
319350

320351
use crate::{
321352
bors::merge_queue::{AUTO_BRANCH_NAME, AUTO_BUILD_CHECK_RUN_NAME},
@@ -383,4 +414,87 @@ mod tests {
383414
})
384415
.await;
385416
}
417+
418+
#[sqlx::test]
419+
async fn auto_build_push_fail_comment(pool: sqlx::PgPool) {
420+
run_test(pool, |mut tester| async {
421+
tester.create_branch(AUTO_BRANCH_NAME).expect_suites(1);
422+
423+
tester.post_comment("@bors r+").await?;
424+
tester.expect_comments(1).await;
425+
426+
tester.process_merge_queue().await;
427+
tester.expect_comments(1).await;
428+
429+
tester.workflow_success(tester.auto_branch()).await?;
430+
tester.expect_comments(1).await;
431+
432+
tester.default_repo().lock().push_error = true;
433+
434+
tester.process_merge_queue().await;
435+
insta::assert_snapshot!(
436+
tester.get_comment().await?,
437+
@":eyes: Test was successful, but fast-forwarding failed: IO error"
438+
);
439+
440+
Ok(tester)
441+
})
442+
.await;
443+
}
444+
445+
#[sqlx::test]
446+
async fn auto_build_push_fail_updates_check_run(pool: sqlx::PgPool) {
447+
run_test(pool, |mut tester| async {
448+
tester.create_branch(AUTO_BRANCH_NAME).expect_suites(1);
449+
450+
tester.post_comment("@bors r+").await?;
451+
tester.expect_comments(1).await;
452+
453+
tester.process_merge_queue().await;
454+
tester.expect_comments(1).await;
455+
456+
tester.workflow_success(tester.auto_branch()).await?;
457+
tester.expect_comments(1).await;
458+
459+
tester.default_repo().lock().push_error = true;
460+
461+
tester.process_merge_queue().await;
462+
tester.expect_comments(1).await;
463+
464+
tester.expect_check_run(
465+
&tester.default_pr().await.get_gh_pr().head_sha,
466+
AUTO_BUILD_CHECK_RUN_NAME,
467+
AUTO_BUILD_CHECK_RUN_NAME,
468+
CheckRunStatus::Completed,
469+
Some(CheckRunConclusion::Failure),
470+
);
471+
Ok(tester)
472+
})
473+
.await;
474+
}
475+
476+
#[sqlx::test]
477+
async fn auto_build_push_fail_in_db(pool: sqlx::PgPool) {
478+
run_test(pool, |mut tester| async {
479+
tester.create_branch(AUTO_BRANCH_NAME).expect_suites(1);
480+
481+
tester.post_comment("@bors r+").await?;
482+
tester.expect_comments(1).await;
483+
484+
tester.process_merge_queue().await;
485+
tester.expect_comments(1).await;
486+
487+
tester.workflow_success(tester.auto_branch()).await?;
488+
tester.expect_comments(1).await;
489+
490+
tester.default_repo().lock().push_error = true;
491+
492+
tester.process_merge_queue().await;
493+
tester.expect_comments(1).await;
494+
495+
tester.default_pr().await.expect_auto_build_failed();
496+
Ok(tester)
497+
})
498+
.await;
499+
}
386500
}

src/tests/mocks/bors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,14 @@ impl PullRequestProxy {
951951
);
952952
}
953953

954+
#[track_caller]
955+
pub fn expect_auto_build_failed(&self) {
956+
assert_eq!(
957+
self.require_db_pr().auto_build.as_ref().unwrap().status,
958+
BuildStatus::Failure
959+
);
960+
}
961+
954962
#[track_caller]
955963
fn require_db_pr(&self) -> &PullRequestModel {
956964
self.db_pr.as_ref().unwrap()

src/tests/mocks/repository.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ pub struct Repo {
152152
pub check_runs: Vec<CheckRunData>,
153153
// Cause pull request fetch to fail.
154154
pub pull_request_error: bool,
155+
// Cause branch push to fail.
156+
pub push_error: bool,
155157
pub pr_push_counter: u64,
156158
}
157159

@@ -166,6 +168,7 @@ impl Repo {
166168
cancelled_workflows: vec![],
167169
workflow_cancel_error: false,
168170
pull_request_error: false,
171+
push_error: false,
169172
pr_push_counter: 0,
170173
check_runs: vec![],
171174
}
@@ -499,6 +502,10 @@ async fn mock_update_branch(repo: Arc<Mutex<Repo>>, mock_server: &MockServer) {
499502
}
500503

501504
let data: SetRefRequest = req.body_json().unwrap();
505+
506+
if repo.push_error {
507+
return ResponseTemplate::new(500).set_body_string("Simulated push error");
508+
}
502509

503510
let sha = data.sha;
504511
match repo.get_branch_by_name(branch_name) {

0 commit comments

Comments
 (0)