Skip to content

Commit 8cdb504

Browse files
authored
Merge pull request #70 from vohoanglong0107/refactor-global-event
refactor: split global event from per repo ones
2 parents ea02dca + 08f095d commit 8cdb504

File tree

6 files changed

+358
-257
lines changed

6 files changed

+358
-257
lines changed

src/bin/bors.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::time::Duration;
55

66
use anyhow::Context;
77
use bors::{
8-
create_app, create_bors_process, BorsContext, BorsEvent, CommandParser, GithubAppState,
9-
SeaORMClient, ServerState, WebhookSecret,
8+
create_app, create_bors_process, BorsContext, BorsEvent, BorsGlobalEvent, CommandParser,
9+
GithubAppState, SeaORMClient, ServerState, WebhookSecret,
1010
};
1111
use clap::Parser;
1212
use sea_orm::Database;
@@ -85,7 +85,9 @@ fn try_main(opts: Opts) -> anyhow::Result<()> {
8585
let refresh_process = async move {
8686
loop {
8787
tokio::time::sleep(PERIODIC_REFRESH).await;
88-
refresh_tx.send(BorsEvent::Refresh).await?;
88+
refresh_tx
89+
.send(BorsEvent::Global(BorsGlobalEvent::Refresh))
90+
.await?;
8991
}
9092
};
9193

src/bors/event.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::github::{CommitSha, GithubRepoName, GithubUser, PullRequestNumber};
33
use octocrab::models::RunId;
44

55
#[derive(Debug)]
6-
pub enum BorsEvent {
6+
pub enum BorsRepositoryEvent {
77
/// A comment was posted on a pull request.
88
Comment(PullRequestComment),
99
/// A workflow run on Github Actions or a check run from external CI system has been started.
@@ -13,12 +13,35 @@ pub enum BorsEvent {
1313
/// A check suite has been completed, either as a workflow run on Github Actions, or as a
1414
/// workflow from some external CI system.
1515
CheckSuiteCompleted(CheckSuiteCompleted),
16+
}
17+
18+
impl BorsRepositoryEvent {
19+
pub fn repository(&self) -> &GithubRepoName {
20+
match self {
21+
BorsRepositoryEvent::Comment(comment) => &comment.repository,
22+
BorsRepositoryEvent::WorkflowStarted(workflow) => &workflow.repository,
23+
BorsRepositoryEvent::WorkflowCompleted(workflow) => &workflow.repository,
24+
BorsRepositoryEvent::CheckSuiteCompleted(payload) => &payload.repository,
25+
}
26+
}
27+
}
28+
29+
#[derive(Debug)]
30+
pub enum BorsGlobalEvent {
1631
/// The configuration of some repository has been changed for the bot's Github App.
1732
InstallationsChanged,
1833
/// Periodic event that serves for checking e.g. timeouts.
1934
Refresh,
2035
}
2136

37+
#[derive(Debug)]
38+
pub enum BorsEvent {
39+
/// An event that happen per repository basis.
40+
Repository(BorsRepositoryEvent),
41+
/// An event that happen with bors globally.
42+
Global(BorsGlobalEvent),
43+
}
44+
2245
#[derive(Debug)]
2346
pub struct PullRequestComment {
2447
pub repository: GithubRepoName,

src/bors/handlers/mod.rs

Lines changed: 98 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::sync::Arc;
33
use tracing::Instrument;
44

55
use crate::bors::command::{BorsCommand, CommandParseError};
6-
use crate::bors::event::{BorsEvent, PullRequestComment};
6+
use crate::bors::event::{BorsRepositoryEvent, PullRequestComment};
77
use crate::bors::handlers::help::command_help;
88
use crate::bors::handlers::ping::command_ping;
99
use crate::bors::handlers::refresh::refresh_repository;
@@ -16,6 +16,8 @@ use crate::database::DbClient;
1616
use crate::github::GithubRepoName;
1717
use crate::utils::logging::LogError;
1818

19+
use super::event::{BorsEvent, BorsGlobalEvent};
20+
1921
mod help;
2022
mod labels;
2123
mod ping;
@@ -28,93 +30,118 @@ pub async fn handle_bors_event<Client: RepositoryClient>(
2830
event: BorsEvent,
2931
state: Arc<dyn BorsState<Client>>,
3032
ctx: Arc<BorsContext>,
33+
) -> anyhow::Result<()> {
34+
match event {
35+
BorsEvent::Repository(event) => {
36+
handle_bors_repository_event(event, state, ctx).await?;
37+
}
38+
BorsEvent::Global(event) => {
39+
handle_bors_global_event(event, state, ctx).await?;
40+
}
41+
}
42+
Ok(())
43+
}
44+
45+
pub async fn handle_bors_repository_event<Client: RepositoryClient>(
46+
event: BorsRepositoryEvent,
47+
state: Arc<dyn BorsState<Client>>,
48+
ctx: Arc<BorsContext>,
3149
) -> anyhow::Result<()> {
3250
let db = Arc::clone(&ctx.db);
51+
let Some(repo) = get_repo_state(state, event.repository()) else {
52+
return Err(anyhow::anyhow!(
53+
"Repository {} not found in the bot state",
54+
event.repository()
55+
));
56+
};
57+
3358
match event {
34-
BorsEvent::Comment(comment) => {
59+
BorsRepositoryEvent::Comment(comment) => {
3560
// We want to ignore comments made by this bot
36-
if let Some(repo) = get_repo_state(state, &comment.repository) {
37-
if repo.client.is_comment_internal(&comment).await? {
38-
tracing::trace!(
39-
"Ignoring comment {comment:?} because it was authored by this bot"
40-
);
41-
return Ok(());
42-
}
61+
if repo.client.is_comment_internal(&comment).await? {
62+
tracing::trace!("Ignoring comment {comment:?} because it was authored by this bot");
63+
return Ok(());
64+
}
4365

44-
let span = tracing::info_span!(
45-
"Comment",
46-
pr = format!("{}#{}", comment.repository, comment.pr_number),
47-
author = comment.author.username
48-
);
49-
let pr_number = comment.pr_number;
50-
if let Err(error) = handle_comment(Arc::clone(&repo), db, ctx, comment)
51-
.instrument(span.clone())
66+
let span = tracing::info_span!(
67+
"Comment",
68+
pr = format!("{}#{}", comment.repository, comment.pr_number),
69+
author = comment.author.username
70+
);
71+
let pr_number = comment.pr_number;
72+
if let Err(error) = handle_comment(Arc::clone(&repo), db, ctx, comment)
73+
.instrument(span.clone())
74+
.await
75+
{
76+
span.log_error(error);
77+
repo.client
78+
.post_comment(
79+
pr_number,
80+
Comment::new(
81+
":x: Encountered an error while executing command".to_string(),
82+
),
83+
)
5284
.await
53-
{
54-
span.log_error(error);
55-
repo.client
56-
.post_comment(
57-
pr_number,
58-
Comment::new(
59-
":x: Encountered an error while executing command".to_string(),
60-
),
61-
)
62-
.await
63-
.context("Cannot send comment reacting to an error")?;
64-
}
85+
.context("Cannot send comment reacting to an error")?;
6586
}
6687
}
67-
BorsEvent::InstallationsChanged => {
68-
let span = tracing::info_span!("Repository reload");
69-
if let Err(error) = state.reload_repositories().instrument(span.clone()).await {
88+
89+
BorsRepositoryEvent::WorkflowStarted(payload) => {
90+
let span = tracing::info_span!(
91+
"Workflow started",
92+
repo = payload.repository.to_string(),
93+
id = payload.run_id.into_inner()
94+
);
95+
if let Err(error) = handle_workflow_started(db, payload)
96+
.instrument(span.clone())
97+
.await
98+
{
7099
span.log_error(error);
71100
}
72101
}
73-
BorsEvent::WorkflowStarted(payload) => {
74-
if let Some(_) = get_repo_state(state, &payload.repository) {
75-
let span = tracing::info_span!(
76-
"Workflow started",
77-
repo = payload.repository.to_string(),
78-
id = payload.run_id.into_inner()
79-
);
80-
if let Err(error) = handle_workflow_started(db, payload)
81-
.instrument(span.clone())
82-
.await
83-
{
84-
span.log_error(error);
85-
}
102+
BorsRepositoryEvent::WorkflowCompleted(payload) => {
103+
let span = tracing::info_span!(
104+
"Workflow completed",
105+
repo = payload.repository.to_string(),
106+
id = payload.run_id.into_inner()
107+
);
108+
if let Err(error) = handle_workflow_completed(repo, db, payload)
109+
.instrument(span.clone())
110+
.await
111+
{
112+
span.log_error(error);
86113
}
87114
}
88-
BorsEvent::WorkflowCompleted(payload) => {
89-
if let Some(repo) = get_repo_state(state, &payload.repository) {
90-
let span = tracing::info_span!(
91-
"Workflow completed",
92-
repo = payload.repository.to_string(),
93-
id = payload.run_id.into_inner()
94-
);
95-
if let Err(error) = handle_workflow_completed(repo, db, payload)
96-
.instrument(span.clone())
97-
.await
98-
{
99-
span.log_error(error);
100-
}
115+
BorsRepositoryEvent::CheckSuiteCompleted(payload) => {
116+
let span = tracing::info_span!(
117+
"Check suite completed",
118+
repo = payload.repository.to_string(),
119+
);
120+
if let Err(error) = handle_check_suite_completed(repo, db, payload)
121+
.instrument(span.clone())
122+
.await
123+
{
124+
span.log_error(error);
101125
}
102126
}
103-
BorsEvent::CheckSuiteCompleted(payload) => {
104-
if let Some(repo) = get_repo_state(state, &payload.repository) {
105-
let span = tracing::info_span!(
106-
"Check suite completed",
107-
repo = payload.repository.to_string(),
108-
);
109-
if let Err(error) = handle_check_suite_completed(repo, db, payload)
110-
.instrument(span.clone())
111-
.await
112-
{
113-
span.log_error(error);
114-
}
127+
}
128+
Ok(())
129+
}
130+
131+
pub async fn handle_bors_global_event<Client: RepositoryClient>(
132+
event: BorsGlobalEvent,
133+
state: Arc<dyn BorsState<Client>>,
134+
ctx: Arc<BorsContext>,
135+
) -> anyhow::Result<()> {
136+
let db = Arc::clone(&ctx.db);
137+
match event {
138+
BorsGlobalEvent::InstallationsChanged => {
139+
let span = tracing::info_span!("Repository reload");
140+
if let Err(error) = state.reload_repositories().instrument(span.clone()).await {
141+
span.log_error(error);
115142
}
116143
}
117-
BorsEvent::Refresh => {
144+
BorsGlobalEvent::Refresh => {
118145
let span = tracing::info_span!("Refresh");
119146
let repos = state.get_all_repos();
120147
futures::future::join_all(repos.into_iter().map(|repo| {

0 commit comments

Comments
 (0)