WIP: feat: configure a webhook for receiving notifications
All checks were successful
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful

This commit is contained in:
Paul Campbell 2024-07-18 20:51:47 +01:00
parent 8f95ae0058
commit 58b047cdb5
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 {
http: Http,
webhook: Webhook,
notifications: Notification,
storage: ServerStorage,
pub forge: BTreeMap<String, ForgeConfig>,
}
@ -64,6 +65,10 @@ impl ServerConfig {
&self.storage
}
pub const fn notifications(&self) -> &Notification {
&self.notifications
}
pub const fn webhook(&self) -> &Webhook {
&self.webhook
}
@ -149,3 +154,63 @@ impl ServerStorage {
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 webhook_url = server_config.webhook().base_url();
let storage_path = server_config.storage().path();
let notification_webhook_url = server_config
.notifications()
.webhook_url()
.unwrap_or_default();
let forge_alias = server_config
.forges()
.next()
@ -519,6 +523,10 @@ url = "{webhook_url}"
[storage]
path = {storage_path:?}
[notifications]
type = "Webhook"
webhook = {{ url = "{notification_webhook_url}" }}
[forge.{forge_alias}]
forge_type = "{forge_type}"
hostname = "{forge_hostname}"
@ -687,6 +695,8 @@ mod push {
}
mod given {
use crate::server::Notification;
use super::*;
use rand::Rng as _;
use std::{
@ -710,6 +720,7 @@ mod given {
ServerConfig::new(
an_http(),
a_webhook(),
a_notification_config(),
a_server_storage(),
some_forge_configs(),
)
@ -736,6 +747,9 @@ mod given {
pub fn a_server_storage() -> ServerStorage {
ServerStorage::new(a_name().into())
}
pub fn a_notification_config() -> Notification {
Notification::webhook(a_webhook())
}
pub fn some_forge_configs() -> BTreeMap<String, ForgeConfig> {
[(a_name(), a_forge_config())].into()
}

View file

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

View file

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