refactor: cleanup pedantic clippy in cli crate

This commit is contained in:
Paul Campbell 2024-08-05 07:39:38 +01:00
parent 281c07c849
commit 24251f0c9c
45 changed files with 152 additions and 151 deletions

View file

@ -15,11 +15,11 @@ documentation = "https://git.kemitix.net/kemitix/git-next/src/branch/main/README
keywords = ["git", "cli", "server", "tool"] keywords = ["git", "cli", "server", "tool"]
categories = ["development-tools"] categories = ["development-tools"]
[workspace.lints.clippy] # [workspace.lints.clippy]
nursery = { level = "warn", priority = -1 } # pedantic = { level = "warn", priority = -1 }
# pedantic = "warn" # nursery = { level = "warn", priority = -1 }
unwrap_used = "warn" # unwrap_used = "warn"
expect_used = "warn" # expect_used = "warn"
[workspace.dependencies] [workspace.dependencies]
git-next-core = { path = "crates/core", version = "0.13" } git-next-core = { path = "crates/core", version = "0.13" }

View file

@ -76,7 +76,7 @@ mockall = { workspace = true }
[lints.clippy] [lints.clippy]
nursery = { level = "warn", priority = -1 } nursery = { level = "warn", priority = -1 }
# pedantic = "warn" pedantic = { level = "warn", priority = -1 }
unwrap_used = "warn" unwrap_used = "warn"
expect_used = "warn" expect_used = "warn"

View file

@ -23,11 +23,11 @@ pub(super) fn send_email(user_notification: &UserNotification, email_config: &Em
}; };
match email_config.smtp() { match email_config.smtp() {
Some(smtp) => send_email_smtp(email_message, smtp), Some(smtp) => send_email_smtp(email_message, smtp),
None => send_email_sendmail(email_message), None => send_email_sendmail(&email_message),
} }
} }
fn send_email_sendmail(email_message: EmailMessage) { fn send_email_sendmail(email_message: &EmailMessage) {
use sendmail::email; use sendmail::email;
match email::send( match email::send(
&email_message.from, &email_message.from,
@ -35,7 +35,7 @@ fn send_email_sendmail(email_message: EmailMessage) {
&email_message.subject, &email_message.subject,
&email_message.body, &email_message.body,
) { ) {
Ok(_) => tracing::info!("Email sent successfully!"), Ok(()) => tracing::info!("Email sent successfully!"),
Err(e) => tracing::warn!("Could not send email: {:?}", e), Err(e) => tracing::warn!("Could not send email: {:?}", e),
} }
} }
@ -62,7 +62,7 @@ fn do_send_email_smtp(email_message: EmailMessage, smtp: &SmtpConfig) -> Result<
.map(|response| { .map(|response| {
response response
.message() .message()
.map(|s| s.to_string()) .map(ToString::to_string)
.collect::<Vec<_>>() .collect::<Vec<_>>()
}) })
.map(|response| { .map(|response| {

View file

@ -16,7 +16,7 @@ pub struct History {
/// Maps a user notification to when it was last seen. /// Maps a user notification to when it was last seen.
/// ///
/// The user notification will not be sent until after max_age_seconds from last seen. /// The user notification will not be sent until after `max_age_seconds` from last seen.
/// ///
/// Each time we see a given user notification, the last seen time will be updated. /// Each time we see a given user notification, the last seen time will be updated.
items: HashMap<UserNotification, Instant>, items: HashMap<UserNotification, Instant>,
@ -44,7 +44,7 @@ impl History {
pub fn prune(&mut self, now: &Instant) { pub fn prune(&mut self, now: &Instant) {
if let Some(threshold) = now.checked_sub(self.max_age_seconds) { if let Some(threshold) = now.checked_sub(self.max_age_seconds) {
self.items.retain(|_, last_seen| *last_seen > threshold) self.items.retain(|_, last_seen| *last_seen > threshold);
}; };
} }
} }

View file

@ -17,6 +17,7 @@ mod webhook;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
#[allow(clippy::module_name_repetitions)]
#[derive(Debug, Constructor)] #[derive(Debug, Constructor)]
pub struct AlertsActor { pub struct AlertsActor {
shout: Option<Shout>, // config for sending alerts to users shout: Option<Shout>, // config for sending alerts to users

View file

@ -1,5 +1,6 @@
// //
use git_next_core::{git::UserNotification, server::OutboundWebhook}; use git_next_core::{git::UserNotification, server::OutboundWebhook};
use kxio::network::{NetRequest, NetUrl, RequestBody, ResponseType};
use secrecy::ExposeSecret as _; use secrecy::ExposeSecret as _;
use standardwebhooks::Webhook; use standardwebhooks::Webhook;
@ -35,7 +36,7 @@ async fn do_send_webhook(
.expect("signature"); .expect("signature");
tracing::info!(?signature, ""); tracing::info!(?signature, "");
let url = webhook_config.url(); let url = webhook_config.url();
use kxio::network::{NetRequest, NetUrl, RequestBody, ResponseType};
let net_url = NetUrl::new(url.to_string()); let net_url = NetUrl::new(url.to_string());
let request = NetRequest::post(net_url) let request = NetRequest::post(net_url)
.body(RequestBody::Json(payload)) .body(RequestBody::Json(payload))

View file

@ -2,7 +2,7 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use kxio::fs::FileSystem; use kxio::fs::FileSystem;
pub fn run(fs: FileSystem) -> Result<()> { pub fn run(fs: &FileSystem) -> Result<()> {
let pathbuf = fs.base().join(".git-next.toml"); let pathbuf = fs.base().join(".git-next.toml");
if fs if fs
.path_exists(&pathbuf) .path_exists(&pathbuf)

View file

@ -44,11 +44,11 @@ fn main() -> Result<()> {
match commands.command { match commands.command {
Command::Init => { Command::Init => {
init::run(fs)?; init::run(&fs)?;
} }
Command::Server(server) => match server { Command::Server(server) => match server {
Server::Init => { Server::Init => {
server::init(fs)?; server::init(&fs)?;
} }
Server::Start => { Server::Start => {
let sleep_duration = std::time::Duration::from_secs(10); let sleep_duration = std::time::Duration::from_secs(10);

View file

@ -66,7 +66,7 @@ pub fn find_next_commit_on_dev(
) -> (Option<Commit>, Force) { ) -> (Option<Commit>, Force) {
let mut next_commit: Option<&Commit> = None; let mut next_commit: Option<&Commit> = None;
let mut force = Force::No; let mut force = Force::No;
for commit in dev_commit_history.iter() { for commit in dev_commit_history {
if commit == next { if commit == next {
break; break;
}; };

View file

@ -36,12 +36,12 @@ impl Handler<AdvanceMain> for RepoActor {
Err(err) => { Err(err) => {
warn!("advance main: {err}"); warn!("advance main: {err}");
} }
Ok(_) => match repo_config.source() { Ok(()) => match repo_config.source() {
RepoConfigSource::Repo => { RepoConfigSource::Repo => {
do_send(addr, LoadConfigFromRepo, self.log.as_ref()); do_send(&addr, LoadConfigFromRepo, self.log.as_ref());
} }
RepoConfigSource::Server => { RepoConfigSource::Server => {
do_send(addr, ValidateRepo::new(message_token), self.log.as_ref()); do_send(&addr, ValidateRepo::new(message_token), self.log.as_ref());
} }
}, },
} }

View file

@ -41,7 +41,7 @@ impl Handler<AdvanceNext> for RepoActor {
Ok(message_token) => { Ok(message_token) => {
// pause to allow any CI checks to be started // pause to allow any CI checks to be started
std::thread::sleep(self.sleep_duration); std::thread::sleep(self.sleep_duration);
do_send(addr, ValidateRepo::new(message_token), self.log.as_ref()); do_send(&addr, ValidateRepo::new(message_token), self.log.as_ref());
} }
Err(err) => warn!("advance next: {err}"), Err(err) => warn!("advance next: {err}"),
} }

View file

@ -23,7 +23,7 @@ impl Handler<CheckCIStatus> for RepoActor {
async move { async move {
let status = forge.commit_status(&next).await; let status = forge.commit_status(&next).await;
debug!("got status: {status:?}"); debug!("got status: {status:?}");
do_send(addr, ReceiveCIStatus::new((next, status)), log.as_ref()); do_send(&addr, ReceiveCIStatus::new((next, status)), log.as_ref());
} }
.in_current_span() .in_current_span()
.into_actor(self) .into_actor(self)

View file

@ -22,14 +22,14 @@ impl Handler<CloneRepo> for RepoActor {
debug!("open okay"); debug!("open okay");
self.open_repository.replace(repository); self.open_repository.replace(repository);
if self.repo_details.repo_config.is_none() { if self.repo_details.repo_config.is_none() {
do_send(ctx.address(), LoadConfigFromRepo, self.log.as_ref()); do_send(&ctx.address(), LoadConfigFromRepo, self.log.as_ref());
} else { } else {
do_send(ctx.address(), RegisterWebhook::new(), self.log.as_ref()); do_send(&ctx.address(), RegisterWebhook::new(), self.log.as_ref());
} }
} }
Err(err) => { Err(err) => {
logger(self.log.as_ref(), "open failed"); logger(self.log.as_ref(), "open failed");
warn!("Could not open repo: {err:?}") warn!("Could not open repo: {err:?}");
} }
} }
debug!("Handler: CloneRepo: finish"); debug!("Handler: CloneRepo: finish");

View file

@ -28,7 +28,9 @@ impl Handler<LoadConfigFromRepo> for RepoActor {
let log = self.log.clone(); let log = self.log.clone();
async move { async move {
match load::config_from_repository(repo_details, &*open_repository).await { match load::config_from_repository(repo_details, &*open_repository).await {
Ok(repo_config) => do_send(addr, ReceiveRepoConfig::new(repo_config), log.as_ref()), Ok(repo_config) => {
do_send(&addr, ReceiveRepoConfig::new(repo_config), log.as_ref());
}
Err(err) => notify_user( Err(err) => notify_user(
notify_user_recipient.as_ref(), notify_user_recipient.as_ref(),
UserNotification::RepoConfigLoadFailure { UserNotification::RepoConfigLoadFailure {

View file

@ -26,11 +26,11 @@ impl Handler<ReceiveCIStatus> for RepoActor {
debug!(?status, ""); debug!(?status, "");
match status { match status {
Status::Pass => { Status::Pass => {
do_send(addr, AdvanceMain::new(next), self.log.as_ref()); do_send(&addr, AdvanceMain::new(next), self.log.as_ref());
} }
Status::Pending => { Status::Pending => {
std::thread::sleep(sleep_duration); std::thread::sleep(sleep_duration);
do_send(addr, ValidateRepo::new(message_token), self.log.as_ref()); do_send(&addr, ValidateRepo::new(message_token), self.log.as_ref());
} }
Status::Fail => { Status::Fail => {
tracing::warn!("Checks have failed"); tracing::warn!("Checks have failed");
@ -44,7 +44,7 @@ impl Handler<ReceiveCIStatus> for RepoActor {
log.as_ref(), log.as_ref(),
); );
delay_send( delay_send(
addr, &addr,
sleep_duration, sleep_duration,
ValidateRepo::new(message_token), ValidateRepo::new(message_token),
self.log.as_ref(), self.log.as_ref(),

View file

@ -15,6 +15,6 @@ impl Handler<ReceiveRepoConfig> for RepoActor {
let repo_config = msg.unwrap(); let repo_config = msg.unwrap();
self.repo_details.repo_config.replace(repo_config); self.repo_details.repo_config.replace(repo_config);
do_send(ctx.address(), RegisterWebhook::new(), self.log.as_ref()); do_send(&ctx.address(), RegisterWebhook::new(), self.log.as_ref());
} }
} }

View file

@ -31,7 +31,7 @@ impl Handler<RegisterWebhook> for RepoActor {
Ok(registered_webhook) => { Ok(registered_webhook) => {
debug!(?registered_webhook, ""); debug!(?registered_webhook, "");
do_send( do_send(
addr, &addr,
WebhookRegistered::from(registered_webhook), WebhookRegistered::from(registered_webhook),
log.as_ref(), log.as_ref(),
); );

View file

@ -14,7 +14,7 @@ impl Handler<UnRegisterWebhook> for RepoActor {
debug!("unregistering webhook"); debug!("unregistering webhook");
async move { async move {
match forge.unregister_webhook(&webhook_id).await { match forge.unregister_webhook(&webhook_id).await {
Ok(_) => debug!("unregistered webhook"), Ok(()) => debug!("unregistered webhook"),
Err(err) => warn!(?err, "unregistering webhook"), Err(err) => warn!(?err, "unregistering webhook"),
} }
} }

View file

@ -1,7 +1,6 @@
// //
use actix::prelude::*; use actix::prelude::*;
use derive_more::Deref as _;
use tracing::{debug, instrument, Instrument as _}; use tracing::{debug, instrument, Instrument as _};
use crate::repo::{ use crate::repo::{
@ -15,7 +14,7 @@ use git_next_core::git::validation::positions::{validate_positions, Error, Posit
impl Handler<ValidateRepo> for RepoActor { impl Handler<ValidateRepo> for RepoActor {
type Result = (); type Result = ();
#[instrument(name = "RepoActor::ValidateRepo", skip_all, fields(repo = %self.repo_details, token = %msg.deref()))] #[instrument(name = "RepoActor::ValidateRepo", skip_all, fields(repo = %self.repo_details, token = %&*msg))]
fn handle(&mut self, msg: ValidateRepo, ctx: &mut Self::Context) -> Self::Result { fn handle(&mut self, msg: ValidateRepo, ctx: &mut Self::Context) -> Self::Result {
logger(self.log.as_ref(), "start: ValidateRepo"); logger(self.log.as_ref(), "start: ValidateRepo");
@ -64,17 +63,17 @@ impl Handler<ValidateRepo> for RepoActor {
}) => { }) => {
debug!(%main, %next, %dev, "positions"); debug!(%main, %next, %dev, "positions");
if next_is_valid && next != main { if next_is_valid && next != main {
do_send(ctx.address(), CheckCIStatus::new(next), self.log.as_ref()); do_send(&ctx.address(), CheckCIStatus::new(next), self.log.as_ref());
} else if next != dev { } else if next != dev {
do_send( do_send(
ctx.address(), &ctx.address(),
AdvanceNext::new(AdvanceNextPayload { AdvanceNext::new(AdvanceNextPayload {
next, next,
main, main,
dev_commit_history, dev_commit_history,
}), }),
self.log.as_ref(), self.log.as_ref(),
) );
} else { } else {
// do nothing // do nothing
} }
@ -90,7 +89,7 @@ impl Handler<ValidateRepo> for RepoActor {
logger(log.as_ref(), "before sleep"); logger(log.as_ref(), "before sleep");
actix_rt::time::sleep(sleep_duration).await; actix_rt::time::sleep(sleep_duration).await;
logger(log.as_ref(), "after sleep"); logger(log.as_ref(), "after sleep");
do_send(addr, ValidateRepo::new(message_token), log.as_ref()); do_send(&addr, ValidateRepo::new(message_token), log.as_ref());
} }
.in_current_span() .in_current_span()
.into_actor(self) .into_actor(self)

View file

@ -6,7 +6,7 @@ use tracing::{info, instrument, warn};
use crate::repo::{ use crate::repo::{
do_send, logger, do_send, logger,
messages::{ValidateRepo, WebhookNotification}, messages::{ValidateRepo, WebhookNotification},
RepoActor, RepoActorLog, ActorLog, RepoActor,
}; };
use git_next_core::{ use git_next_core::{
@ -54,7 +54,7 @@ impl Handler<WebhookNotification> for RepoActor {
Some(Branch::Main) => { Some(Branch::Main) => {
if handle_push( if handle_push(
push, push,
config.branches().main(), &config.branches().main(),
&mut self.last_main_commit, &mut self.last_main_commit,
self.log.as_ref(), self.log.as_ref(),
) )
@ -66,7 +66,7 @@ impl Handler<WebhookNotification> for RepoActor {
Some(Branch::Next) => { Some(Branch::Next) => {
if handle_push( if handle_push(
push, push,
config.branches().next(), &config.branches().next(),
&mut self.last_next_commit, &mut self.last_next_commit,
self.log.as_ref(), self.log.as_ref(),
) )
@ -78,7 +78,7 @@ impl Handler<WebhookNotification> for RepoActor {
Some(Branch::Dev) => { Some(Branch::Dev) => {
if handle_push( if handle_push(
push, push,
config.branches().dev(), &config.branches().dev(),
&mut self.last_dev_commit, &mut self.last_dev_commit,
self.log.as_ref(), self.log.as_ref(),
) )
@ -95,7 +95,7 @@ impl Handler<WebhookNotification> for RepoActor {
"New commit" "New commit"
); );
do_send( do_send(
ctx.address(), &ctx.address(),
ValidateRepo::new(message_token), ValidateRepo::new(message_token),
self.log.as_ref(), self.log.as_ref(),
); );
@ -106,7 +106,7 @@ fn validate_notification(
msg: &WebhookNotification, msg: &WebhookNotification,
webhook_auth: Option<&WebhookAuth>, webhook_auth: Option<&WebhookAuth>,
forge: &dyn ForgeLike, forge: &dyn ForgeLike,
log: Option<&RepoActorLog>, log: Option<&ActorLog>,
) -> Result<(), ()> { ) -> Result<(), ()> {
let Some(expected_authorization) = webhook_auth else { let Some(expected_authorization) = webhook_auth else {
logger(log, "server has no auth token"); logger(log, "server has no auth token");
@ -131,9 +131,9 @@ fn validate_notification(
fn handle_push( fn handle_push(
push: Push, push: Push,
branch: BranchName, branch: &BranchName,
last_commit: &mut Option<Commit>, last_commit: &mut Option<Commit>,
log: Option<&RepoActorLog>, log: Option<&ActorLog>,
) -> Result<(), ()> { ) -> Result<(), ()> {
logger(log, "message is for dev branch"); logger(log, "message is for dev branch");
let commit = Commit::from(push); let commit = Commit::from(push);

View file

@ -15,7 +15,7 @@ impl Handler<WebhookRegistered> for RepoActor {
self.webhook_id.replace(msg.webhook_id().clone()); self.webhook_id.replace(msg.webhook_id().clone());
self.webhook_auth.replace(msg.webhook_auth().clone()); self.webhook_auth.replace(msg.webhook_auth().clone());
do_send( do_send(
ctx.address(), &ctx.address(),
ValidateRepo::new(self.message_token), ValidateRepo::new(self.message_token),
self.log.as_ref(), self.log.as_ref(),
); );

View file

@ -46,7 +46,7 @@ Primarily used by [ValidateRepo] to reduce duplicate messages. The token is incr
received, marking that message the latest, and causing any previous messages still being processed to be dropped when received, marking that message the latest, and causing any previous messages still being processed to be dropped when
they next send a [ValidateRepo] message."#); they next send a [ValidateRepo] message."#);
impl MessageToken { impl MessageToken {
pub const fn next(&self) -> Self { pub const fn next(self) -> Self {
Self(self.0 + 1) Self(self.0 + 1)
} }
} }

View file

@ -27,8 +27,8 @@ mod notifications;
pub mod tests; pub mod tests;
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct RepoActorLog(std::sync::Arc<std::sync::RwLock<Vec<String>>>); pub struct ActorLog(std::sync::Arc<std::sync::RwLock<Vec<String>>>);
impl Deref for RepoActorLog { impl Deref for ActorLog {
type Target = std::sync::Arc<std::sync::RwLock<Vec<String>>>; type Target = std::sync::Arc<std::sync::RwLock<Vec<String>>>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@ -38,7 +38,8 @@ impl Deref for RepoActorLog {
/// An actor that represents a Git Repository. /// An actor that represents a Git Repository.
/// ///
/// When this actor is started it is sent the [CloneRepo] message. /// When this actor is started it is sent the `CloneRepo` message.
#[allow(clippy::module_name_repetitions)]
#[derive(Debug, derive_more::Display, derive_with::With)] #[derive(Debug, derive_more::Display, derive_with::With)]
#[display("{}:{}:{}", generation, repo_details.forge.forge_alias(), repo_details.repo_alias)] #[display("{}:{}:{}", generation, repo_details.forge.forge_alias(), repo_details.repo_alias)]
pub struct RepoActor { pub struct RepoActor {
@ -56,7 +57,7 @@ pub struct RepoActor {
open_repository: Option<Box<dyn OpenRepositoryLike>>, open_repository: Option<Box<dyn OpenRepositoryLike>>,
net: Network, net: Network,
forge: Box<dyn git::ForgeLike>, forge: Box<dyn git::ForgeLike>,
log: Option<RepoActorLog>, log: Option<ActorLog>,
notify_user_recipient: Option<Recipient<NotifyUser>>, notify_user_recipient: Option<Recipient<NotifyUser>>,
} }
impl RepoActor { impl RepoActor {
@ -118,33 +119,35 @@ impl Actor for RepoActor {
} }
} }
pub fn delay_send<M>(addr: Addr<RepoActor>, delay: Duration, msg: M, log: Option<&RepoActorLog>) pub fn delay_send<M>(addr: &Addr<RepoActor>, delay: Duration, msg: M, log: Option<&ActorLog>)
where where
M: actix::Message + Send + 'static + std::fmt::Debug, M: actix::Message + Send + 'static + std::fmt::Debug,
RepoActor: actix::Handler<M>, RepoActor: actix::Handler<M>,
<M as actix::Message>::Result: Send, <M as actix::Message>::Result: Send,
{ {
let log_message = format!("send-after-delay: {:?}", msg); let log_message = format!("send-after-delay: {msg:?}");
tracing::debug!(log_message); tracing::debug!(log_message);
logger(log, log_message); logger(log, log_message);
std::thread::sleep(delay); std::thread::sleep(delay);
do_send(addr, msg, log) do_send(addr, msg, log);
} }
pub fn do_send<M>(_addr: Addr<RepoActor>, msg: M, log: Option<&RepoActorLog>) pub fn do_send<M>(addr: &Addr<RepoActor>, msg: M, log: Option<&ActorLog>)
where where
M: actix::Message + Send + 'static + std::fmt::Debug, M: actix::Message + Send + 'static + std::fmt::Debug,
RepoActor: actix::Handler<M>, RepoActor: actix::Handler<M>,
<M as actix::Message>::Result: Send, <M as actix::Message>::Result: Send,
{ {
let log_message = format!("send: {:?}", msg); let log_message = format!("send: {msg:?}");
tracing::debug!(log_message); tracing::debug!(log_message);
logger(log, log_message); logger(log, log_message);
#[cfg(not(test))] if cfg!(not(test)) {
_addr.do_send(msg) // #[cfg(not(test))]
addr.do_send(msg);
}
} }
pub fn logger(log: Option<&RepoActorLog>, message: impl Into<String>) { pub fn logger(log: Option<&ActorLog>, message: impl Into<String>) {
if let Some(log) = log { if let Some(log) = log {
let message: String = message.into(); let message: String = message.into();
tracing::debug!(message); tracing::debug!(message);
@ -154,10 +157,10 @@ pub fn logger(log: Option<&RepoActorLog>, message: impl Into<String>) {
pub fn notify_user( pub fn notify_user(
recipient: Option<&Recipient<NotifyUser>>, recipient: Option<&Recipient<NotifyUser>>,
user_notification: UserNotification, user_notification: UserNotification,
log: Option<&RepoActorLog>, log: Option<&ActorLog>,
) { ) {
let msg = NotifyUser::from(user_notification); let msg = NotifyUser::from(user_notification);
let log_message = format!("send: {:?}", msg); let log_message = format!("send: {msg:?}");
tracing::debug!(log_message); tracing::debug!(log_message);
logger(log, log_message); logger(log, log_message);
if let Some(recipient) = &recipient { if let Some(recipient) = &recipient {

View file

@ -1,5 +1,4 @@
// //
use derive_more::Deref as _;
use crate::repo::messages::NotifyUser; use crate::repo::messages::NotifyUser;
@ -10,7 +9,7 @@ use serde_json::json;
impl NotifyUser { impl NotifyUser {
pub fn as_json(&self, timestamp: time::OffsetDateTime) -> serde_json::Value { pub fn as_json(&self, timestamp: time::OffsetDateTime) -> serde_json::Value {
let timestamp = timestamp.unix_timestamp().to_string(); let timestamp = timestamp.unix_timestamp().to_string();
match self.deref() { match &**self {
UserNotification::CICheckFailed { UserNotification::CICheckFailed {
forge_alias, forge_alias,
repo_alias, repo_alias,

View file

@ -4,8 +4,9 @@ use super::*;
mod when_at_dev { mod when_at_dev {
// next and dev branches are the same // next and dev branches are the same
use super::*; use super::*;
#[test] #[test]
fn should_not_push() -> TestResult { fn should_not_push() {
let next = given::a_commit(); let next = given::a_commit();
let main = &next; let main = &next;
let dev_commit_history = &[next.clone()]; let dev_commit_history = &[next.clone()];
@ -27,7 +28,6 @@ mod when_at_dev {
); );
tracing::debug!("Got: {err}"); tracing::debug!("Got: {err}");
assert!(matches!(err, branch::Error::NextAtDev)); assert!(matches!(err, branch::Error::NextAtDev));
Ok(())
} }
} }
@ -40,7 +40,7 @@ mod can_advance {
use super::*; use super::*;
#[test] #[test]
fn should_not_push() -> TestResult { fn should_not_push() {
let next = given::a_commit(); let next = given::a_commit();
let main = &next; let main = &next;
let dev = given::a_commit_with_message("wip: test: message".to_string()); let dev = given::a_commit_with_message("wip: test: message".to_string());
@ -63,7 +63,6 @@ mod can_advance {
); );
tracing::debug!("Got: {err}"); tracing::debug!("Got: {err}");
assert!(matches!(err, branch::Error::IsWorkInProgress)); assert!(matches!(err, branch::Error::IsWorkInProgress));
Ok(())
} }
} }
@ -72,7 +71,7 @@ mod can_advance {
use super::*; use super::*;
#[test] #[test]
fn should_not_push_and_error() -> TestResult { fn should_not_push_and_error() {
let next = given::a_commit(); let next = given::a_commit();
let main = &next; let main = &next;
let dev = given::a_commit(); let dev = given::a_commit();
@ -99,7 +98,6 @@ mod can_advance {
branch::Error::InvalidCommitMessage{reason} branch::Error::InvalidCommitMessage{reason}
if reason == "Missing type in the commit summary, expected `type: description`" if reason == "Missing type in the commit summary, expected `type: description`"
)); ));
Ok(())
} }
} }
@ -112,7 +110,7 @@ mod can_advance {
use super::*; use super::*;
#[test] #[test]
fn should_error() -> TestResult { fn should_error() {
let next = given::a_commit(); let next = given::a_commit();
let main = &next; let main = &next;
let dev = given::a_commit_with_message("test: message".to_string()); let dev = given::a_commit_with_message("test: message".to_string());
@ -136,7 +134,6 @@ mod can_advance {
); );
tracing::debug!("Got: {err:?}"); tracing::debug!("Got: {err:?}");
assert!(matches!(err, branch::Error::Push(git::push::Error::Lock))); assert!(matches!(err, branch::Error::Push(git::push::Error::Lock)));
Ok(())
} }
} }
@ -145,7 +142,7 @@ mod can_advance {
use super::*; use super::*;
#[test] #[test]
fn should_ok() -> TestResult { fn should_ok() {
let next = given::a_commit(); let next = given::a_commit();
let main = &next; let main = &next;
let dev = given::a_commit_with_message("test: message".to_string()); let dev = given::a_commit_with_message("test: message".to_string());
@ -169,7 +166,6 @@ mod can_advance {
); );
tracing::debug!("Got: {mt:?}"); tracing::debug!("Got: {mt:?}");
assert_eq!(mt, message_token); assert_eq!(mt, message_token);
Ok(())
} }
} }
} }

View file

@ -15,7 +15,7 @@ pub fn fetch(open_repository: &mut MockOpenRepositoryLike, result: Result<(), fe
} }
pub fn push_ok(open_repository: &mut MockOpenRepositoryLike) { pub fn push_ok(open_repository: &mut MockOpenRepositoryLike) {
expect::push(open_repository, Ok(())) expect::push(open_repository, Ok(()));
} }
pub fn push( pub fn push(

View file

@ -20,12 +20,12 @@ pub fn has_remote_defaults(
open_repository: &mut MockOpenRepositoryLike, open_repository: &mut MockOpenRepositoryLike,
remotes: HashMap<Direction, Option<RemoteUrl>>, remotes: HashMap<Direction, Option<RemoteUrl>>,
) { ) {
remotes.into_iter().for_each(|(direction, remote)| { for (direction, remote) in remotes {
open_repository open_repository
.expect_find_default_remote() .expect_find_default_remote()
.with(eq(direction)) .with(eq(direction))
.return_once(|_| remote); .return_once(|_| remote);
}); }
} }
pub fn a_webhook_auth() -> WebhookAuth { pub fn a_webhook_auth() -> WebhookAuth {
@ -89,7 +89,7 @@ pub fn a_forge_config() -> ForgeConfig {
a_name(), a_name(),
a_name(), a_name(),
a_name(), a_name(),
Default::default(), // no repos BTreeMap::default(), // no repos
) )
} }
@ -170,6 +170,7 @@ pub fn a_message_token() -> MessageToken {
MessageToken::default() MessageToken::default()
} }
#[allow(clippy::unnecessary_box_returns)]
pub fn a_forge() -> Box<MockForgeLike> { pub fn a_forge() -> Box<MockForgeLike> {
Box::new(MockForgeLike::new()) Box::new(MockForgeLike::new())
} }
@ -179,10 +180,10 @@ pub fn a_repo_actor(
repository_factory: Box<dyn RepositoryFactory>, repository_factory: Box<dyn RepositoryFactory>,
forge: Box<dyn ForgeLike>, forge: Box<dyn ForgeLike>,
net: kxio::network::Network, net: kxio::network::Network,
) -> (RepoActor, RepoActorLog) { ) -> (RepoActor, ActorLog) {
let listen_url = given::a_listen_url(); let listen_url = given::a_listen_url();
let generation = Generation::default(); let generation = Generation::default();
let log = RepoActorLog::default(); let log = ActorLog::default();
let actors_log = log.clone(); let actors_log = log.clone();
( (
RepoActor::new( RepoActor::new(

View file

@ -41,7 +41,7 @@ async fn when_repo_config_should_fetch_then_push_then_revalidate() -> TestResult
log.read().map_err(|e| e.to_string()).map(|l| { log.read().map_err(|e| e.to_string()).map(|l| {
assert!(l assert!(l
.iter() .iter()
.any(|message| message.contains("send: LoadConfigFromRepo"))) .any(|message| message.contains("send: LoadConfigFromRepo")));
})?; })?;
Ok(()) Ok(())
} }
@ -86,7 +86,7 @@ async fn when_server_config_should_fetch_then_push_then_revalidate() -> TestResu
log.read().map_err(|e| e.to_string()).map(|l| { log.read().map_err(|e| e.to_string()).map(|l| {
assert!(l assert!(l
.iter() .iter()
.any(|message| message.contains("send: ValidateRepo"))) .any(|message| message.contains("send: ValidateRepo")));
})?; })?;
Ok(()) Ok(())
} }

View file

@ -48,7 +48,7 @@ async fn should_fetch_then_push_then_revalidate() -> TestResult {
log.read().map_err(|e| e.to_string()).map(|l| { log.read().map_err(|e| e.to_string()).map(|l| {
assert!(l assert!(l
.iter() .iter()
.any(|message| message.contains("send: ValidateRepo"))) .any(|message| message.contains("send: ValidateRepo")));
})?; })?;
Ok(()) Ok(())
} }

View file

@ -31,7 +31,7 @@ async fn should_passthrough_to_receive_ci_status() -> TestResult {
log.read().map_err(|e| e.to_string()).map(|l| { log.read().map_err(|e| e.to_string()).map(|l| {
assert!(l assert!(l
.iter() .iter()
.any(|message| message.contains("send: ReceiveCIStatus"))) .any(|message| message.contains("send: ReceiveCIStatus")));
})?; })?;
Ok(()) Ok(())
} }

View file

@ -57,7 +57,7 @@ async fn should_register_webhook() -> TestResult {
log.read().map_err(|e| e.to_string()).map(|l| { log.read().map_err(|e| e.to_string()).map(|l| {
assert!(l assert!(l
.iter() .iter()
.any(|message| message.contains("send: RegisterWebhook"))) .any(|message| message.contains("send: RegisterWebhook")));
})?; })?;
Ok(()) Ok(())
} }

View file

@ -24,9 +24,9 @@ async fn when_pass_should_advance_main_to_next() -> TestResult {
//then //then
tracing::debug!(?log, ""); tracing::debug!(?log, "");
log.read().map_err(|e| e.to_string()).map(|l| { log.read().map_err(|e| e.to_string()).map(|l| {
let expected = format!("send: AdvanceMain({:?})", next_commit); let expected = format!("send: AdvanceMain({next_commit:?})");
tracing::debug!(%expected,""); tracing::debug!(%expected,"");
assert!(l.iter().any(|message| message.contains(&expected))) assert!(l.iter().any(|message| message.contains(&expected)));
})?; })?;
Ok(()) Ok(())
} }
@ -56,7 +56,7 @@ async fn when_pending_should_recheck_ci_status() -> TestResult {
log.read().map_err(|e| e.to_string()).map(|l| { log.read().map_err(|e| e.to_string()).map(|l| {
assert!(l assert!(l
.iter() .iter()
.any(|message| message.contains("send: ValidateRepo"))) .any(|message| message.contains("send: ValidateRepo")));
})?; })?;
Ok(()) Ok(())
} }

View file

@ -31,7 +31,7 @@ async fn when_registered_ok_should_send_webhook_registered() -> TestResult {
log.read().map_err(|e| e.to_string()).map(|l| { log.read().map_err(|e| e.to_string()).map(|l| {
assert!(l assert!(l
.iter() .iter()
.any(|message| message.contains("send: WebhookRegistered"))) .any(|message| message.contains("send: WebhookRegistered")));
})?; })?;
Ok(()) Ok(())
} }

View file

@ -9,7 +9,7 @@ async fn when_no_expected_auth_token_drop_notification() -> TestResult {
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let (actor, log) = given::a_repo_actor( let (actor, log) = given::a_repo_actor(
@ -43,7 +43,7 @@ async fn when_no_repo_config_drop_notification() -> TestResult {
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let (actor, log) = given::a_repo_actor( let (actor, log) = given::a_repo_actor(
@ -77,7 +77,7 @@ async fn when_message_auth_is_invalid_drop_notification() -> TestResult {
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let mut forge = given::a_forge(); let mut forge = given::a_forge();
@ -115,7 +115,7 @@ async fn when_message_is_ignorable_drop_notification() -> TestResult {
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let mut forge = given::a_forge(); let mut forge = given::a_forge();
@ -157,7 +157,7 @@ async fn when_message_is_not_a_push_drop_notification() -> TestResult {
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let mut forge = given::a_forge(); let mut forge = given::a_forge();
@ -200,7 +200,7 @@ async fn when_message_is_push_on_unknown_branch_drop_notification() -> TestResul
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let commit = given::a_commit(); let commit = given::a_commit();
@ -248,7 +248,7 @@ async fn when_message_is_push_already_seen_commit_to_main() -> TestResult {
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let commit = given::a_commit(); let commit = given::a_commit();
@ -297,7 +297,7 @@ async fn when_message_is_push_already_seen_commit_to_next() -> TestResult {
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let commit = given::a_commit(); let commit = given::a_commit();
@ -346,7 +346,7 @@ async fn when_message_is_push_already_seen_commit_to_dev() -> TestResult {
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let commit = given::a_commit(); let commit = given::a_commit();
@ -395,7 +395,7 @@ async fn when_message_is_push_new_commit_to_main_should_stash_and_validate_repo(
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let push_commit = given::a_commit(); let push_commit = given::a_commit();
@ -443,7 +443,7 @@ async fn when_message_is_push_new_commit_to_next_should_stash_and_validate_repo(
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let push_commit = given::a_commit(); let push_commit = given::a_commit();
@ -491,7 +491,7 @@ async fn when_message_is_push_new_commit_to_dev_should_stash_and_validate_repo()
let forge_alias = given::a_forge_alias(); let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias(); let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new(); let headers = BTreeMap::new();
let body = Body::new("".to_string()); let body = Body::new(String::new());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body); let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new(); let repository_factory = MockRepositoryFactory::new();
let push_commit = given::a_commit(); let push_commit = given::a_commit();

View file

@ -5,7 +5,7 @@ use crate::{
git, git,
repo::{ repo::{
messages::{CloneRepo, MessageToken}, messages::{CloneRepo, MessageToken},
RepoActor, RepoActorLog, ActorLog, RepoActor,
}, },
}; };
@ -45,7 +45,7 @@ mod handlers;
mod load; mod load;
mod when; mod when;
impl RepoActorLog { impl ActorLog {
pub fn no_message_contains(&self, needle: impl AsRef<str> + std::fmt::Display) -> TestResult { pub fn no_message_contains(&self, needle: impl AsRef<str> + std::fmt::Display) -> TestResult {
if self.find_in_messages(needle.as_ref())? { if self.find_in_messages(needle.as_ref())? {
error!(?self, ""); error!(?self, "");

View file

@ -5,7 +5,7 @@ pub fn start_actor(
repository_factory: MockRepositoryFactory, repository_factory: MockRepositoryFactory,
repo_details: RepoDetails, repo_details: RepoDetails,
forge: Box<dyn ForgeLike>, forge: Box<dyn ForgeLike>,
) -> (actix::Addr<RepoActor>, RepoActorLog) { ) -> (actix::Addr<RepoActor>, ActorLog) {
let (actor, log) = given::a_repo_actor( let (actor, log) = given::a_repo_actor(
repo_details, repo_details,
Box::new(repository_factory), Box::new(repository_factory),
@ -19,7 +19,7 @@ pub fn start_actor_with_open_repository(
open_repository: Box<dyn OpenRepositoryLike>, open_repository: Box<dyn OpenRepositoryLike>,
repo_details: RepoDetails, repo_details: RepoDetails,
forge: Box<dyn ForgeLike>, forge: Box<dyn ForgeLike>,
) -> (actix::Addr<RepoActor>, RepoActorLog) { ) -> (actix::Addr<RepoActor>, ActorLog) {
let (actor, log) = given::a_repo_actor(repo_details, mock(), forge, given::a_network().into()); let (actor, log) = given::a_repo_actor(repo_details, mock(), forge, given::a_network().into());
let actor = actor.with_open_repository(Some(open_repository)); let actor = actor.with_open_repository(Some(open_repository));
(actor.start(), log) (actor.start(), log)

View file

@ -14,7 +14,7 @@ impl Handler<FileUpdated> for ServerActor {
fn handle(&mut self, _msg: FileUpdated, ctx: &mut Self::Context) -> Self::Result { fn handle(&mut self, _msg: FileUpdated, ctx: &mut Self::Context) -> Self::Result {
match ServerConfig::load(&self.fs) { match ServerConfig::load(&self.fs) {
Ok(server_config) => self.do_send(ReceiveServerConfig::new(server_config), ctx), Ok(server_config) => self.do_send(ReceiveServerConfig::new(server_config), ctx),
Err(err) => self.abort(ctx, format!("Failed to load config file. Error: {}", err)), Err(err) => self.abort(ctx, format!("Failed to load config file. Error: {err}")),
}; };
} }
} }

View file

@ -1,17 +1,19 @@
// //
use actix::prelude::*; use actix::prelude::*;
use git_next_core::{ForgeAlias, RepoAlias};
use tracing::info; use tracing::info;
use crate::{ use crate::{
alerts::messages::UpdateShout, alerts::messages::UpdateShout,
repo::{messages::CloneRepo, RepoActor},
server::actor::{ server::actor::{
messages::{ReceiveValidServerConfig, ValidServerConfig}, messages::{ReceiveValidServerConfig, ValidServerConfig},
ServerActor, ServerActor,
}, },
webhook::{ webhook::{
messages::ShutdownWebhook, messages::ShutdownWebhook,
router::{AddWebhookRecipient, WebhookRouter}, router::{AddWebhookRecipient, WebhookRouterActor},
WebhookActor, WebhookActor,
}, },
}; };
@ -32,9 +34,9 @@ impl Handler<ReceiveValidServerConfig> for ServerActor {
self.generation.inc(); self.generation.inc();
// Webhook Server // Webhook Server
info!("Starting Webhook Server..."); info!("Starting Webhook Server...");
let webhook_router = WebhookRouter::default().start(); let webhook_router = WebhookRouterActor::default().start();
let listen_url = server_config.listen().url(); let listen_url = server_config.listen().url();
let alerts = self.alerts.clone(); let notify_user_recipient = self.alerts.clone().recipient();
// Forge Actors // Forge Actors
for (forge_alias, forge_config) in server_config.forges() { for (forge_alias, forge_config) in server_config.forges() {
let repo_actors = self let repo_actors = self
@ -43,10 +45,10 @@ impl Handler<ReceiveValidServerConfig> for ServerActor {
forge_alias.clone(), forge_alias.clone(),
&server_storage, &server_storage,
listen_url, listen_url,
alerts.clone().recipient(), &notify_user_recipient,
) )
.into_iter() .into_iter()
.map(|a| self.start_actor(a)) .map(start_repo_actor)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
repo_actors repo_actors
.iter() .iter()
@ -58,10 +60,10 @@ impl Handler<ReceiveValidServerConfig> for ServerActor {
) )
}) })
.for_each(|msg| webhook_router.do_send(msg)); .for_each(|msg| webhook_router.do_send(msg));
repo_actors.into_iter().for_each(|(repo_alias, addr)| { for (repo_alias, addr) in repo_actors {
self.repo_actors self.repo_actors
.insert((forge_alias.clone(), repo_alias), addr); .insert((forge_alias.clone(), repo_alias), addr);
}); }
} }
let webhook_actor_addr = let webhook_actor_addr =
WebhookActor::new(socket_address, webhook_router.recipient()).start(); WebhookActor::new(socket_address, webhook_router.recipient()).start();
@ -71,3 +73,13 @@ impl Handler<ReceiveValidServerConfig> for ServerActor {
self.alerts.do_send(UpdateShout::new(shout)); self.alerts.do_send(UpdateShout::new(shout));
} }
} }
fn start_repo_actor(actor: (ForgeAlias, RepoAlias, RepoActor)) -> (RepoAlias, Addr<RepoActor>) {
let (forge_name, repo_alias, actor) = actor;
let span = tracing::info_span!("start_repo_actor", forge = %forge_name, repo = %repo_alias);
let _guard = span.enter();
let addr = actor.start();
addr.do_send(CloneRepo);
tracing::info!("Started");
(repo_alias, addr)
}

View file

@ -10,10 +10,7 @@ mod handlers;
pub mod messages; pub mod messages;
use crate::{ use crate::{
alerts::messages::NotifyUser, alerts::messages::NotifyUser, alerts::AlertsActor, forge::Forge, repo::RepoActor,
alerts::AlertsActor,
forge::Forge,
repo::{messages::CloneRepo, RepoActor},
webhook::WebhookActor, webhook::WebhookActor,
}; };
@ -47,6 +44,7 @@ pub enum Error {
} }
type Result<T> = core::result::Result<T, Error>; type Result<T> = core::result::Result<T, Error>;
#[allow(clippy::module_name_repetitions)]
#[derive(derive_with::With)] #[derive(derive_with::With)]
#[with(message_log)] #[with(message_log)]
pub struct ServerActor { pub struct ServerActor {
@ -116,7 +114,7 @@ impl ServerActor {
forge_name: ForgeAlias, forge_name: ForgeAlias,
server_storage: &ServerStorage, server_storage: &ServerStorage,
listen_url: &ListenUrl, listen_url: &ListenUrl,
notify_user_recipient: Recipient<NotifyUser>, notify_user_recipient: &Recipient<NotifyUser>,
) -> Vec<(ForgeAlias, RepoAlias, RepoActor)> { ) -> Vec<(ForgeAlias, RepoAlias, RepoActor)> {
let span = let span =
tracing::info_span!("create_forge_repos", name = %forge_name, config = %forge_config); tracing::info_span!("create_forge_repos", name = %forge_name, config = %forge_config);
@ -198,19 +196,6 @@ impl ServerActor {
} }
} }
fn start_actor(
&self,
actor: (ForgeAlias, RepoAlias, RepoActor),
) -> (RepoAlias, Addr<RepoActor>) {
let (forge_name, repo_alias, actor) = actor;
let span = tracing::info_span!("start_actor", forge = %forge_name, repo = %repo_alias);
let _guard = span.enter();
let addr = actor.start();
addr.do_send(CloneRepo);
tracing::info!("Started");
(repo_alias, addr)
}
fn server_storage(&self, server_config: &ReceiveServerConfig) -> Option<ServerStorage> { fn server_storage(&self, server_config: &ReceiveServerConfig) -> Option<ServerStorage> {
let server_storage = server_config.storage().clone(); let server_storage = server_config.storage().clone();
let dir = server_storage.path(); let dir = server_storage.path();
@ -232,25 +217,26 @@ impl ServerActor {
} }
/// Attempts to gracefully shutdown the server before stopping the system. /// Attempts to gracefully shutdown the server before stopping the system.
fn abort(&self, ctx: &mut <Self as actix::Actor>::Context, message: impl Into<String>) { fn abort(&self, ctx: &<Self as actix::Actor>::Context, message: impl Into<String>) {
tracing::error!("Aborting: {}", message.into()); tracing::error!("Aborting: {}", message.into());
self.do_send(crate::server::actor::messages::Shutdown, ctx); self.do_send(crate::server::actor::messages::Shutdown, ctx);
System::current().stop_with_code(1); System::current().stop_with_code(1);
} }
fn do_send<M>(&self, msg: M, _ctx: &mut <Self as actix::Actor>::Context) fn do_send<M>(&self, msg: M, ctx: &<Self as actix::Actor>::Context)
where where
M: actix::Message + Send + 'static + std::fmt::Debug, M: actix::Message + Send + 'static + std::fmt::Debug,
Self: actix::Handler<M>, Self: actix::Handler<M>,
<M as actix::Message>::Result: Send, <M as actix::Message>::Result: Send,
{ {
if let Some(message_log) = &self.message_log { if let Some(message_log) = &self.message_log {
let log_message = format!("send: {:?}", msg); let log_message = format!("send: {msg:?}");
if let Ok(mut log) = message_log.write() { if let Ok(mut log) = message_log.write() {
log.push(log_message); log.push(log_message);
} }
} }
#[cfg(not(test))] if cfg!(not(test)) {
_ctx.address().do_send(msg); ctx.address().do_send(msg);
}
} }
} }

View file

@ -21,7 +21,7 @@ use std::{path::PathBuf, time::Duration};
const A_DAY: Duration = Duration::from_secs(24 * 60 * 60); const A_DAY: Duration = Duration::from_secs(24 * 60 * 60);
pub fn init(fs: FileSystem) -> Result<()> { pub fn init(fs: &FileSystem) -> Result<()> {
let file_name = "git-next-server.toml"; let file_name = "git-next-server.toml";
let pathbuf = PathBuf::from(file_name); let pathbuf = PathBuf::from(file_name);
if fs if fs

View file

@ -37,7 +37,7 @@ fn gitdir_should_display_as_pathbuf() {
//given //given
let gitdir = GitDir::new("foo/dir".into(), StoragePathType::External); let gitdir = GitDir::new("foo/dir".into(), StoragePathType::External);
//when //when
let result = format!("{}", gitdir); let result = format!("{gitdir}");
//then //then
assert_eq!(result, "foo/dir"); assert_eq!(result, "foo/dir");
} }
@ -59,7 +59,7 @@ fn repo_details_find_default_push_remote_finds_correct_remote() -> Result<()> {
repo_details.forge = repo_details repo_details.forge = repo_details
.forge .forge
.with_user(User::new("git".to_string())) .with_user(User::new("git".to_string()))
.with_token(ApiToken::new(Secret::new("".to_string()))) .with_token(ApiToken::new(Secret::new(String::new())))
.with_hostname(Hostname::new("git.kemitix.net")); .with_hostname(Hostname::new("git.kemitix.net"));
repo_details.repo_path = RepoPath::new("kemitix/git-next".to_string()); repo_details.repo_path = RepoPath::new("kemitix/git-next".to_string());
let open_repository = git::repository::factory::real().open(&repo_details)?; let open_repository = git::repository::factory::real().open(&repo_details)?;
@ -92,7 +92,7 @@ fn gitdir_validate_should_pass_a_valid_git_repo() -> Result<()> {
repo_details.forge = repo_details repo_details.forge = repo_details
.forge .forge
.with_user(User::new("git".to_string())) .with_user(User::new("git".to_string()))
.with_token(ApiToken::new(Secret::new("".to_string()))) .with_token(ApiToken::new(Secret::new(String::new())))
.with_hostname(Hostname::new("git.kemitix.net")); .with_hostname(Hostname::new("git.kemitix.net"));
tracing::debug!("opening..."); tracing::debug!("opening...");
let_assert!( let_assert!(
@ -124,7 +124,7 @@ fn gitdir_validate_should_fail_a_git_repo_with_wrong_remote() -> Result<()> {
repo_details.forge = repo_details repo_details.forge = repo_details
.forge .forge
.with_user(User::new("git".to_string())) .with_user(User::new("git".to_string()))
.with_token(ApiToken::new(Secret::new("".to_string()))) .with_token(ApiToken::new(Secret::new(String::new())))
.with_hostname(Hostname::new("git.kemitix.net")); .with_hostname(Hostname::new("git.kemitix.net"));
let repository = git::repository::factory::real().open(&repo_details)?; let repository = git::repository::factory::real().open(&repo_details)?;
let mut repo_details = repo_details.clone(); let mut repo_details = repo_details.clone();

View file

@ -8,7 +8,7 @@ mod init {
let file = fs.base().join(".git-next.toml"); let file = fs.base().join(".git-next.toml");
fs.file_write(&file, "contents")?; fs.file_write(&file, "contents")?;
crate::init::run(fs.clone())?; crate::init::run(&fs)?;
assert_eq!( assert_eq!(
fs.file_read_to_string(&file)?, fs.file_read_to_string(&file)?,
@ -23,7 +23,7 @@ mod init {
fn should_create_default_file_if_not_exists() -> TestResult { fn should_create_default_file_if_not_exists() -> TestResult {
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
crate::init::run(fs.clone())?; crate::init::run(&fs)?;
let file = fs.base().join(".git-next.toml"); let file = fs.base().join(".git-next.toml");

View file

@ -12,6 +12,7 @@ use std::net::SocketAddr;
use tracing::Instrument; use tracing::Instrument;
#[allow(clippy::module_name_repetitions)]
#[derive(Debug)] #[derive(Debug)]
pub struct WebhookActor { pub struct WebhookActor {
socket_addr: SocketAddr, socket_addr: SocketAddr,

View file

@ -10,29 +10,29 @@ use crate::repo::messages::WebhookNotification;
use git_next_core::{ForgeAlias, RepoAlias}; use git_next_core::{ForgeAlias, RepoAlias};
pub struct WebhookRouter { pub struct WebhookRouterActor {
span: tracing::Span, span: tracing::Span,
recipients: BTreeMap<ForgeAlias, BTreeMap<RepoAlias, Recipient<WebhookNotification>>>, recipients: BTreeMap<ForgeAlias, BTreeMap<RepoAlias, Recipient<WebhookNotification>>>,
} }
impl Default for WebhookRouter { impl Default for WebhookRouterActor {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }
} }
impl WebhookRouter { impl WebhookRouterActor {
pub fn new() -> Self { pub fn new() -> Self {
let span = tracing::info_span!("WebhookRouter"); let span = tracing::info_span!("WebhookRouter");
Self { Self {
span, span,
recipients: Default::default(), recipients: BTreeMap::default(),
} }
} }
} }
impl Actor for WebhookRouter { impl Actor for WebhookRouterActor {
type Context = Context<Self>; type Context = Context<Self>;
} }
impl Handler<WebhookNotification> for WebhookRouter { impl Handler<WebhookNotification> for WebhookRouterActor {
type Result = (); type Result = ();
fn handle(&mut self, msg: WebhookNotification, _ctx: &mut Self::Context) -> Self::Result { fn handle(&mut self, msg: WebhookNotification, _ctx: &mut Self::Context) -> Self::Result {
@ -59,7 +59,7 @@ pub struct AddWebhookRecipient {
pub repo_alias: RepoAlias, pub repo_alias: RepoAlias,
pub recipient: Recipient<WebhookNotification>, pub recipient: Recipient<WebhookNotification>,
} }
impl Handler<AddWebhookRecipient> for WebhookRouter { impl Handler<AddWebhookRecipient> for WebhookRouterActor {
type Result = (); type Result = ();
fn handle(&mut self, msg: AddWebhookRecipient, _ctx: &mut Self::Context) -> Self::Result { fn handle(&mut self, msg: AddWebhookRecipient, _ctx: &mut Self::Context) -> Self::Result {

View file

@ -50,7 +50,7 @@ pub async fn start(
)); ));
recipient recipient
.try_send(message) .try_send(message)
.map(|_| { .map(|()| {
info!("Message sent ok"); info!("Message sent ok");
warp::reply::with_status("OK", warp::http::StatusCode::OK) warp::reply::with_status("OK", warp::http::StatusCode::OK)
}) })