From 731c22826c9fa47b41d9759d9abd95618261af97 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Sun, 21 Jul 2024 13:44:44 +0100 Subject: [PATCH] WIP: feat: post webhook to user --- Cargo.toml | 1 + crates/config/src/branch_name.rs | 4 +- crates/config/src/forge_alias.rs | 4 +- crates/config/src/repo_alias.rs | 3 +- crates/git/Cargo.toml | 6 +- crates/git/src/commit.rs | 6 +- crates/repo-actor/Cargo.toml | 1 + crates/repo-actor/src/lib.rs | 1 + crates/repo-actor/src/notifications.rs | 72 +++++++++++++++++++ crates/server-actor/Cargo.toml | 4 ++ .../server-actor/src/handlers/notify_user.rs | 5 +- .../handlers/receive_valid_server_config.rs | 4 +- crates/server-actor/src/handlers/shutdown.rs | 2 +- crates/server-actor/src/lib.rs | 4 +- 14 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 crates/repo-actor/src/notifications.rs diff --git a/Cargo.toml b/Cargo.toml index 940ed14..f136d51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,6 +78,7 @@ git-conventional = "0.12" bytes = "1.6" ulid = "1.1" warp = "0.3" +time = "0.3" # boilerplate derive_more = { version = "1.0.0-beta.6", features = [ diff --git a/crates/config/src/branch_name.rs b/crates/config/src/branch_name.rs index 2d4ac67..192e740 100644 --- a/crates/config/src/branch_name.rs +++ b/crates/config/src/branch_name.rs @@ -1 +1,3 @@ -crate::newtype!(BranchName: String, derive_more::Display, Default: "The name of a Git branch"); +use serde::Serialize; + +crate::newtype!(BranchName: String, derive_more::Display, Default, Serialize: "The name of a Git branch"); diff --git a/crates/config/src/forge_alias.rs b/crates/config/src/forge_alias.rs index a665b6f..f27a7a8 100644 --- a/crates/config/src/forge_alias.rs +++ b/crates/config/src/forge_alias.rs @@ -1,4 +1,6 @@ -crate::newtype!(ForgeAlias: String, Hash, PartialOrd, Ord, derive_more::Display, Default: "The name of a Forge to connect to"); +use serde::Serialize; + +crate::newtype!(ForgeAlias: String, Hash, PartialOrd, Ord, derive_more::Display, Default, Serialize: "The name of a Forge to connect to"); impl From<&ForgeAlias> for std::path::PathBuf { fn from(value: &ForgeAlias) -> Self { Self::from(&value.0) diff --git a/crates/config/src/repo_alias.rs b/crates/config/src/repo_alias.rs index bd42984..7cedbf5 100644 --- a/crates/config/src/repo_alias.rs +++ b/crates/config/src/repo_alias.rs @@ -1,7 +1,8 @@ use derive_more::Display; +use serde::Serialize; use crate::newtype; -newtype!(RepoAlias: String, Display, Default, PartialOrd, Ord: r#"The alias of a repo. +newtype!(RepoAlias: String, Display, Default, PartialOrd, Ord, Serialize: r#"The alias of a repo. This is the alias for the repo within `git-next-server.toml`."#); diff --git a/crates/git/Cargo.toml b/crates/git/Cargo.toml index 48d9666..e60d092 100644 --- a/crates/git/Cargo.toml +++ b/crates/git/Cargo.toml @@ -25,11 +25,13 @@ async-trait = { workspace = true } # fs/network kxio = { workspace = true } -# # TOML parsing -# serde = { workspace = true } +# TOML parsing serde_json = { workspace = true } # toml = { workspace = true } +# webhooks - user notification +serde = { workspace = true } + # Secrets and Password secrecy = { workspace = true } diff --git a/crates/git/src/commit.rs b/crates/git/src/commit.rs index 045d223..443a780 100644 --- a/crates/git/src/commit.rs +++ b/crates/git/src/commit.rs @@ -2,6 +2,7 @@ use config::newtype; use derive_more::Display; // use git_next_config as config; +use serde::Serialize; #[derive( Clone, @@ -13,6 +14,7 @@ use git_next_config as config; Ord, derive_more::Constructor, derive_more::Display, + Serialize, )] #[display("{}", sha)] pub struct Commit { @@ -37,8 +39,8 @@ impl From for Commit { } } -newtype!(Sha: String, Display, Hash,PartialOrd, Ord: "The unique SHA for a git commit."); -newtype!(Message: String, Hash, PartialOrd, Ord: "The commit message for a git commit."); +newtype!(Sha: String, Display, Hash,PartialOrd, Ord, Serialize: "The unique SHA for a git commit."); +newtype!(Message: String, Display, Hash, PartialOrd, Ord, Serialize: "The commit message for a git commit."); #[derive(Clone, Debug)] pub struct Histories { diff --git a/crates/repo-actor/Cargo.toml b/crates/repo-actor/Cargo.toml index 11e7418..45fdba0 100644 --- a/crates/repo-actor/Cargo.toml +++ b/crates/repo-actor/Cargo.toml @@ -43,6 +43,7 @@ git-conventional = { workspace = true } # Webhooks bytes = { workspace = true } ulid = { workspace = true } +time = { workspace = true } # boilerplate derive_more = { workspace = true } diff --git a/crates/repo-actor/src/lib.rs b/crates/repo-actor/src/lib.rs index 73c2bfc..37767d7 100644 --- a/crates/repo-actor/src/lib.rs +++ b/crates/repo-actor/src/lib.rs @@ -2,6 +2,7 @@ mod branch; pub mod handlers; mod load; pub mod messages; +mod notifications; #[cfg(test)] mod tests; diff --git a/crates/repo-actor/src/notifications.rs b/crates/repo-actor/src/notifications.rs new file mode 100644 index 0000000..0adbd84 --- /dev/null +++ b/crates/repo-actor/src/notifications.rs @@ -0,0 +1,72 @@ +use derive_more::Deref as _; +use git_next_git::UserNotification; +use serde_json::json; + +use crate::messages::NotifyUser; + +impl From for serde_json::Value { + fn from(value: NotifyUser) -> Self { + let timestamp = time::OffsetDateTime::now_utc().unix_timestamp().to_string(); + match value.deref() { + UserNotification::CICheckFailed { + forge_alias, + repo_alias, + commit, + } => json!({ + "type": "cicheck.failed", + "timestamp": timestamp, + "data": { + "forge_alias": forge_alias, + "repo_alias": repo_alias, + "commit": { + "sha": commit.sha(), + "message": commit.message() + } + } + }), + UserNotification::RepoConfigLoadFailure { + forge_alias, + repo_alias, + reason, + } => json!({ + "type": "config.load.failed", + "timestamp": timestamp, + "data": { + "forge_alias": forge_alias, + "repo_alias": repo_alias, + "reason": reason + } + }), + UserNotification::WebhookRegistration { + forge_alias, + repo_alias, + reason, + } => json!({ + "type": "webhook.registration.failed", + "timestamp": timestamp, + "data": { + "forge_alias": forge_alias, + "repo_alias": repo_alias, + "reason": reason + } + }), + UserNotification::DevNotBasedOnMain { + forge_alias, + repo_alias, + dev_branch, + main_branch, + } => json!({ + "type": "branch.dev.not-on-main", + "timestamp": timestamp, + "data": { + "forge_alias": forge_alias, + "repo_alias": repo_alias, + "branches": { + "dev": dev_branch, + "main": main_branch + } + } + }), + } + } +} diff --git a/crates/server-actor/Cargo.toml b/crates/server-actor/Cargo.toml index e0a42eb..924e824 100644 --- a/crates/server-actor/Cargo.toml +++ b/crates/server-actor/Cargo.toml @@ -28,6 +28,10 @@ derive-with = { workspace = true } # Actors actix = { workspace = true } +# Webhooks +serde = { workspace = true } +serde_json = { workspace = true } + [dev-dependencies] # Testing # assert2 = { workspace = true } diff --git a/crates/server-actor/src/handlers/notify_user.rs b/crates/server-actor/src/handlers/notify_user.rs index 23ee70f..ac62591 100644 --- a/crates/server-actor/src/handlers/notify_user.rs +++ b/crates/server-actor/src/handlers/notify_user.rs @@ -1,4 +1,5 @@ // + use actix::prelude::*; use git_next_repo_actor::messages::NotifyUser; @@ -7,7 +8,9 @@ use crate::ServerActor; impl Handler for ServerActor { type Result = (); - fn handle(&mut self, _msg: NotifyUser, _ctx: &mut Self::Context) -> Self::Result { + fn handle(&mut self, msg: NotifyUser, _ctx: &mut Self::Context) -> Self::Result { + let _payload = serde_json::Value::from(msg); + tracing::info!("{}", _payload.to_string()); // TODO: (#95) should notify user // send post to notification webhook url } diff --git a/crates/server-actor/src/handlers/receive_valid_server_config.rs b/crates/server-actor/src/handlers/receive_valid_server_config.rs index 7fab4b1..990930e 100644 --- a/crates/server-actor/src/handlers/receive_valid_server_config.rs +++ b/crates/server-actor/src/handlers/receive_valid_server_config.rs @@ -15,7 +15,7 @@ impl Handler for ServerActor { socket_address, server_storage, } = msg.unwrap(); - if let Some(webhook) = self.webhook.take() { + if let Some(webhook) = self.webhook_actor_addr.take() { webhook.do_send(ShutdownWebhook); } self.generation.inc(); @@ -52,6 +52,6 @@ impl Handler for ServerActor { }); } let webhook = WebhookActor::new(socket_address, webhook_router.recipient()).start(); - self.webhook.replace(webhook); + self.webhook_actor_addr.replace(webhook); } } diff --git a/crates/server-actor/src/handlers/shutdown.rs b/crates/server-actor/src/handlers/shutdown.rs index f046037..c421149 100644 --- a/crates/server-actor/src/handlers/shutdown.rs +++ b/crates/server-actor/src/handlers/shutdown.rs @@ -16,7 +16,7 @@ impl Handler for ServerActor { tracing::debug!(%forge_alias, %repo_alias, "removed webhook"); }); tracing::debug!("server shutdown"); - if let Some(webhook) = self.webhook.take() { + if let Some(webhook) = self.webhook_actor_addr.take() { tracing::debug!("shuting down webhook"); webhook.do_send(ShutdownWebhook); tracing::debug!("webhook shutdown"); diff --git a/crates/server-actor/src/lib.rs b/crates/server-actor/src/lib.rs index 597d048..b544304 100644 --- a/crates/server-actor/src/lib.rs +++ b/crates/server-actor/src/lib.rs @@ -46,7 +46,7 @@ type Result = core::result::Result; #[with(message_log)] pub struct ServerActor { generation: Generation, - webhook: Option>, + webhook_actor_addr: Option>, fs: FileSystem, net: Network, repository_factory: Box, @@ -70,7 +70,7 @@ impl ServerActor { let generation = Generation::default(); Self { generation, - webhook: None, + webhook_actor_addr: None, fs, net, repository_factory: repo,