Skip to content

Commit 38a3c39

Browse files
committed
feat: support pull request opened event
1 parent daaa405 commit 38a3c39

File tree

3 files changed

+91
-21
lines changed

3 files changed

+91
-21
lines changed

src/gh/event.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
1+
use octocrab::models::webhook_events::payload::PullRequestWebhookEventPayload;
2+
use octocrab::models::webhook_events::WebhookEventPayload;
13
use serde::Deserialize;
24

5+
#[derive(Debug, Deserialize)]
6+
#[serde(untagged)]
7+
pub enum Payload {
8+
CheckSuite(CheckSuiteEvent),
9+
PullRequest(PullRequestEvent),
10+
Other(WebhookEventPayload),
11+
}
12+
313
#[derive(Debug, Deserialize)]
414
pub struct CheckSuiteEvent {
515
pub action: CheckSuiteAction,
@@ -18,7 +28,6 @@ pub enum CheckSuiteAction {
1828

1929
#[derive(Debug, Deserialize)]
2030
pub struct CheckSuitePayload {
21-
pub id: u64,
2231
pub pull_requests: Vec<PullRequest>,
2332
pub head_sha: String,
2433
}
@@ -44,3 +53,11 @@ pub struct RepositoryOwner {
4453
pub struct Installation {
4554
pub id: u64,
4655
}
56+
57+
#[derive(Debug, Deserialize)]
58+
pub struct PullRequestEvent {
59+
pub installation: Installation,
60+
#[serde(flatten)]
61+
pub inner: PullRequestWebhookEventPayload,
62+
pub repository: octocrab::models::Repository,
63+
}

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

+39-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,52 @@ 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+
}
111+
_ => { /* ignore other event */ }
87112
}
88113

89-
CocogittoBot::from_check_suite(event, &state.github_key)
90-
.await?
91-
.run()
92-
.await?;
93-
94114
Ok(())
95115
}
96116

0 commit comments

Comments
 (0)