2024-04-09 15:31:59 +01:00
|
|
|
mod branch;
|
2024-06-19 07:03:08 +01:00
|
|
|
pub mod handlers;
|
2024-05-22 08:41:30 +01:00
|
|
|
mod load;
|
2024-06-19 07:03:08 +01:00
|
|
|
pub mod messages;
|
2024-04-09 10:44:01 +01:00
|
|
|
|
2024-05-14 07:59:31 +01:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests;
|
|
|
|
|
2024-04-09 10:44:01 +01:00
|
|
|
use actix::prelude::*;
|
2024-05-23 16:50:36 +01:00
|
|
|
|
2024-05-23 17:56:47 +01:00
|
|
|
use git_next_config as config;
|
2024-05-23 16:19:28 +01:00
|
|
|
use git_next_git as git;
|
2024-05-23 16:50:36 +01:00
|
|
|
|
2024-04-09 10:44:01 +01:00
|
|
|
use kxio::network::Network;
|
2024-06-19 07:03:08 +01:00
|
|
|
use tracing::{info, warn, Instrument};
|
|
|
|
|
|
|
|
pub type RepoActorLog = std::sync::Arc<std::sync::Mutex<Vec<String>>>;
|
|
|
|
|
|
|
|
/// An actor that represents a Git Repository.
|
|
|
|
///
|
|
|
|
/// When this actor is started it is sent the [CloneRepo] message.
|
|
|
|
///
|
|
|
|
/// ```mermaid
|
|
|
|
/// stateDiagram-v2
|
|
|
|
/// [*] --> CloneRepo :START
|
|
|
|
///
|
|
|
|
/// CloneRepo --> LoadConfigFromRepo
|
|
|
|
/// CloneRepo --> ValidateRepo
|
|
|
|
///
|
|
|
|
/// LoadConfigFromRepo --> LoadedConfig
|
|
|
|
///
|
|
|
|
/// ValidateRepo --> WebhookRegistered
|
|
|
|
/// ValidateRepo --> StartMonitoring
|
|
|
|
/// ValidateRepo --> ValidateRepo :SLEEP 10s
|
|
|
|
///
|
|
|
|
/// LoadedConfig --> ValidateRepo
|
|
|
|
///
|
|
|
|
/// WebhookRegistered --> [*]
|
|
|
|
///
|
|
|
|
/// StartMonitoring --> AdvanceMainTo
|
|
|
|
/// StartMonitoring --> ValidateRepo :SLEEP 10s
|
|
|
|
///
|
|
|
|
/// AdvanceMainTo --> LoadConfigFromRepo
|
|
|
|
/// AdvanceMainTo --> ValidateRepo
|
|
|
|
///
|
|
|
|
/// [*] --> WebhookMessage :WEBHOOK
|
|
|
|
///
|
|
|
|
/// WebhookMessage --> ValidateRepo
|
|
|
|
/// ```
|
|
|
|
///
|
2024-05-15 21:01:19 +01:00
|
|
|
#[derive(Debug, derive_more::Display)]
|
2024-05-29 19:22:05 +01:00
|
|
|
#[display("{}:{}:{}", generation, repo_details.forge.forge_alias(), repo_details.repo_alias)]
|
2024-04-09 10:44:01 +01:00
|
|
|
pub struct RepoActor {
|
2024-06-19 07:03:08 +01:00
|
|
|
sleep_duration: std::time::Duration,
|
2024-05-23 16:19:28 +01:00
|
|
|
generation: git::Generation,
|
2024-06-19 07:03:08 +01:00
|
|
|
message_token: messages::MessageToken,
|
2024-05-26 08:35:45 +01:00
|
|
|
repo_details: git::RepoDetails,
|
2024-05-23 17:56:47 +01:00
|
|
|
webhook: config::server::Webhook,
|
2024-05-25 11:25:13 +01:00
|
|
|
webhook_id: Option<config::WebhookId>, // INFO: if [None] then no webhook is configured
|
|
|
|
webhook_auth: Option<config::WebhookAuth>, // INFO: if [None] then no webhook is configured
|
2024-05-11 19:46:20 +01:00
|
|
|
last_main_commit: Option<git::Commit>,
|
|
|
|
last_next_commit: Option<git::Commit>,
|
|
|
|
last_dev_commit: Option<git::Commit>,
|
2024-06-19 07:03:08 +01:00
|
|
|
repository_factory: Box<dyn git::repository::RepositoryFactory>,
|
2024-06-19 16:40:10 +01:00
|
|
|
open_repository: Option<Box<dyn git::repository::OpenRepositoryLike>>,
|
2024-04-09 10:44:01 +01:00
|
|
|
net: Network,
|
2024-06-19 07:03:08 +01:00
|
|
|
forge: Box<dyn git::ForgeLike>,
|
|
|
|
log: Option<RepoActorLog>,
|
2024-04-09 10:44:01 +01:00
|
|
|
}
|
|
|
|
impl RepoActor {
|
2024-05-11 19:46:20 +01:00
|
|
|
pub fn new(
|
2024-06-19 07:03:08 +01:00
|
|
|
repo_details: git::RepoDetails,
|
|
|
|
forge: Box<dyn git::ForgeLike>,
|
2024-05-23 17:56:47 +01:00
|
|
|
webhook: config::server::Webhook,
|
2024-05-23 16:19:28 +01:00
|
|
|
generation: git::Generation,
|
2024-05-07 08:17:29 +01:00
|
|
|
net: Network,
|
2024-06-19 07:03:08 +01:00
|
|
|
repository_factory: Box<dyn git::repository::RepositoryFactory>,
|
|
|
|
sleep_duration: std::time::Duration,
|
2024-05-07 08:17:29 +01:00
|
|
|
) -> Self {
|
2024-06-19 07:03:08 +01:00
|
|
|
let message_token = messages::MessageToken::default();
|
2024-04-09 10:44:01 +01:00
|
|
|
Self {
|
2024-05-07 08:17:29 +01:00
|
|
|
generation,
|
2024-06-19 07:03:08 +01:00
|
|
|
message_token,
|
|
|
|
repo_details,
|
2024-04-14 06:48:26 +01:00
|
|
|
webhook,
|
2024-04-09 19:30:05 +01:00
|
|
|
webhook_id: None,
|
2024-04-14 06:48:26 +01:00
|
|
|
webhook_auth: None,
|
2024-04-14 15:46:21 +01:00
|
|
|
last_main_commit: None,
|
|
|
|
last_next_commit: None,
|
|
|
|
last_dev_commit: None,
|
2024-06-19 07:03:08 +01:00
|
|
|
repository_factory,
|
2024-05-26 09:44:56 +01:00
|
|
|
open_repository: None,
|
2024-04-16 22:21:55 +01:00
|
|
|
forge,
|
2024-06-19 07:03:08 +01:00
|
|
|
net,
|
|
|
|
sleep_duration,
|
|
|
|
log: None,
|
2024-04-09 10:44:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-06-19 07:03:08 +01:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
impl RepoActor {
|
|
|
|
pub fn with_log(mut self, log: RepoActorLog) -> Self {
|
|
|
|
self.log = Some(log);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_open_repository(
|
|
|
|
mut self,
|
|
|
|
open_repository: Box<dyn git::repository::OpenRepositoryLike>,
|
|
|
|
) -> Self {
|
|
|
|
self.open_repository.replace(open_repository);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub const fn with_message_token(mut self, message_token: messages::MessageToken) -> Self {
|
|
|
|
self.message_token = message_token;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
2024-04-09 10:44:01 +01:00
|
|
|
impl Actor for RepoActor {
|
|
|
|
type Context = Context<Self>;
|
2024-05-26 08:35:45 +01:00
|
|
|
#[tracing::instrument(name = "RepoActor::stopping", skip_all, fields(repo = %self.repo_details))]
|
2024-04-09 19:30:05 +01:00
|
|
|
fn stopping(&mut self, ctx: &mut Self::Context) -> Running {
|
2024-06-19 07:03:08 +01:00
|
|
|
tracing::debug!("stopping");
|
2024-05-04 12:37:35 +01:00
|
|
|
info!("Checking webhook");
|
2024-04-09 19:30:05 +01:00
|
|
|
match self.webhook_id.take() {
|
|
|
|
Some(webhook_id) => {
|
2024-06-19 07:03:08 +01:00
|
|
|
tracing::warn!("stopping - unregistering webhook");
|
2024-05-07 08:17:29 +01:00
|
|
|
info!(%webhook_id, "Unregistring webhook");
|
2024-06-19 07:03:08 +01:00
|
|
|
let forge = self.forge.duplicate();
|
2024-05-25 11:25:13 +01:00
|
|
|
async move {
|
|
|
|
if let Err(err) = forge.unregister_webhook(&webhook_id).await {
|
|
|
|
warn!("unregistering webhook: {err}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.in_current_span()
|
|
|
|
.into_actor(self)
|
|
|
|
.wait(ctx);
|
2024-04-09 19:30:05 +01:00
|
|
|
Running::Continue
|
|
|
|
}
|
|
|
|
None => Running::Stop,
|
|
|
|
}
|
|
|
|
}
|
2024-04-09 10:44:01 +01:00
|
|
|
}
|
|
|
|
|
2024-06-19 07:03:08 +01:00
|
|
|
pub fn do_send<M>(_addr: Addr<RepoActor>, msg: M, log: &Option<crate::RepoActorLog>)
|
|
|
|
where
|
|
|
|
M: actix::Message + Send + 'static + std::fmt::Debug,
|
|
|
|
RepoActor: actix::Handler<M>,
|
|
|
|
<M as actix::Message>::Result: Send,
|
|
|
|
{
|
|
|
|
let log_message = format!("send: {:?}", msg);
|
|
|
|
tracing::debug!(log_message);
|
|
|
|
logger(log, log_message);
|
|
|
|
#[cfg(not(test))]
|
|
|
|
_addr.do_send(msg)
|
2024-04-09 18:18:19 +01:00
|
|
|
}
|
2024-04-09 22:43:54 +01:00
|
|
|
|
2024-06-19 07:03:08 +01:00
|
|
|
pub async fn send<M>(
|
|
|
|
addr: Addr<RepoActor>,
|
|
|
|
msg: M,
|
|
|
|
log: &Option<crate::RepoActorLog>,
|
|
|
|
) -> std::result::Result<<M as actix::Message>::Result, actix::MailboxError>
|
|
|
|
where
|
|
|
|
M: actix::Message + Send + 'static + std::fmt::Debug,
|
|
|
|
RepoActor: actix::Handler<M>,
|
|
|
|
<M as actix::Message>::Result: Send,
|
|
|
|
{
|
|
|
|
let log_message = format!("send: {:?}", msg);
|
|
|
|
logger(log, log_message);
|
|
|
|
addr.send(msg).await
|
2024-04-09 22:43:54 +01:00
|
|
|
}
|
2024-05-23 08:30:58 +01:00
|
|
|
|
2024-06-19 07:03:08 +01:00
|
|
|
pub fn logger(log: &Option<crate::RepoActorLog>, message: impl Into<String>) {
|
|
|
|
if let Some(log) = log {
|
|
|
|
let message: String = message.into();
|
|
|
|
tracing::debug!(message);
|
|
|
|
let _ = log.lock().map(|mut l| l.push(message));
|
2024-05-23 08:30:58 +01:00
|
|
|
}
|
|
|
|
}
|