Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support pull request opened event #24

Merged
merged 1 commit into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading