Compare commits

...

1 commit

Author SHA1 Message Date
346920cde5 WIP: feat: configure a webhook for receiving notifications
All checks were successful
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful
ci/woodpecker/push/push-next Pipeline was successful
2024-07-19 07:37:24 +01:00
4 changed files with 86 additions and 1 deletions

View file

@ -42,6 +42,7 @@ type Result<T> = core::result::Result<T, Error>;
pub struct ServerConfig { pub struct ServerConfig {
http: Http, http: Http,
webhook: Webhook, webhook: Webhook,
notifications: Notification,
storage: ServerStorage, storage: ServerStorage,
pub forge: BTreeMap<String, ForgeConfig>, pub forge: BTreeMap<String, ForgeConfig>,
} }
@ -64,6 +65,10 @@ impl ServerConfig {
&self.storage &self.storage
} }
pub const fn notifications(&self) -> &Notification {
&self.notifications
}
pub const fn webhook(&self) -> &Webhook { pub const fn webhook(&self) -> &Webhook {
&self.webhook &self.webhook
} }
@ -149,3 +154,63 @@ impl ServerStorage {
self.path.as_path() self.path.as_path()
} }
} }
/// Identifier for the type of Notification
#[derive(
Clone,
Default,
Debug,
derive_more::From,
PartialEq,
Eq,
PartialOrd,
Ord,
serde::Deserialize,
Copy,
)]
pub enum NotificationType {
#[default]
None,
Webhook,
}
/// Defines the Webhook Forges should send updates to
/// Must be an address that is accessible from the remote forge
#[derive(
Clone,
Debug,
derive_more::From,
PartialEq,
Eq,
PartialOrd,
Ord,
derive_more::AsRef,
serde::Deserialize,
)]
pub struct Notification {
r#type: NotificationType,
webhook: Option<Webhook>,
}
impl Notification {
pub const fn none() -> Self {
Self {
r#type: NotificationType::None,
webhook: None,
}
}
pub const fn webhook(webhook: Webhook) -> Self {
Self {
r#type: NotificationType::Webhook,
webhook: Some(webhook),
}
}
pub fn webhook_url(&self) -> Option<String> {
self.webhook.clone().map(|x| x.url)
}
}
impl Default for Notification {
fn default() -> Self {
Self::none()
}
}

View file

@ -470,6 +470,10 @@ mod server {
let http_port = server_config.http()?.port(); let http_port = server_config.http()?.port();
let webhook_url = server_config.webhook().base_url(); let webhook_url = server_config.webhook().base_url();
let storage_path = server_config.storage().path(); let storage_path = server_config.storage().path();
let notification_webhook_url = server_config
.notifications()
.webhook_url()
.unwrap_or_default();
let forge_alias = server_config let forge_alias = server_config
.forges() .forges()
.next() .next()
@ -519,6 +523,10 @@ url = "{webhook_url}"
[storage] [storage]
path = {storage_path:?} path = {storage_path:?}
[notifications]
type = "Webhook"
webhook = {{ url = "{notification_webhook_url}" }}
[forge.{forge_alias}] [forge.{forge_alias}]
forge_type = "{forge_type}" forge_type = "{forge_type}"
hostname = "{forge_hostname}" hostname = "{forge_hostname}"
@ -687,6 +695,8 @@ mod push {
} }
mod given { mod given {
use crate::server::Notification;
use super::*; use super::*;
use rand::Rng as _; use rand::Rng as _;
use std::{ use std::{
@ -710,6 +720,7 @@ mod given {
ServerConfig::new( ServerConfig::new(
an_http(), an_http(),
a_webhook(), a_webhook(),
a_notification_config(),
a_server_storage(), a_server_storage(),
some_forge_configs(), some_forge_configs(),
) )
@ -736,6 +747,9 @@ mod given {
pub fn a_server_storage() -> ServerStorage { pub fn a_server_storage() -> ServerStorage {
ServerStorage::new(a_name().into()) ServerStorage::new(a_name().into())
} }
pub fn a_notification_config() -> Notification {
Notification::webhook(a_webhook())
}
pub fn some_forge_configs() -> BTreeMap<String, ForgeConfig> { pub fn some_forge_configs() -> BTreeMap<String, ForgeConfig> {
[(a_name(), a_forge_config())].into() [(a_name(), a_forge_config())].into()
} }

View file

@ -1,7 +1,7 @@
// //
use crate::{tests::given, ReceiveServerConfig, Server}; use crate::{tests::given, ReceiveServerConfig, Server};
use actix::prelude::*; use actix::prelude::*;
use git_next_config::server::{Http, ServerConfig, ServerStorage, Webhook}; use git_next_config::server::{Http, Notification, ServerConfig, ServerStorage, Webhook};
use std::{ use std::{
collections::BTreeMap, collections::BTreeMap,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
@ -22,6 +22,7 @@ async fn when_webhook_url_has_trailing_slash_should_not_send() {
// collaborators // collaborators
let http = Http::new("0.0.0.0".to_string(), 80); let http = Http::new("0.0.0.0".to_string(), 80);
let webhook = Webhook::new("http://localhost/".to_string()); // With trailing slash let webhook = Webhook::new("http://localhost/".to_string()); // With trailing slash
let notifications = Notification::none();
let server_storage = ServerStorage::new((fs.base()).to_path_buf()); let server_storage = ServerStorage::new((fs.base()).to_path_buf());
let repos = BTreeMap::default(); let repos = BTreeMap::default();
@ -35,6 +36,7 @@ async fn when_webhook_url_has_trailing_slash_should_not_send() {
.do_send(ReceiveServerConfig::new(ServerConfig::new( .do_send(ReceiveServerConfig::new(ServerConfig::new(
http, http,
webhook, webhook,
notifications,
server_storage, server_storage,
repos, repos,
))); )));

View file

@ -8,6 +8,10 @@ url = "https://localhost:8080" # don't include any query path or a trailing slas
[storage] [storage]
path = "./data" path = "./data"
[notifications]
type = "WebHook"
webhook = { url = "https://localhost:9090" }
[forge] [forge]
[forge.default] [forge.default]