Skip to content

Commit

Permalink
feat: support pull request opened event
Browse files Browse the repository at this point in the history
  • Loading branch information
oknozor committed Oct 11, 2024
1 parent daaa405 commit 4bace5f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 21 deletions.
17 changes: 16 additions & 1 deletion src/gh/event.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
use octocrab::models::webhook_events::payload::PullRequestWebhookEventPayload;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum Payload {
CheckSuite(CheckSuiteEvent),
PullRequest(PullRequestEvent),
}

#[derive(Debug, Deserialize)]
pub struct CheckSuiteEvent {
pub action: CheckSuiteAction,
Expand All @@ -18,7 +26,6 @@ pub enum CheckSuiteAction {

#[derive(Debug, Deserialize)]
pub struct CheckSuitePayload {
pub id: u64,
pub pull_requests: Vec<PullRequest>,
pub head_sha: String,
}
Expand All @@ -44,3 +51,11 @@ pub struct RepositoryOwner {
pub struct Installation {
pub id: u64,
}

#[derive(Debug, Deserialize)]
pub struct PullRequestEvent {
pub installation: Installation,
#[serde(flatten)]
pub inner: PullRequestWebhookEventPayload,
pub repository: octocrab::models::Repository,
}
35 changes: 34 additions & 1 deletion src/gh/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::anyhow;
use cocogitto::settings::Settings as CogSettings;
use octocrab::models::checks::CheckRun;
use octocrab::models::issues::Comment;
Expand All @@ -12,6 +13,7 @@ use event::CheckSuiteEvent;
use crate::cog::report::CogBotReportBuilder;
use crate::gh::authenticate::authenticate;
use crate::gh::commits::GetCommits;
use crate::gh::event::PullRequestEvent;

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

impl CocogittoBot {
pub async fn from_check_suite(event: CheckSuiteEvent, gh_key: &str) -> octocrab::Result<Self> {
pub async fn from_check_suite(event: CheckSuiteEvent, gh_key: &str) -> anyhow::Result<Self> {
let check_suite = event.check_suite;
let installation = event.installation;
let repository = event.repository;
Expand Down Expand Up @@ -62,6 +64,37 @@ impl CocogittoBot {
})
}

pub async fn from_pull_request(event: PullRequestEvent, gh_key: &str) -> anyhow::Result<Self> {
let installation = event.installation;
let repository = event.repository;

info!("Authenticating to github api");
let auth = authenticate(installation.id, &repository.name, gh_key).await;
if let Err(auth_error) = &auth {
return Err(anyhow!("Failed to authenticate: {auth_error}"));
}

let inner = auth?;
let pull_request_number = Some(event.inner.pull_request.number);

let Some(default_branch) = repository.default_branch else {
return Err(anyhow!("default_branch missing from pull_request event"));
};

let Some(owner) = repository.owner.map(|owner| owner.login) else {
return Err(anyhow!("owner missing from pull_request event"));
};

Ok(Self {
inner,
owner,
repo: repository.name,
head_sha: event.inner.pull_request.head.sha,
pull_request_number,
default_branch,
})
}

pub async fn run(&mut self) -> anyhow::Result<()> {
let check_run = self.create_check_runs().await?;

Expand Down
57 changes: 38 additions & 19 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ use axum::http::HeaderMap;
use axum::routing::{get, post};
use axum::{Json, Router};
use axum_macros::debug_handler;
use gh::event::CheckSuiteAction;
use octocrab::models::webhook_events::payload::PullRequestWebhookEventAction;
use tower_http::trace::TraceLayer;
use tracing::{info, warn};
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;

use gh::event::{CheckSuiteAction, CheckSuiteEvent};

use crate::error::AppResult;
use crate::gh::event::Payload;
use crate::gh::CocogittoBot;
use crate::settings::Settings;

Expand Down Expand Up @@ -64,33 +65,51 @@ async fn main() -> anyhow::Result<()> {
async fn pull_request_handler(
State(state): State<AppState>,
headers: HeaderMap,
Json(event): Json<CheckSuiteEvent>,
Json(event): Json<Payload>,
) -> AppResult<()> {
let Some(event_header) = headers.get("X-Github-Event") else {
warn!("'X-Github-Event' header missing, ignoring request");
return Ok(());
};

let Ok("check_suite") = event_header.to_str() else {
info!("Ignoring non check_suite event");
return Ok(());
};

if event.action == CheckSuiteAction::Completed {
info!("Ignoring completed check_suite");
return Ok(());
match event_header.to_str() {
Ok("check_suite") | Ok("pull_request") => {}
_ => {
info!("Ignoring non check_suite event");
return Ok(());
}
}

if event.check_suite.pull_requests.is_empty() {
info!("Ignoring non pull request check_suite event");
return Ok(());
match event {
Payload::CheckSuite(event) => {
if event.action == CheckSuiteAction::Completed {
info!("Ignoring completed check_suite");
return Ok(());
}

if event.check_suite.pull_requests.is_empty() {
info!("Ignoring non pull request check_suite event");
return Ok(());
}

CocogittoBot::from_check_suite(event, &state.github_key)
.await?
.run()
.await?;
}
Payload::PullRequest(event) => {
if event.inner.action != PullRequestWebhookEventAction::Opened {
info!("Ignoring pull_request event");
return Ok(());
}

CocogittoBot::from_pull_request(event, &state.github_key)
.await?
.run()
.await?;
}
}

CocogittoBot::from_check_suite(event, &state.github_key)
.await?
.run()
.await?;

Ok(())
}

Expand Down

0 comments on commit 4bace5f

Please sign in to comment.