forked from kemitix/git-next
feat(server/webhook): implement register webhook
Closes kemitix/git-next#15
This commit is contained in:
parent
e7060800eb
commit
dd91aa4f69
7 changed files with 116 additions and 54 deletions
|
@ -4,7 +4,6 @@ use kxio::network::{self, Network};
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
|
|
||||||
use crate::server::{
|
use crate::server::{
|
||||||
actors::repo::ValidateRepo,
|
|
||||||
config::{self, RepoConfig, RepoDetails},
|
config::{self, RepoConfig, RepoDetails},
|
||||||
forge::{self, CommitHistories},
|
forge::{self, CommitHistories},
|
||||||
git::Git,
|
git::Git,
|
||||||
|
@ -27,7 +26,6 @@ pub async fn validate_positions(
|
||||||
Ok(commit_histories) => commit_histories,
|
Ok(commit_histories) => commit_histories,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(?err, "Failed to get commit histories");
|
error!(?err, "Failed to get commit histories");
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -35,20 +33,17 @@ pub async fn validate_positions(
|
||||||
// Validations
|
// Validations
|
||||||
let Some(main) = commit_histories.main.first().cloned() else {
|
let Some(main) = commit_histories.main.first().cloned() else {
|
||||||
warn!("No commits on main branch '{}'", config.branches().main());
|
warn!("No commits on main branch '{}'", config.branches().main());
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
// verify that next is an ancestor of dev, and force update to it main if it isn't
|
// verify that next is an ancestor of dev, and force update to it main if it isn't
|
||||||
let Some(next) = commit_histories.next.first().cloned() else {
|
let Some(next) = commit_histories.next.first().cloned() else {
|
||||||
warn!("No commits on next branch '{}", config.branches().next());
|
warn!("No commits on next branch '{}", config.branches().next());
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let next_is_ancestor_of_dev = commit_histories.dev.iter().any(|dev| dev == &next);
|
let next_is_ancestor_of_dev = commit_histories.dev.iter().any(|dev| dev == &next);
|
||||||
if !next_is_ancestor_of_dev {
|
if !next_is_ancestor_of_dev {
|
||||||
info!("Next is not an ancestor of dev - resetting next to main");
|
info!("Next is not an ancestor of dev - resetting next to main");
|
||||||
reset_next_to_main(next, main, &repo_details, &config, &git);
|
reset_next_to_main(next, main, &repo_details, &config, &git);
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,12 +59,10 @@ pub async fn validate_positions(
|
||||||
config.branches().next()
|
config.branches().next()
|
||||||
);
|
);
|
||||||
reset_next_to_main(next, main, &repo_details, &config, &git);
|
reset_next_to_main(next, main, &repo_details, &config, &git);
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let Some(next) = next_commits.first().cloned() else {
|
let Some(next) = next_commits.first().cloned() else {
|
||||||
warn!("No commits on next branch '{}'", config.branches().next());
|
warn!("No commits on next branch '{}'", config.branches().next());
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let dev_has_next = commit_histories
|
let dev_has_next = commit_histories
|
||||||
|
@ -82,7 +75,6 @@ pub async fn validate_positions(
|
||||||
config.branches().dev(),
|
config.branches().dev(),
|
||||||
config.branches().next()
|
config.branches().next()
|
||||||
);
|
);
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return; // dev is not based on next
|
return; // dev is not based on next
|
||||||
}
|
}
|
||||||
let dev_has_main = commit_histories.dev.iter().any(|commit| commit == &main);
|
let dev_has_main = commit_histories.dev.iter().any(|commit| commit == &main);
|
||||||
|
@ -93,12 +85,10 @@ pub async fn validate_positions(
|
||||||
config.branches().main(),
|
config.branches().main(),
|
||||||
config.branches().main(),
|
config.branches().main(),
|
||||||
);
|
);
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let Some(dev) = commit_histories.dev.first().cloned() else {
|
let Some(dev) = commit_histories.dev.first().cloned() else {
|
||||||
warn!("No commits on dev branch '{}'", config.branches().dev());
|
warn!("No commits on dev branch '{}'", config.branches().dev());
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
addr.do_send(StartMonitoring {
|
addr.do_send(StartMonitoring {
|
||||||
|
@ -144,12 +134,6 @@ fn reset_next_to_main(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn revalidate_positions(addr: Addr<RepoActor>) {
|
|
||||||
// TODO : (#43) sleep and restart while we don't have webhooks
|
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
|
|
||||||
addr.do_send(ValidateRepo)
|
|
||||||
}
|
|
||||||
|
|
||||||
// advance next to the next commit towards the head of the dev branch
|
// advance next to the next commit towards the head of the dev branch
|
||||||
#[tracing::instrument(fields(next), skip_all)]
|
#[tracing::instrument(fields(next), skip_all)]
|
||||||
pub async fn advance_next(
|
pub async fn advance_next(
|
||||||
|
@ -157,18 +141,15 @@ pub async fn advance_next(
|
||||||
dev_commit_history: Vec<forge::Commit>,
|
dev_commit_history: Vec<forge::Commit>,
|
||||||
repo_details: config::RepoDetails,
|
repo_details: config::RepoDetails,
|
||||||
repo_config: config::RepoConfig,
|
repo_config: config::RepoConfig,
|
||||||
addr: Addr<RepoActor>,
|
|
||||||
git: Git,
|
git: Git,
|
||||||
) {
|
) {
|
||||||
let next_commit = find_next_commit_on_dev(next, dev_commit_history);
|
let next_commit = find_next_commit_on_dev(next, dev_commit_history);
|
||||||
let Some(commit) = next_commit else {
|
let Some(commit) = next_commit else {
|
||||||
warn!("No commits to advance next to");
|
warn!("No commits to advance next to");
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if let Some(problem) = validate_commit_message(commit.message()) {
|
if let Some(problem) = validate_commit_message(commit.message()) {
|
||||||
warn!("Can't advance next to commit '{}': {}", commit, problem);
|
warn!("Can't advance next to commit '{}': {}", commit, problem);
|
||||||
revalidate_positions(addr).await;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info!("Advancing next to commit '{}'", commit);
|
info!("Advancing next to commit '{}'", commit);
|
||||||
|
@ -180,7 +161,6 @@ pub async fn advance_next(
|
||||||
) {
|
) {
|
||||||
warn!(?err, "Failed")
|
warn!(?err, "Failed")
|
||||||
};
|
};
|
||||||
revalidate_positions(addr).await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
|
|
|
@ -8,7 +8,7 @@ use kxio::network::Network;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
use crate::server::{
|
use crate::server::{
|
||||||
config::{RepoConfig, RepoDetails},
|
config::{RepoConfig, RepoDetails, Webhook},
|
||||||
forge,
|
forge,
|
||||||
git::Git,
|
git::Git,
|
||||||
};
|
};
|
||||||
|
@ -17,17 +17,24 @@ use self::webhook::WebhookId;
|
||||||
|
|
||||||
pub struct RepoActor {
|
pub struct RepoActor {
|
||||||
details: RepoDetails,
|
details: RepoDetails,
|
||||||
config: Option<RepoConfig>, // INFO: if [None] then send [StartRepo] to populate it
|
webhook: Webhook,
|
||||||
webhook_id: Option<WebhookId>, // INFO: if [None] then no webhook is configured
|
webhook_id: Option<WebhookId>, // INFO: if [None] then no webhook is configured
|
||||||
|
webhook_auth: Option<ulid::Ulid>,
|
||||||
net: Network,
|
net: Network,
|
||||||
git: Git,
|
git: Git,
|
||||||
}
|
}
|
||||||
impl RepoActor {
|
impl RepoActor {
|
||||||
pub(crate) const fn new(details: RepoDetails, net: Network, git: Git) -> Self {
|
pub(crate) const fn new(
|
||||||
|
details: RepoDetails,
|
||||||
|
webhook: Webhook,
|
||||||
|
net: Network,
|
||||||
|
git: Git,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
details,
|
details,
|
||||||
config: None,
|
webhook,
|
||||||
webhook_id: None,
|
webhook_id: None,
|
||||||
|
webhook_auth: None,
|
||||||
net,
|
net,
|
||||||
git,
|
git,
|
||||||
}
|
}
|
||||||
|
@ -72,7 +79,18 @@ impl Handler<LoadedConfig> for RepoActor {
|
||||||
fn handle(&mut self, msg: LoadedConfig, ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: LoadedConfig, ctx: &mut Self::Context) -> Self::Result {
|
||||||
let config = msg.0;
|
let config = msg.0;
|
||||||
info!(%self.details, %config, "Config loaded");
|
info!(%self.details, %config, "Config loaded");
|
||||||
self.config.replace(config);
|
self.details.config.replace(config);
|
||||||
|
if self.webhook_id.is_none() {
|
||||||
|
info!("lets register the webhook...");
|
||||||
|
webhook::register(
|
||||||
|
self.details.clone(),
|
||||||
|
self.webhook.clone(),
|
||||||
|
ctx.address(),
|
||||||
|
self.net.clone(),
|
||||||
|
)
|
||||||
|
.into_actor(self)
|
||||||
|
.wait(ctx);
|
||||||
|
}
|
||||||
ctx.address().do_send(ValidateRepo);
|
ctx.address().do_send(ValidateRepo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +101,7 @@ pub struct ValidateRepo;
|
||||||
impl Handler<ValidateRepo> for RepoActor {
|
impl Handler<ValidateRepo> for RepoActor {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
fn handle(&mut self, _msg: ValidateRepo, ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, _msg: ValidateRepo, ctx: &mut Self::Context) -> Self::Result {
|
||||||
if let Some(repo_config) = self.config.clone() {
|
if let Some(repo_config) = self.details.config.clone() {
|
||||||
let repo_details = self.details.clone();
|
let repo_details = self.details.clone();
|
||||||
let addr = ctx.address();
|
let addr = ctx.address();
|
||||||
let net = self.net.clone();
|
let net = self.net.clone();
|
||||||
|
@ -106,7 +124,7 @@ pub struct StartMonitoring {
|
||||||
impl Handler<StartMonitoring> for RepoActor {
|
impl Handler<StartMonitoring> for RepoActor {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
fn handle(&mut self, msg: StartMonitoring, ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: StartMonitoring, ctx: &mut Self::Context) -> Self::Result {
|
||||||
let Some(repo_config) = self.config.clone() else {
|
let Some(repo_config) = self.details.config.clone() else {
|
||||||
warn!("No config loaded");
|
warn!("No config loaded");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -116,6 +134,7 @@ impl Handler<StartMonitoring> for RepoActor {
|
||||||
info!(%msg.main, %msg.next, %msg.dev, next_ahead_of_main, dev_ahead_of_next, "StartMonitoring");
|
info!(%msg.main, %msg.next, %msg.dev, next_ahead_of_main, dev_ahead_of_next, "StartMonitoring");
|
||||||
|
|
||||||
let repo_details = self.details.clone();
|
let repo_details = self.details.clone();
|
||||||
|
let webhook = self.webhook.clone();
|
||||||
let addr = ctx.address();
|
let addr = ctx.address();
|
||||||
let net = self.net.clone();
|
let net = self.net.clone();
|
||||||
let git = self.git.clone();
|
let git = self.git.clone();
|
||||||
|
@ -130,13 +149,12 @@ impl Handler<StartMonitoring> for RepoActor {
|
||||||
msg.dev_commit_history,
|
msg.dev_commit_history,
|
||||||
repo_details,
|
repo_details,
|
||||||
repo_config,
|
repo_config,
|
||||||
addr,
|
|
||||||
git,
|
git,
|
||||||
)
|
)
|
||||||
.into_actor(self)
|
.into_actor(self)
|
||||||
.wait(ctx);
|
.wait(ctx);
|
||||||
} else if self.webhook_id.is_none() {
|
} else if self.webhook_id.is_none() {
|
||||||
webhook::register(repo_details, addr, net)
|
webhook::register(repo_details, webhook, addr, net)
|
||||||
.into_actor(self)
|
.into_actor(self)
|
||||||
.wait(ctx);
|
.wait(ctx);
|
||||||
}
|
}
|
||||||
|
@ -145,11 +163,12 @@ impl Handler<StartMonitoring> for RepoActor {
|
||||||
|
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
pub struct WebhookRegistered(pub WebhookId);
|
pub struct WebhookRegistered(pub WebhookId, pub ulid::Ulid);
|
||||||
impl Handler<WebhookRegistered> for RepoActor {
|
impl Handler<WebhookRegistered> for RepoActor {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
fn handle(&mut self, msg: WebhookRegistered, _ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: WebhookRegistered, _ctx: &mut Self::Context) -> Self::Result {
|
||||||
self.webhook_id.replace(msg.0);
|
self.webhook_id.replace(msg.0);
|
||||||
|
self.webhook_auth.replace(msg.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +179,7 @@ impl Handler<AdvanceMainTo> for RepoActor {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
fn handle(&mut self, msg: AdvanceMainTo, ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: AdvanceMainTo, ctx: &mut Self::Context) -> Self::Result {
|
||||||
let repo_details = self.details.clone();
|
let repo_details = self.details.clone();
|
||||||
let Some(repo_config) = self.config.clone() else {
|
let Some(repo_config) = self.details.config.clone() else {
|
||||||
warn!("No config loaded");
|
warn!("No config loaded");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,6 @@ use gix::trace::warn;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::server::{
|
use crate::server::{
|
||||||
actors::repo::ValidateRepo,
|
|
||||||
config::{self, ForgeType},
|
config::{self, ForgeType},
|
||||||
forge,
|
forge,
|
||||||
};
|
};
|
||||||
|
@ -37,9 +36,6 @@ pub async fn check_next(
|
||||||
warn!("Checks have failed");
|
warn!("Checks have failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO : (#43) sleep and restart while we don't have webhooks
|
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
|
|
||||||
addr.do_send(ValidateRepo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
use kxio::network;
|
use kxio::network::{self, json};
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
use std::{fmt::Display, ops::Deref};
|
use std::{fmt::Display, ops::Deref};
|
||||||
|
|
||||||
use crate::server::actors::{
|
use crate::server::{
|
||||||
repo::{RepoActor, ValidateRepo},
|
actors::{
|
||||||
|
repo::{RepoActor, WebhookRegistered},
|
||||||
webhook::WebhookMessage,
|
webhook::WebhookMessage,
|
||||||
|
},
|
||||||
|
config::Webhook,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
@ -37,8 +40,10 @@ pub async fn unregister(
|
||||||
info!(?webhook_id, "unregister webhook");
|
info!(?webhook_id, "unregister webhook");
|
||||||
let hostname = &repo_details.forge.hostname;
|
let hostname = &repo_details.forge.hostname;
|
||||||
let path = repo_details.repo;
|
let path = repo_details.repo;
|
||||||
|
use secrecy::ExposeSecret;
|
||||||
|
let token = repo_details.forge.token.expose_secret();
|
||||||
let url = network::NetUrl::new(format!(
|
let url = network::NetUrl::new(format!(
|
||||||
"https://{hostname}/api/v1/repos/{path}/hooks/{webhook_id}"
|
"https://{hostname}/api/v1/repos/{path}/hooks/{webhook_id}?token={token}"
|
||||||
));
|
));
|
||||||
let request = network::NetRequest::new(
|
let request = network::NetRequest::new(
|
||||||
network::RequestMethod::Delete,
|
network::RequestMethod::Delete,
|
||||||
|
@ -57,13 +62,66 @@ pub async fn unregister(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn register(
|
pub async fn register(
|
||||||
_repo_details: crate::server::config::RepoDetails,
|
repo_details: crate::server::config::RepoDetails,
|
||||||
|
webhook: Webhook,
|
||||||
addr: actix::prelude::Addr<super::RepoActor>,
|
addr: actix::prelude::Addr<super::RepoActor>,
|
||||||
_net: network::Network,
|
net: network::Network,
|
||||||
) {
|
) {
|
||||||
// TODO: (#15) register webhook - on success send webhook id to RepoActor
|
let Some(repo_config) = repo_details.config else {
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
|
return;
|
||||||
addr.do_send(ValidateRepo);
|
};
|
||||||
|
info!("Registering webhook");
|
||||||
|
let hostname = &repo_details.forge.hostname;
|
||||||
|
let path = repo_details.repo;
|
||||||
|
use secrecy::ExposeSecret;
|
||||||
|
let token = repo_details.forge.token.expose_secret();
|
||||||
|
let url = network::NetUrl::new(format!(
|
||||||
|
"https://{hostname}/api/v1/repos/{path}/hooks?token={token}"
|
||||||
|
));
|
||||||
|
let webhook_url = webhook.url();
|
||||||
|
let repo_alias = repo_details.name;
|
||||||
|
let headers = network::NetRequestHeaders::new().with("Content-Type", "application/json");
|
||||||
|
let authorisation = ulid::Ulid::new();
|
||||||
|
let body = json!({
|
||||||
|
"active": true,
|
||||||
|
"authorization_header": format!("Basic {}", authorisation),
|
||||||
|
"branch_filter": format!("{{{},{},{}}}", repo_config.branches().main(), repo_config.branches().next(), repo_config.branches().dev()),
|
||||||
|
"config": {
|
||||||
|
"content_type": "json",
|
||||||
|
"url": format!("{}/{}", webhook_url.as_ref(), repo_alias),
|
||||||
|
},
|
||||||
|
"events": [ "push" ],
|
||||||
|
"type": "forgejo"
|
||||||
|
});
|
||||||
|
let request = network::NetRequest::new(
|
||||||
|
network::RequestMethod::Post,
|
||||||
|
url,
|
||||||
|
headers,
|
||||||
|
network::RequestBody::Json(body),
|
||||||
|
network::ResponseType::Json,
|
||||||
|
None,
|
||||||
|
network::NetRequestLogging::None,
|
||||||
|
);
|
||||||
|
let result = net.post_json::<Hook>(request).await;
|
||||||
|
match result {
|
||||||
|
Ok(response) => {
|
||||||
|
if let Some(hook) = response.response_body() {
|
||||||
|
info!("Webhook registered");
|
||||||
|
addr.do_send(WebhookRegistered(hook.id(), authorisation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => warn!("Failed to register webhook"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
struct Hook {
|
||||||
|
id: i64,
|
||||||
|
}
|
||||||
|
impl Hook {
|
||||||
|
fn id(&self) -> WebhookId {
|
||||||
|
WebhookId(format!("{}", self.id))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handler<WebhookMessage> for RepoActor {
|
impl Handler<WebhookMessage> for RepoActor {
|
||||||
|
|
|
@ -26,10 +26,14 @@ impl ServerConfig {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, forge)| (ForgeName(name.clone()), forge))
|
.map(|(name, forge)| (ForgeName(name.clone()), forge))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn webhook(&self) -> &Webhook {
|
||||||
|
&self.webhook
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines the Webhook Forges should send updates to
|
/// Defines the Webhook Forges should send updates to
|
||||||
#[derive(Debug, PartialEq, Eq, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
||||||
pub struct Webhook {
|
pub struct Webhook {
|
||||||
url: String,
|
url: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use kxio::network::{self, Network};
|
use kxio::network::{self, Network};
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
use terrors::OneOf;
|
use terrors::OneOf;
|
||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
|
|
||||||
|
@ -34,6 +33,7 @@ pub async fn load(
|
||||||
let path = &details.repo;
|
let path = &details.repo;
|
||||||
let filepath = ".git-next.toml";
|
let filepath = ".git-next.toml";
|
||||||
let branch = &details.branch;
|
let branch = &details.branch;
|
||||||
|
use secrecy::ExposeSecret;
|
||||||
let token = details.forge.token.expose_secret();
|
let token = details.forge.token.expose_secret();
|
||||||
let url = network::NetUrl::new(format!(
|
let url = network::NetUrl::new(format!(
|
||||||
"https://{hostname}/api/v1/repos/{path}/contents/{filepath}?ref={branch}&token={token}"
|
"https://{hostname}/api/v1/repos/{path}/contents/{filepath}?ref={branch}&token={token}"
|
||||||
|
@ -128,6 +128,7 @@ pub async fn validate(
|
||||||
) -> Result<RepoConfig, OneOf<RepoConfigValidateErrors>> {
|
) -> Result<RepoConfig, OneOf<RepoConfigValidateErrors>> {
|
||||||
let hostname = &details.forge.hostname;
|
let hostname = &details.forge.hostname;
|
||||||
let path = &details.repo;
|
let path = &details.repo;
|
||||||
|
use secrecy::ExposeSecret;
|
||||||
let token = details.forge.token.expose_secret();
|
let token = details.forge.token.expose_secret();
|
||||||
let url = network::NetUrl::new(format!(
|
let url = network::NetUrl::new(format!(
|
||||||
"https://{hostname}/api/v1/repos/{path}/branches?token={token}"
|
"https://{hostname}/api/v1/repos/{path}/branches?token={token}"
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
filesystem::FileSystem,
|
filesystem::FileSystem,
|
||||||
server::{
|
server::{
|
||||||
actors::webhook,
|
actors::webhook,
|
||||||
config::{Forge, ForgeName, RepoAlias},
|
config::{Forge, ForgeName, RepoAlias, Webhook},
|
||||||
git::Git,
|
git::Git,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -46,19 +46,19 @@ pub async fn start(fs: FileSystem, net: Network, git: Git) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
info!("Starting Server...");
|
info!("Starting Server...");
|
||||||
let config = match config::ServerConfig::load(&fs) {
|
let server_config = match config::ServerConfig::load(&fs) {
|
||||||
Ok(config) => config,
|
Ok(server_config) => server_config,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Failed to load config file. Error: {}", err);
|
error!("Failed to load config file. Error: {}", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Config loaded");
|
|
||||||
let webhook_router = webhook::WebhookRouter::new().start();
|
let webhook_router = webhook::WebhookRouter::new().start();
|
||||||
config
|
let webhook = server_config.webhook();
|
||||||
|
server_config
|
||||||
.forges()
|
.forges()
|
||||||
.flat_map(|(forge_name, forge)| create_forge_repos(forge, forge_name, &net, &git))
|
.flat_map(|(forge_name, forge)| create_forge_repos(forge, forge_name, webhook, &net, &git))
|
||||||
.map(start_actor)
|
.map(start_actor)
|
||||||
.map(|(alias, addr)| webhook::AddWebhookRecipient(alias, addr.recipient()))
|
.map(|(alias, addr)| webhook::AddWebhookRecipient(alias, addr.recipient()))
|
||||||
.for_each(|msg| webhook_router.do_send(msg));
|
.for_each(|msg| webhook_router.do_send(msg));
|
||||||
|
@ -71,6 +71,7 @@ pub async fn start(fs: FileSystem, net: Network, git: Git) {
|
||||||
fn create_forge_repos(
|
fn create_forge_repos(
|
||||||
forge: &Forge,
|
forge: &Forge,
|
||||||
forge_name: ForgeName,
|
forge_name: ForgeName,
|
||||||
|
webhook: &Webhook,
|
||||||
net: &Network,
|
net: &Network,
|
||||||
git: &Git,
|
git: &Git,
|
||||||
) -> Vec<(ForgeName, RepoAlias, RepoActor)> {
|
) -> Vec<(ForgeName, RepoAlias, RepoActor)> {
|
||||||
|
@ -80,16 +81,18 @@ fn create_forge_repos(
|
||||||
info!("Creating Forge");
|
info!("Creating Forge");
|
||||||
forge
|
forge
|
||||||
.repos()
|
.repos()
|
||||||
.map(create_actor(forge_name, forge.clone(), net, git))
|
.map(create_actor(forge_name, forge.clone(), webhook, net, git))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_actor(
|
fn create_actor(
|
||||||
forge_name: ForgeName,
|
forge_name: ForgeName,
|
||||||
forge: config::Forge,
|
forge: config::Forge,
|
||||||
|
webhook: &Webhook,
|
||||||
net: &Network,
|
net: &Network,
|
||||||
git: &Git,
|
git: &Git,
|
||||||
) -> impl Fn((RepoAlias, &Repo)) -> (ForgeName, RepoAlias, RepoActor) {
|
) -> impl Fn((RepoAlias, &Repo)) -> (ForgeName, RepoAlias, RepoActor) {
|
||||||
|
let webhook = webhook.clone();
|
||||||
let net = net.clone();
|
let net = net.clone();
|
||||||
let git = git.clone();
|
let git = git.clone();
|
||||||
move |(repo_name, repo)| {
|
move |(repo_name, repo)| {
|
||||||
|
@ -98,6 +101,7 @@ fn create_actor(
|
||||||
info!("Creating Repo");
|
info!("Creating Repo");
|
||||||
let actor = actors::repo::RepoActor::new(
|
let actor = actors::repo::RepoActor::new(
|
||||||
config::RepoDetails::new(&repo_name, repo, &forge_name, &forge),
|
config::RepoDetails::new(&repo_name, repo, &forge_name, &forge),
|
||||||
|
webhook.clone(),
|
||||||
net.clone(),
|
net.clone(),
|
||||||
git.clone(),
|
git.clone(),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue