diff --git a/crates/octopush_cli/src/commands/execute.rs b/crates/octopush_cli/src/commands/execute.rs index 3a0a769..b4919af 100644 --- a/crates/octopush_cli/src/commands/execute.rs +++ b/crates/octopush_cli/src/commands/execute.rs @@ -1,4 +1,4 @@ -use std::{path::PathBuf, sync::Arc}; +use std::path::PathBuf; use clap::{Arg, ArgAction, ArgMatches, Command}; use octopush_core::{ @@ -6,7 +6,6 @@ use octopush_core::{ schema, }; use octopush_infra::service_register::ServiceRegister; -use tokio::sync::Mutex; pub fn execute_cmd() -> Command { Command::new("execute") @@ -18,6 +17,7 @@ pub fn execute_cmd() -> Command { .action(ArgAction::Set) .help("action path to your local octopush.yaml file") .long_help("action path to your local octopush.yaml file") + .default_value(".") .required(true), ) .arg( @@ -60,89 +60,18 @@ pub async fn execute_subcommand(args: &ArgMatches) -> eyre::Result<()> { } => { tracing::debug!(name, "running action"); - tracing::info!("fetching repos"); - let mut git_paths = Vec::new(); - if let Some(git) = select.git.clone() { - let mut repo_clones = Vec::with_capacity(git.repositories.len()); - for repo in git.repositories { - let gp = service_register.git_provider.clone(); - repo_clones.push(tokio::spawn(async move { gp.clone_from_url(repo).await })); - } - - for repo_clone in repo_clones { - let path = repo_clone.await??; - git_paths.push(path); - } - } - - let mut gitea_paths = Vec::new(); - if let Some(gitea) = select.gitea.clone() { - let mut repo_clones = Vec::with_capacity(gitea.repositories.len()); - for repo in gitea.repositories { - let gp = service_register.gitea_provider.clone(); - repo_clones.push(tokio::spawn(async move { - gp.clone_from_qualified(repo.clone()) - .await - .map(|(p, r)| (p, r, repo)) - })) - } - - for repo_clone in repo_clones { - let path = repo_clone.await??; - gitea_paths.push(path); - } - } - - for (path, repo) in git_paths { - let repo = Arc::new(Mutex::new(repo)); - if let Some(git) = select.git.clone() { - if let Some(push) = git.push { - service_register - .git_provider - .create_branch(repo.clone(), &push.branch.name) - .await?; - } - } - + if let Some(git) = &select.git { service_register - .executor - .execute(path.clone(), action_path.clone(), action.clone()) + .git_selector + .run(git, &action_path, &action) .await?; - - if let Some(git) = select.git.clone() { - if let Some(push) = git.push { - service_register - .git_provider - .push_branch(repo, &push.branch.name) - .await?; - } - } } - for (path, repo, repo_name) in gitea_paths { - let repo = Arc::new(Mutex::new(repo)); - if let Some(gitea) = select.gitea.clone() { - if let Some(push) = gitea.push { - service_register - .gitea_provider - .create_branch(repo.clone(), &push.pull_request) - .await?; - } - } - + if let Some(gitea) = &select.gitea { service_register - .executor - .execute(path.clone(), action_path.clone(), action.clone()) + .gitea_selector + .run(gitea, &action_path, &action) .await?; - - if let Some(gitea) = select.gitea.clone() { - if let Some(push) = gitea.push { - service_register - .gitea_provider - .create_pull_request(repo, &repo_name, &push.pull_request) - .await?; - } - } } } } diff --git a/crates/octopush_core/src/builder/builder_capabilities.rs b/crates/octopush_core/src/builder/builder_capabilities.rs index 05441e4..ac4517e 100644 --- a/crates/octopush_core/src/builder/builder_capabilities.rs +++ b/crates/octopush_core/src/builder/builder_capabilities.rs @@ -19,13 +19,13 @@ impl BuilderCapabilities { #[async_trait] impl Builder for BuilderCapabilities { - async fn build(&self, action_path: PathBuf, action: Action) -> eyre::Result { + async fn build(&self, action_path: &PathBuf, action: &Action) -> eyre::Result { match action { Action::Go { entry } => { let bin = GolangBinBuild::new() .build(GolangBinBuildOpts { - entry, - src_path: action_path, + entry: entry.clone(), + src_path: action_path.clone(), }) .await?; diff --git a/crates/octopush_core/src/builder/builders/golang_bin.rs b/crates/octopush_core/src/builder/builders/golang_bin.rs index 10cbfa8..03cbeb1 100644 --- a/crates/octopush_core/src/builder/builders/golang_bin.rs +++ b/crates/octopush_core/src/builder/builders/golang_bin.rs @@ -47,8 +47,12 @@ impl GolangBin { #[async_trait] impl RunnableBin for GolangBin { - async fn run(&self, victim_path: PathBuf) -> eyre::Result<()> { - execute_shell(self.path.to_string_lossy().to_string(), Some(victim_path)).await?; + async fn run(&self, victim_path: &PathBuf) -> eyre::Result<()> { + execute_shell( + self.path.to_string_lossy().to_string(), + Some(victim_path.clone()), + ) + .await?; Ok(()) } diff --git a/crates/octopush_core/src/builder/mod.rs b/crates/octopush_core/src/builder/mod.rs index c22c629..a99ca6d 100644 --- a/crates/octopush_core/src/builder/mod.rs +++ b/crates/octopush_core/src/builder/mod.rs @@ -9,14 +9,14 @@ use crate::schema::models::Action; #[async_trait] pub trait RunnableBin { - async fn run(&self, victim_path: PathBuf) -> eyre::Result<()>; + async fn run(&self, victim_path: &PathBuf) -> eyre::Result<()>; } pub type DynRunnableBin = Arc; #[async_trait] pub trait Builder { - async fn build(&self, action_path: PathBuf, action: Action) -> eyre::Result; + async fn build(&self, action_path: &PathBuf, action: &Action) -> eyre::Result; } pub type DynBuilder = Arc; diff --git a/crates/octopush_core/src/executor/default_executor.rs b/crates/octopush_core/src/executor/default_executor.rs index 3092303..a0824ee 100644 --- a/crates/octopush_core/src/executor/default_executor.rs +++ b/crates/octopush_core/src/executor/default_executor.rs @@ -23,19 +23,22 @@ impl DefaultExecutor { impl Executor for DefaultExecutor { async fn execute( &self, - victim_path: PathBuf, - action_path: PathBuf, - action: Action, + victim_path: &PathBuf, + action_path: &PathBuf, + action: &Action, ) -> eyre::Result<()> { tracing::trace!( victim_path = victim_path.to_string_lossy().to_string(), "execute" ); - let bin = self.builder.build(action_path, action.clone()).await?; + let bin = self.builder.build(action_path, action).await?; match action { Action::Go { .. } => { GolangExecutor::new() - .execute(GolangExecutorOpts { bin, victim_path }) + .execute(GolangExecutorOpts { + bin, + victim_path: victim_path.clone(), + }) .await? } } diff --git a/crates/octopush_core/src/executor/executor.rs b/crates/octopush_core/src/executor/executor.rs index d723c08..ba36d64 100644 --- a/crates/octopush_core/src/executor/executor.rs +++ b/crates/octopush_core/src/executor/executor.rs @@ -8,9 +8,9 @@ use crate::schema::models::Action; pub trait Executor { async fn execute( &self, - victim_path: PathBuf, - action_path: PathBuf, - action: Action, + victim_path: &PathBuf, + action_path: &PathBuf, + action: &Action, ) -> eyre::Result<()>; } diff --git a/crates/octopush_core/src/executor/executors/golang.rs b/crates/octopush_core/src/executor/executors/golang.rs index af6c7a8..7cd4d3a 100644 --- a/crates/octopush_core/src/executor/executors/golang.rs +++ b/crates/octopush_core/src/executor/executors/golang.rs @@ -15,7 +15,7 @@ impl GolangExecutor { } pub async fn execute(&self, opts: GolangExecutorOpts) -> eyre::Result<()> { - opts.bin.run(opts.victim_path).await?; + opts.bin.run(&opts.victim_path).await?; Ok(()) } diff --git a/crates/octopush_core/src/git/git.rs b/crates/octopush_core/src/git/git.rs index f0df79e..cd2785b 100644 --- a/crates/octopush_core/src/git/git.rs +++ b/crates/octopush_core/src/git/git.rs @@ -29,7 +29,8 @@ impl LocalGitProvider { #[async_trait::async_trait] impl GitProvider for LocalGitProvider { - async fn clone_from_url(&self, url: String) -> eyre::Result<(PathBuf, Repository)> { + async fn clone_from_url(&self, url: &String) -> eyre::Result<(PathBuf, Repository)> { + let url = url.clone(); tracing::debug!(url, "allocating dir"); let dir = self.storage_engine.allocate_dir().await?; let options = self.options.clone(); @@ -65,7 +66,6 @@ impl GitProvider for LocalGitProvider { builder.fetch_options(fo).with_checkout(checkout_builder); tracing::debug!( - url, path = dirpath.as_os_str().to_string_lossy().to_string(), "clone git repo" ); diff --git a/crates/octopush_core/src/git/gitea/mod.rs b/crates/octopush_core/src/git/gitea/mod.rs index 1f3e469..96abb1f 100644 --- a/crates/octopush_core/src/git/gitea/mod.rs +++ b/crates/octopush_core/src/git/gitea/mod.rs @@ -24,7 +24,7 @@ pub type DynGiteaClient = Arc; #[async_trait] pub trait GiteaProvider { - async fn clone_from_qualified(&self, repo: String) -> eyre::Result<(PathBuf, Repository)>; + async fn clone_from_qualified(&self, repo: &String) -> eyre::Result<(PathBuf, Repository)>; async fn create_branch( &self, repo: Arc>, diff --git a/crates/octopush_core/src/git/gitea/provider.rs b/crates/octopush_core/src/git/gitea/provider.rs index 381484d..323099b 100644 --- a/crates/octopush_core/src/git/gitea/provider.rs +++ b/crates/octopush_core/src/git/gitea/provider.rs @@ -30,7 +30,7 @@ impl DefaultGiteaProvider { #[async_trait] impl GiteaProvider for DefaultGiteaProvider { - async fn clone_from_qualified(&self, repo: String) -> eyre::Result<(PathBuf, Repository)> { + async fn clone_from_qualified(&self, repo: &String) -> eyre::Result<(PathBuf, Repository)> { let (owner, repo_name) = repo .split_once("/") .ok_or(eyre::anyhow!("repo is not a valid format"))?; @@ -40,7 +40,7 @@ impl GiteaProvider for DefaultGiteaProvider { .get_clone_url(owner.into(), repo_name.into()) .await?; - let (path, repo) = self.git_provider.clone_from_url(clone_url).await?; + let (path, repo) = self.git_provider.clone_from_url(&clone_url).await?; Ok((path, repo)) } diff --git a/crates/octopush_core/src/git/mod.rs b/crates/octopush_core/src/git/mod.rs index 9eb51b7..64f58e6 100644 --- a/crates/octopush_core/src/git/mod.rs +++ b/crates/octopush_core/src/git/mod.rs @@ -4,14 +4,12 @@ use async_trait::async_trait; use git2::Repository; use tokio::sync::Mutex; -use crate::schema::models::GitPushBranch; - pub mod git; pub mod gitea; #[async_trait] pub trait GitProvider { - async fn clone_from_url(&self, url: String) -> eyre::Result<(PathBuf, Repository)>; + async fn clone_from_url(&self, url: &String) -> eyre::Result<(PathBuf, Repository)>; async fn create_branch( &self, repo: Arc>, diff --git a/crates/octopush_core/src/lib.rs b/crates/octopush_core/src/lib.rs index a51286f..07c1e0c 100644 --- a/crates/octopush_core/src/lib.rs +++ b/crates/octopush_core/src/lib.rs @@ -2,5 +2,6 @@ pub mod builder; pub mod executor; pub mod git; pub mod schema; +pub mod selectors; mod shell; pub mod storage; diff --git a/crates/octopush_core/src/selectors/git_selector.rs b/crates/octopush_core/src/selectors/git_selector.rs new file mode 100644 index 0000000..303ac57 --- /dev/null +++ b/crates/octopush_core/src/selectors/git_selector.rs @@ -0,0 +1,48 @@ +use std::{path::PathBuf, sync::Arc}; + +use tokio::sync::Mutex; + +use crate::{ + executor::executor::DynExecutor, + git::DynGitProvider, + schema::models::{Action, Git}, +}; + +pub struct GitSelector { + git_provider: DynGitProvider, + executor: DynExecutor, +} + +impl GitSelector { + pub fn new(git_provider: DynGitProvider, executor: DynExecutor) -> Self { + Self { + git_provider, + executor, + } + } + + pub async fn run(&self, git: &Git, action_path: &PathBuf, action: &Action) -> eyre::Result<()> { + tracing::info!("fetching repos"); + for repo in &git.repositories { + let gp = self.git_provider.clone(); + let (path, repo) = gp.clone_from_url(repo).await?; + let repo = Arc::new(Mutex::new(repo)); + + if let Some(push) = &git.push { + self.git_provider + .create_branch(repo.clone(), &push.branch.name) + .await?; + } + + self.executor.execute(&path, action_path, action).await?; + + if let Some(push) = &git.push { + self.git_provider + .push_branch(repo, &push.branch.name) + .await?; + } + } + + Ok(()) + } +} diff --git a/crates/octopush_core/src/selectors/gitea_selector.rs b/crates/octopush_core/src/selectors/gitea_selector.rs new file mode 100644 index 0000000..4b80b97 --- /dev/null +++ b/crates/octopush_core/src/selectors/gitea_selector.rs @@ -0,0 +1,59 @@ +use std::{path::PathBuf, sync::Arc}; + +use tokio::sync::Mutex; + +use crate::{ + executor::executor::DynExecutor, + git::{gitea::DynGiteaProvider, DynGitProvider}, + schema::models::{Action, Gitea}, +}; + +pub struct GiteaSelector { + gitea_provider: DynGiteaProvider, + git_provider: DynGitProvider, + executor: DynExecutor, +} + +impl GiteaSelector { + pub fn new( + gitea_provider: DynGiteaProvider, + git_provider: DynGitProvider, + executor: DynExecutor, + ) -> Self { + Self { + gitea_provider, + git_provider, + executor, + } + } + + pub async fn run( + &self, + git: &Gitea, + action_path: &PathBuf, + action: &Action, + ) -> eyre::Result<()> { + tracing::info!("fetching repos"); + for repo in &git.repositories { + let gp = self.gitea_provider.clone(); + let (path, repo) = gp.clone_from_qualified(repo).await?; + let repo = Arc::new(Mutex::new(repo)); + + if let Some(push) = &git.push { + self.git_provider + .create_branch(repo.clone(), &push.pull_request.name) + .await?; + } + + self.executor.execute(&path, action_path, action).await?; + + if let Some(push) = &git.push { + self.git_provider + .push_branch(repo, &push.pull_request.name) + .await?; + } + } + + Ok(()) + } +} diff --git a/crates/octopush_core/src/selectors/mod.rs b/crates/octopush_core/src/selectors/mod.rs new file mode 100644 index 0000000..c31befe --- /dev/null +++ b/crates/octopush_core/src/selectors/mod.rs @@ -0,0 +1,3 @@ +pub mod git_selector; +pub mod gitea_selector; + diff --git a/crates/octopush_infra/src/service_register.rs b/crates/octopush_infra/src/service_register.rs index acbd0d1..7b0301a 100644 --- a/crates/octopush_infra/src/service_register.rs +++ b/crates/octopush_infra/src/service_register.rs @@ -13,6 +13,7 @@ use octopush_core::{ DynGitProvider, }, schema::parser::{DefaultSchemaParser, DynSchemaParser}, + selectors::{git_selector::GitSelector, gitea_selector::GiteaSelector}, storage::{local::LocalStorageEngine, DynStorageEngine}, }; @@ -23,6 +24,8 @@ pub struct ServiceRegister { pub builder: DynBuilder, pub executor: DynExecutor, pub gitea_provider: DynGiteaProvider, + pub git_selector: Arc, + pub gitea_selector: Arc, } impl ServiceRegister { @@ -44,6 +47,12 @@ impl ServiceRegister { storage_engine.clone(), gitea_client.clone(), )); + let git_selector = Arc::new(GitSelector::new(git_provider.clone(), executor.clone())); + let gitea_selector = Arc::new(GiteaSelector::new( + gitea_provider.clone(), + git_provider.clone(), + executor.clone(), + )); Self { storage_engine, @@ -52,6 +61,8 @@ impl ServiceRegister { builder, executor, gitea_provider, + git_selector, + gitea_selector, } }