Skip to content

Commit a5f239a

Browse files
committed
Complete auto build
- Post comment - Update check run - Update label
1 parent a7cdb0d commit a5f239a

File tree

6 files changed

+348
-24
lines changed

6 files changed

+348
-24
lines changed

rust-bors.example.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ approve = ["+approved"]
1919
try = ["+foo", "-bar"]
2020
try_succeed = ["+foobar", "+foo", "+baz"]
2121
try_failed = []
22+
succeeded = ["+foo", "+bar"]
23+
failed = ["+foo", "+bar"]
2224

2325
# Labels that will block approval when present on a PR
2426
# (Optional)

src/bors/comment.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,20 @@ pub fn auto_build_started_comment(head_sha: &CommitSha, merge_sha: &CommitSha) -
283283
head_sha, merge_sha
284284
))
285285
}
286+
287+
pub fn auto_build_succeeded_comment(
288+
workflows: &[WorkflowModel],
289+
approved_by: &str,
290+
merge_sha: &CommitSha,
291+
base_ref: &str,
292+
) -> Comment {
293+
let urls = workflows
294+
.iter()
295+
.map(|w| format!("[{}]({})", w.name, w.url))
296+
.collect::<Vec<_>>()
297+
.join(", ");
298+
299+
Comment::new(format!(
300+
":sunny: Test successful - {urls}\nApproved by: `{approved_by}`\nPushing {merge_sha} to `{base_ref}`...",
301+
))
302+
}

src/bors/handlers/workflow.rs

Lines changed: 203 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::PgDbClient;
22
use crate::bors::comment::{build_failed_comment, try_build_succeeded_comment};
33
use crate::bors::event::{WorkflowRunCompleted, WorkflowRunStarted};
4+
use crate::bors::handlers::TRY_BRANCH_NAME;
45
use crate::bors::handlers::is_bors_observed_branch;
56
use crate::bors::handlers::labels::handle_label_trigger;
67
use crate::bors::merge_queue::AUTO_BRANCH_NAME;
@@ -184,21 +185,26 @@ async fn maybe_complete_build(
184185
let has_failure = db_workflow_runs
185186
.iter()
186187
.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"),
192198
};
193-
db.update_build_status(&build, status).await?;
194199

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?;
196202

197203
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 {
201205
(CheckRunStatus::Completed, Some(CheckRunConclusion::Success))
206+
} else {
207+
(CheckRunStatus::Completed, Some(CheckRunConclusion::Failure))
202208
};
203209

204210
if let Err(error) = repo
@@ -212,10 +218,21 @@ async fn maybe_complete_build(
212218

213219
db_workflow_runs.sort_by(|a, b| a.name.cmp(&b.name));
214220

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+
}
218233
} else {
234+
tracing::info!("Build failed for PR {pr_num}");
235+
219236
// Download failed jobs
220237
let mut workflow_runs: Vec<FailedWorkflowRun> = vec![];
221238
for workflow_run in db_workflow_runs {
@@ -235,10 +252,12 @@ async fn maybe_complete_build(
235252
})
236253
}
237254

238-
tracing::info!("Build failed");
239-
build_failed_comment(repo.repository(), workflow_runs)
255+
Some(build_failed_comment(repo.repository(), workflow_runs))
240256
};
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+
}
242261

243262
// Trigger merge queue when an auto build completes
244263
if payload.branch == AUTO_BRANCH_NAME {
@@ -273,10 +292,24 @@ async fn get_failed_jobs(
273292

274293
#[cfg(test)]
275294
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;
277298
use crate::database::operations::get_all_workflows;
299+
use crate::database::{BuildStatus, WorkflowStatus};
278300
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+
}
280313

281314
#[sqlx::test]
282315
async fn workflow_started_unknown_build(pool: sqlx::PgPool) {
@@ -425,4 +458,156 @@ mod tests {
425458
})
426459
.await;
427460
}
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+
}
428613
}

0 commit comments

Comments
 (0)