diff --git a/Cargo.toml b/Cargo.toml index c2bd1a1..dff25df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_yaml = "0.9" sha2 = "0.10" -tokio = { version = "1.22", features = ["full"] } +tokio = { version = "1.23", features = ["full"] } tracing = "0.1" tracing-appender = "0.2" tracing-subscriber = "0.3" diff --git a/src/config.rs b/src/config.rs index 10697e2..13ba8f9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -32,6 +32,7 @@ pub struct Logging { #[derive(Deserialize)] pub struct Hook { + pub name: String, pub repo_url: String, pub current_dir: String, pub command: String, diff --git a/src/mailer.rs b/src/mailer.rs index 55e689e..dc0e4e8 100644 --- a/src/mailer.rs +++ b/src/mailer.rs @@ -2,6 +2,7 @@ use anyhow::{Context, Result}; use lettre::address::Address; use lettre::message::{Mailbox, MessageBuilder}; use lettre::transport::smtp::authentication::Credentials; +use lettre::Transport; use lettre::{Message, SmtpTransport}; use std::mem; @@ -42,7 +43,16 @@ impl Mailer { }) } - pub fn send(&self) -> Result<()> { + pub fn send(&self, hook_name: &str, hook_log_link: &str, status: &str) -> Result<()> { + let email = self + .message_builder + .clone() + .subject(format!("GWC {}: {}", hook_name, status)) + .body(hook_log_link.to_string()) + .context("Failed to build email!")?; + + self.mailer.send(&email).context("Failed to send email!")?; + Ok(()) } } diff --git a/src/routes.rs b/src/routes.rs index 448d80b..8cecb03 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -11,9 +11,9 @@ use sha2::Sha256; use std::process::Command; use std::sync::Arc; use std::thread; -use tracing::info; +use tracing::{error, info}; -use crate::{db, errors, states, templates}; +use crate::{db, errors, mailer, states, templates}; #[derive(Deserialize)] pub struct IndexQuery { @@ -51,6 +51,7 @@ async fn is_valid_signature(secret: &[u8], received_signature: &[u8], body: &[u8 pub async fn trigger( State(db_state): State>, State(config_state): State>, + State(mailer): State>, headers: HeaderMap, body: Bytes, ) -> Result { @@ -92,6 +93,8 @@ pub async fn trigger( let hook_log_id = db::add_hook_log(&db_state.pool, hook)?.id; + let hook_log_link = format!("{}/?id={}", config_state.base_url, hook_log_id); + { // Spawn and detach a thread that runs the command and fills the output in the log. // This is useful to give a quick response to the git server in case that the command has a long @@ -102,6 +105,8 @@ pub async fn trigger( let current_dir = hook.current_dir.clone(); let db_pool = db_state.pool.clone(); let clone_url = clone_url.to_string(); + let hook_name = hook.name.clone(); + let hook_log_link = hook_log_link.clone(); thread::spawn(move || { info!("Running webhook for Repo: {clone_url}"); @@ -129,9 +134,16 @@ pub async fn trigger( } }; + let status = if status_code == Some(0) { "Ok" } else { "Err" }; + db::fill_hook_log(&db_pool, hook_log_id, &stdout, &stderr, status_code); + + match mailer.send(&hook_name, &hook_log_link, status) { + Ok(_) => info!("Sent email with hook name {hook_name}"), + Err(e) => error!("{e:?}"), + }; }); } - Ok(format!("{}/?id={}", config_state.base_url, hook_log_id).into_response()) + Ok(hook_log_link.into_response()) }