git-next/src/server/actors/repo/mod.rs

235 lines
7.8 KiB
Rust
Raw Normal View History

mod branch;
2024-04-09 10:44:01 +01:00
mod config;
pub mod status;
pub mod webhook;
2024-04-09 10:44:01 +01:00
use actix::prelude::*;
use kxio::network::Network;
use tracing::{debug, info, warn, Instrument};
2024-04-09 10:44:01 +01:00
use crate::server::{
actors::repo::webhook::WebhookAuth,
config::{RepoConfig, RepoDetails, Webhook},
gitforge,
};
2024-04-09 10:44:01 +01:00
use self::webhook::WebhookId;
2024-04-09 10:44:01 +01:00
pub struct RepoActor {
span: tracing::Span,
2024-04-09 10:44:01 +01:00
details: RepoDetails,
webhook: Webhook,
webhook_id: Option<WebhookId>, // INFO: if [None] then no webhook is configured
webhook_auth: Option<WebhookAuth>, // INFO: if [None] then no webhook is configured
last_main_commit: Option<gitforge::Commit>,
last_next_commit: Option<gitforge::Commit>,
last_dev_commit: Option<gitforge::Commit>,
2024-04-09 10:44:01 +01:00
net: Network,
forge: gitforge::Forge,
2024-04-09 10:44:01 +01:00
}
impl RepoActor {
pub(crate) fn new(details: RepoDetails, webhook: Webhook, net: Network) -> Self {
let span = tracing::info_span!("RepoActor", repo = %details);
let forge = match details.forge.forge_type {
#[cfg(feature = "forgejo")]
crate::server::config::ForgeType::ForgeJo => {
gitforge::Forge::new_forgejo(details.clone(), net.clone())
}
#[cfg(test)]
crate::server::config::ForgeType::MockForge => gitforge::Forge::new_mock(),
};
debug!(?forge, "new");
2024-04-09 10:44:01 +01:00
Self {
span,
2024-04-09 10:44:01 +01:00
details,
webhook,
webhook_id: None,
webhook_auth: None,
last_main_commit: None,
last_next_commit: None,
last_dev_commit: None,
2024-04-09 10:44:01 +01:00
net,
forge,
2024-04-09 10:44:01 +01:00
}
}
}
impl Actor for RepoActor {
type Context = Context<Self>;
fn stopping(&mut self, ctx: &mut Self::Context) -> Running {
let _gaurd = self.span.enter();
info!("Checking webhook");
match self.webhook_id.take() {
Some(webhook_id) => {
let repo_details = self.details.clone();
let net = self.net.clone();
webhook::unregister(webhook_id, repo_details, net)
.in_current_span()
.into_actor(self)
.wait(ctx);
Running::Continue
}
None => Running::Stop,
}
}
2024-04-09 10:44:01 +01:00
}
impl std::fmt::Display for RepoActor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}/{}",
self.details.forge.forge_name, self.details.repo_alias
)
}
}
2024-04-09 10:44:01 +01:00
#[derive(Message)]
#[rtype(result = "()")]
2024-04-23 07:09:30 +01:00
pub struct CloneRepo;
impl Handler<CloneRepo> for RepoActor {
2024-04-09 10:44:01 +01:00
type Result = ();
#[tracing::instrument(name = "RepoActor::CloneRepo", skip_all, fields(repo = %self, gitdir = %self.details.gitdir))]
2024-04-23 07:09:30 +01:00
fn handle(&mut self, _msg: CloneRepo, ctx: &mut Self::Context) -> Self::Result {
info!("Message Received");
2024-04-23 07:09:30 +01:00
let gitdir = self.details.gitdir.clone();
match self.forge.repo_clone(gitdir) {
Ok(_) => ctx.address().do_send(LoadConfigFromRepo),
Err(err) => warn!("Could not Clone repo: {err}"),
2024-04-23 07:09:30 +01:00
}
}
}
#[derive(Message)]
#[rtype(result = "()")]
pub struct LoadConfigFromRepo;
impl Handler<LoadConfigFromRepo> for RepoActor {
type Result = ();
#[tracing::instrument(name = "RepoActor::LoadConfigFromRepo", skip_all, fields(repo = %self))]
2024-04-23 07:09:30 +01:00
fn handle(&mut self, _msg: LoadConfigFromRepo, ctx: &mut Self::Context) -> Self::Result {
info!("Message Received");
2024-04-09 10:44:01 +01:00
let details = self.details.clone();
let addr = ctx.address();
let forge = self.forge.clone();
config::load(details, addr, forge)
.in_current_span()
.into_actor(self)
.wait(ctx);
2024-04-09 10:44:01 +01:00
}
}
#[derive(Message)]
#[rtype(result = "()")]
struct LoadedConfig(pub RepoConfig);
impl Handler<LoadedConfig> for RepoActor {
type Result = ();
#[tracing::instrument(name = "RepoActor::LoadedConfig", skip_all, fields(repo = %self.details, branches = %msg.0))]
fn handle(&mut self, msg: LoadedConfig, ctx: &mut Self::Context) -> Self::Result {
info!("Message Received");
let repo_config = msg.0;
self.details.repo_config.replace(repo_config);
if self.webhook_id.is_none() {
webhook::register(
self.details.clone(),
self.webhook.clone(),
ctx.address(),
self.net.clone(),
)
.in_current_span()
.into_actor(self)
.wait(ctx);
}
ctx.address().do_send(ValidateRepo);
}
}
#[derive(Message)]
#[rtype(result = "()")]
pub struct ValidateRepo;
impl Handler<ValidateRepo> for RepoActor {
type Result = ();
#[tracing::instrument(name = "RepoActor::ValidateRepo", skip_all, fields(repo = %self.details))]
fn handle(&mut self, _msg: ValidateRepo, ctx: &mut Self::Context) -> Self::Result {
info!("Message Received");
if let Some(repo_config) = self.details.repo_config.clone() {
let forge = self.forge.clone();
let addr = ctx.address();
async move { forge.branches_validate_positions(repo_config, addr).await }
.in_current_span()
.into_actor(self)
.wait(ctx);
}
2024-04-09 10:44:01 +01:00
}
}
#[derive(Debug, Message)]
#[rtype(result = "()")]
pub struct StartMonitoring {
pub main: gitforge::Commit,
pub next: gitforge::Commit,
pub dev: gitforge::Commit,
pub dev_commit_history: Vec<gitforge::Commit>,
}
impl Handler<StartMonitoring> for RepoActor {
type Result = ();
#[tracing::instrument(name = "RepoActor::StartMonitoring", skip_all, fields(repo = %self.details, main = %msg.main, next= %msg.next, dev = %msg.dev))]
fn handle(&mut self, msg: StartMonitoring, ctx: &mut Self::Context) -> Self::Result {
info!("Message Received");
let Some(repo_config) = self.details.repo_config.clone() else {
warn!("No config loaded");
return;
};
let next_ahead_of_main = msg.main != msg.next;
let dev_ahead_of_next = msg.next != msg.dev;
info!(next_ahead_of_main, dev_ahead_of_next, "StartMonitoring");
let addr = ctx.address();
let forge = self.forge.clone();
if next_ahead_of_main {
status::check_next(msg.next, addr, forge)
.in_current_span()
.into_actor(self)
.wait(ctx);
} else if dev_ahead_of_next {
branch::advance_next(msg.next, msg.dev_commit_history, repo_config, forge, addr)
.in_current_span()
.into_actor(self)
.wait(ctx);
}
}
}
#[derive(Message)]
#[rtype(result = "()")]
pub struct WebhookRegistered(pub WebhookId, pub WebhookAuth);
impl Handler<WebhookRegistered> for RepoActor {
type Result = ();
#[tracing::instrument(name = "RepoActor::WebhookRegistered", skip_all, fields(webhook_id = %msg.0))]
fn handle(&mut self, msg: WebhookRegistered, _ctx: &mut Self::Context) -> Self::Result {
info!("Message Received");
self.webhook_id.replace(msg.0);
self.webhook_auth.replace(msg.1);
}
}
#[derive(Message)]
#[rtype(result = "()")]
pub struct AdvanceMainTo(pub gitforge::Commit);
impl Handler<AdvanceMainTo> for RepoActor {
type Result = ();
#[tracing::instrument(name = "RepoActor::AdvanceMainTo", skip_all, fields(commit = %msg.0))]
fn handle(&mut self, msg: AdvanceMainTo, ctx: &mut Self::Context) -> Self::Result {
info!("Message Received");
let Some(repo_config) = self.details.repo_config.clone() else {
warn!("No config loaded");
return;
};
let forge = self.forge.clone();
let addr = ctx.address();
branch::advance_main(msg.0, repo_config, forge, addr)
.in_current_span()
.into_actor(self)
.wait(ctx);
}
}