Implement advancing next branch to next commit on dev branch
Uses gix to invoke git commands as there is not API to directly update the position of a branch. Closes kemitix/git-next#14
This commit is contained in:
parent
a5e9421405
commit
98a94ea855
5 changed files with 104 additions and 15 deletions
|
@ -17,6 +17,9 @@ tracing-subscriber = "0.3"
|
|||
# base64 decoding
|
||||
base64 = "0.22"
|
||||
|
||||
# git
|
||||
gix = "0.61"
|
||||
|
||||
# fs/network
|
||||
kxio = "0.1" # { git = "https://git.kemitix.net/kemitix/kxio.git", branch = "main" }
|
||||
|
||||
|
|
|
@ -67,21 +67,70 @@ pub async fn validate_positions(
|
|||
return;
|
||||
}
|
||||
let dev = commit_histories.dev[0].clone();
|
||||
addr.do_send(StartMonitoring { main, next, dev });
|
||||
addr.do_send(StartMonitoring {
|
||||
main,
|
||||
next,
|
||||
dev,
|
||||
dev_commit_history: commit_histories.dev,
|
||||
});
|
||||
}
|
||||
|
||||
// advance next to the next commit towards the head of the dev branch
|
||||
#[allow(dead_code)]
|
||||
pub async fn advance_next(
|
||||
_next: forge::Commit,
|
||||
_repo_details: config::RepoDetails,
|
||||
next: forge::Commit,
|
||||
dev_commit_history: Vec<forge::Commit>,
|
||||
repo_details: config::RepoDetails,
|
||||
repo_config: config::RepoConfig,
|
||||
addr: Addr<RepoActor>,
|
||||
_net: network::Network,
|
||||
) {
|
||||
// TODO: (#14) advance next one commit towards dev
|
||||
info!("Advance Next");
|
||||
let user = repo_details.forge.user;
|
||||
let token = repo_details.forge.token;
|
||||
let hostname = repo_details.forge.hostname;
|
||||
let path = repo_details.repo;
|
||||
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;
|
||||
};
|
||||
let next = repo_config.branches().next();
|
||||
let command =
|
||||
format!("/usr/bin/git push https://{user}:{token}@{hostname}/{path}.git {commit}:{next}");
|
||||
info!("Running command: {}", command);
|
||||
match gix::command::prepare(command)
|
||||
.with_shell_allow_argument_splitting()
|
||||
.spawn()
|
||||
{
|
||||
Ok(mut child) => {
|
||||
match child.wait() {
|
||||
Ok(exit_status) => {
|
||||
info!(%exit_status, "Advance Next Success");
|
||||
addr.do_send(StartRepo);
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(?err, "Advance Next Failed (wait)")
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(?err, "Advance Next Failed (spawn)")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn find_next_commit_on_dev(
|
||||
next: forge::Commit,
|
||||
dev_commit_history: Vec<forge::Commit>,
|
||||
) -> Option<forge::Commit> {
|
||||
let mut next_commit: Option<forge::Commit> = 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'
|
||||
#[allow(dead_code)]
|
||||
|
@ -95,3 +144,21 @@ pub async fn advance_main(
|
|||
info!("Advance Main");
|
||||
addr.do_send(StartRepo);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_find_next_commit_on_dev() {
|
||||
let next = forge::Commit::new("current-next");
|
||||
let dev_commit_history = vec![
|
||||
forge::Commit::new("dev"),
|
||||
forge::Commit::new("dev-next"),
|
||||
forge::Commit::new("current-next"),
|
||||
forge::Commit::new("current-main"),
|
||||
];
|
||||
let next_commit = find_next_commit_on_dev(next, dev_commit_history);
|
||||
assert_eq!(next_commit, Some(forge::Commit::new("dev-next")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ mod webhook;
|
|||
|
||||
use actix::prelude::*;
|
||||
use kxio::network::Network;
|
||||
use tracing::info;
|
||||
use tracing::{info, warn};
|
||||
|
||||
use crate::server::{
|
||||
config::{RepoConfig, RepoDetails},
|
||||
|
@ -86,22 +86,35 @@ pub struct StartMonitoring {
|
|||
pub main: forge::Commit,
|
||||
pub next: forge::Commit,
|
||||
pub dev: forge::Commit,
|
||||
pub dev_commit_history: Vec<forge::Commit>,
|
||||
}
|
||||
impl Handler<StartMonitoring> for RepoActor {
|
||||
type Result = ();
|
||||
fn handle(&mut self, msg: StartMonitoring, ctx: &mut Self::Context) -> Self::Result {
|
||||
info!("Monitoring started");
|
||||
let next_ahead_of_main = msg.main != msg.next;
|
||||
let dev_ahead_of_next = msg.next != msg.dev;
|
||||
let Some(repo_config) = self.config.clone() else {
|
||||
warn!("No config loaded");
|
||||
return;
|
||||
};
|
||||
|
||||
let repo_details = self.details.clone();
|
||||
let addr = ctx.address();
|
||||
let net = self.net.clone();
|
||||
|
||||
let next_ahead_of_main = msg.main != msg.next;
|
||||
let dev_ahead_of_next = msg.next != msg.dev;
|
||||
if next_ahead_of_main {
|
||||
status::check_next(msg.next, repo_details, addr, net)
|
||||
.into_actor(self)
|
||||
.wait(ctx);
|
||||
} else if dev_ahead_of_next {
|
||||
branch::advance_next(msg.next, repo_details, addr, net)
|
||||
branch::advance_next(
|
||||
msg.next,
|
||||
msg.dev_commit_history,
|
||||
repo_details,
|
||||
repo_config,
|
||||
addr,
|
||||
)
|
||||
.into_actor(self)
|
||||
.wait(ctx);
|
||||
} else if self.webhook_id.is_none() {
|
||||
|
|
|
@ -34,9 +34,7 @@ pub async fn check_next(
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum Status {
|
||||
#[allow(dead_code)] // TODO: (#13) remove this when we have results from the forge
|
||||
Pass,
|
||||
#[allow(dead_code)] // TODO: (#13) remove this when we have results from the forge
|
||||
Fail,
|
||||
Pending,
|
||||
}
|
||||
|
|
|
@ -13,6 +13,14 @@ pub struct CommitHistories {
|
|||
pub struct Commit {
|
||||
pub sha: String,
|
||||
}
|
||||
impl Commit {
|
||||
#[cfg(test)]
|
||||
pub fn new(sha: &str) -> Self {
|
||||
Self {
|
||||
sha: sha.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Display for Commit {
|
||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||
write!(f, "{}", self.sha)
|
||||
|
|
Loading…
Reference in a new issue