use std::time::Duration; use actix::prelude::*; use tracing::{info, warn}; use crate::server::{ actors::repo::{RepoActor, ValidateRepo}, config, gitforge, }; // advance next to the next commit towards the head of the dev branch #[tracing::instrument(fields(next), skip_all)] pub async fn advance_next( next: gitforge::Commit, dev_commit_history: Vec, repo_config: config::RepoConfig, forge: gitforge::Forge, addr: Addr, message_token: super::MessageToken, ) { let next_commit = find_next_commit_on_dev(next, dev_commit_history); let Some(commit) = next_commit else { warn!("No commits to advance next to"); return; }; if let Some(problem) = validate_commit_message(commit.message()) { warn!("Can't advance next to commit '{}': {}", commit, problem); return; } info!("Advancing next to commit '{}'", commit); if let Err(err) = forge.branch_reset( repo_config.branches().next(), commit.into(), gitforge::Force::No, ) { warn!(?err, "Failed") } tokio::time::sleep(Duration::from_secs(10)).await; addr.do_send(ValidateRepo { message_token }) } #[tracing::instrument] fn validate_commit_message(message: &gitforge::Message) -> Option { let message = &message.to_string(); if message.to_ascii_lowercase().starts_with("wip") { return Some("Is Work-In-Progress".to_string()); } match git_conventional::Commit::parse(message) { Ok(commit) => { info!(?commit, "Pass"); None } Err(err) => { warn!(?err, "Fail"); Some(err.kind().to_string()) } } } fn find_next_commit_on_dev( next: gitforge::Commit, dev_commit_history: Vec, ) -> Option { let mut next_commit: Option = None; for commit in dev_commit_history.into_iter() { if commit == next { break; }; next_commit.replace(commit); } next_commit } // advance main branch to the commit 'next' #[tracing::instrument(fields(next), skip_all)] pub async fn advance_main( next: gitforge::Commit, repo_config: config::RepoConfig, forge: gitforge::Forge, addr: Addr, message_token: super::MessageToken, ) { info!("Advancing main to next"); if let Err(err) = forge.branch_reset( repo_config.branches().main(), next.into(), gitforge::Force::No, ) { warn!(?err, "Failed") }; addr.do_send(ValidateRepo { message_token }) } #[cfg(test)] mod tests { use super::*; #[actix_rt::test] async fn test_find_next_commit_on_dev() { let next = gitforge::Commit::new("current-next", "foo"); let expected = gitforge::Commit::new("dev-next", "next-should-go-here"); let dev_commit_history = vec![ gitforge::Commit::new("dev", "future"), expected.clone(), next.clone(), gitforge::Commit::new("current-main", "history"), ]; let next_commit = find_next_commit_on_dev(next, dev_commit_history); assert_eq!(next_commit, Some(expected)); } }