Skip to content

Commit 4bace5f

Browse files
committed
feat: support pull request opened event
1 parent daaa405 commit 4bace5f

File tree

3 files changed

+88
-21
lines changed

3 files changed

+88
-21
lines changed

src/gh/event.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1+
use octocrab::models::webhook_events::payload::PullRequestWebhookEventPayload;
12
use serde::Deserialize;
23

4+
#[derive(Debug, Deserialize)]
5+
#[serde(untagged)]
6+
pub enum Payload {
7+
CheckSuite(CheckSuiteEvent),
8+
PullRequest(PullRequestEvent),
9+
}
10+
311
#[derive(Debug, Deserialize)]
412
pub struct CheckSuiteEvent {
513
pub action: CheckSuiteAction,
@@ -18,7 +26,6 @@ pub enum CheckSuiteAction {
1826

1927
#[derive(Debug, Deserialize)]
2028
pub struct CheckSuitePayload {
21-
pub id: u64,
2229
pub pull_requests: Vec<PullRequest>,
2330
pub head_sha: String,
2431
}
@@ -44,3 +51,11 @@ pub struct RepositoryOwner {
4451
pub struct Installation {
4552
pub id: u64,
4653
}
54+
55+
#[derive(Debug, Deserialize)]
56+
pub struct PullRequestEvent {
57+
pub installation: Installation,
58+
#[serde(flatten)]
59+
pub inner: PullRequestWebhookEventPayload,
60+
pub repository: octocrab::models::Repository,
61+
}

src/gh/mod.rs

+34-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use anyhow::anyhow;
12
use cocogitto::settings::Settings as CogSettings;
23
use octocrab::models::checks::CheckRun;
34
use octocrab::models::issues::Comment;
@@ -12,6 +13,7 @@ use event::CheckSuiteEvent;
1213
use crate::cog::report::CogBotReportBuilder;
1314
use crate::gh::authenticate::authenticate;
1415
use crate::gh::commits::GetCommits;
16+
use crate::gh::event::PullRequestEvent;
1517

1618
pub mod authenticate;
1719
pub mod check_run;
@@ -30,7 +32,7 @@ pub struct CocogittoBot {
3032
const COCOGITTO_BOT_LOGIN: &str = "cocogitto-bot[bot]";
3133

3234
impl CocogittoBot {
33-
pub async fn from_check_suite(event: CheckSuiteEvent, gh_key: &str) -> octocrab::Result<Self> {
35+
pub async fn from_check_suite(event: CheckSuiteEvent, gh_key: &str) -> anyhow::Result<Self> {
3436
let check_suite = event.check_suite;
3537
let installation = event.installation;
3638
let repository = event.repository;
@@ -62,6 +64,37 @@ impl CocogittoBot {
6264
})
6365
}
6466

67+
pub async fn from_pull_request(event: PullRequestEvent, gh_key: &str) -> anyhow::Result<Self> {
68+
let installation = event.installation;
69+
let repository = event.repository;
70+
71+
info!("Authenticating to github api");
72+
let auth = authenticate(installation.id, &repository.name, gh_key).await;
73+
if let Err(auth_error) = &auth {
74+
return Err(anyhow!("Failed to authenticate: {auth_error}"));
75+
}
76+
77+
let inner = auth?;
78+
let pull_request_number = Some(event.inner.pull_request.number);
79+
80+
let Some(default_branch) = repository.default_branch else {
81+
return Err(anyhow!("default_branch missing from pull_request event"));
82+
};
83+
84+
let Some(owner) = repository.owner.map(|owner| owner.login) else {
85+
return Err(anyhow!("owner missing from pull_request event"));
86+
};
87+
88+
Ok(Self {
89+
inner,
90+
owner,
91+
repo: repository.name,
92+
head_sha: event.inner.pull_request.head.sha,
93+
pull_request_number,
94+
default_branch,
95+
})
96+
}
97+
6598
pub async fn run(&mut self) -> anyhow::Result<()> {
6699
let check_run = self.create_check_runs().await?;
67100

src/main.rs

+38-19
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ use axum::http::HeaderMap;
55
use axum::routing::{get, post};
66
use axum::{Json, Router};
77
use axum_macros::debug_handler;
8+
use gh::event::CheckSuiteAction;
9+
use octocrab::models::webhook_events::payload::PullRequestWebhookEventAction;
810
use tower_http::trace::TraceLayer;
911
use tracing::{info, warn};
1012
use tracing_subscriber::layer::SubscriberExt;
1113
use tracing_subscriber::util::SubscriberInitExt;
1214

13-
use gh::event::{CheckSuiteAction, CheckSuiteEvent};
14-
1515
use crate::error::AppResult;
16+
use crate::gh::event::Payload;
1617
use crate::gh::CocogittoBot;
1718
use crate::settings::Settings;
1819

@@ -64,33 +65,51 @@ async fn main() -> anyhow::Result<()> {
6465
async fn pull_request_handler(
6566
State(state): State<AppState>,
6667
headers: HeaderMap,
67-
Json(event): Json<CheckSuiteEvent>,
68+
Json(event): Json<Payload>,
6869
) -> AppResult<()> {
6970
let Some(event_header) = headers.get("X-Github-Event") else {
7071
warn!("'X-Github-Event' header missing, ignoring request");
7172
return Ok(());
7273
};
7374

74-
let Ok("check_suite") = event_header.to_str() else {
75-
info!("Ignoring non check_suite event");
76-
return Ok(());
77-
};
78-
79-
if event.action == CheckSuiteAction::Completed {
80-
info!("Ignoring completed check_suite");
81-
return Ok(());
75+
match event_header.to_str() {
76+
Ok("check_suite") | Ok("pull_request") => {}
77+
_ => {
78+
info!("Ignoring non check_suite event");
79+
return Ok(());
80+
}
8281
}
8382

84-
if event.check_suite.pull_requests.is_empty() {
85-
info!("Ignoring non pull request check_suite event");
86-
return Ok(());
83+
match event {
84+
Payload::CheckSuite(event) => {
85+
if event.action == CheckSuiteAction::Completed {
86+
info!("Ignoring completed check_suite");
87+
return Ok(());
88+
}
89+
90+
if event.check_suite.pull_requests.is_empty() {
91+
info!("Ignoring non pull request check_suite event");
92+
return Ok(());
93+
}
94+
95+
CocogittoBot::from_check_suite(event, &state.github_key)
96+
.await?
97+
.run()
98+
.await?;
99+
}
100+
Payload::PullRequest(event) => {
101+
if event.inner.action != PullRequestWebhookEventAction::Opened {
102+
info!("Ignoring pull_request event");
103+
return Ok(());
104+
}
105+
106+
CocogittoBot::from_pull_request(event, &state.github_key)
107+
.await?
108+
.run()
109+
.await?;
110+
}
87111
}
88112

89-
CocogittoBot::from_check_suite(event, &state.github_key)
90-
.await?
91-
.run()
92-
.await?;
93-
94113
Ok(())
95114
}
96115

0 commit comments

Comments
 (0)