extract logic from execute

This commit is contained in:
Kasper Juul Hermansen 2022-11-27 11:06:24 +01:00
parent 4ec5250a8d
commit a777b1d0a4
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
16 changed files with 159 additions and 103 deletions

View File

@ -1,4 +1,4 @@
use std::{path::PathBuf, sync::Arc}; use std::path::PathBuf;
use clap::{Arg, ArgAction, ArgMatches, Command}; use clap::{Arg, ArgAction, ArgMatches, Command};
use octopush_core::{ use octopush_core::{
@ -6,7 +6,6 @@ use octopush_core::{
schema, schema,
}; };
use octopush_infra::service_register::ServiceRegister; use octopush_infra::service_register::ServiceRegister;
use tokio::sync::Mutex;
pub fn execute_cmd() -> Command { pub fn execute_cmd() -> Command {
Command::new("execute") Command::new("execute")
@ -18,6 +17,7 @@ pub fn execute_cmd() -> Command {
.action(ArgAction::Set) .action(ArgAction::Set)
.help("action path to your local octopush.yaml file") .help("action path to your local octopush.yaml file")
.long_help("action path to your local octopush.yaml file") .long_help("action path to your local octopush.yaml file")
.default_value(".")
.required(true), .required(true),
) )
.arg( .arg(
@ -60,89 +60,18 @@ pub async fn execute_subcommand(args: &ArgMatches) -> eyre::Result<()> {
} => { } => {
tracing::debug!(name, "running action"); tracing::debug!(name, "running action");
tracing::info!("fetching repos"); if let Some(git) = &select.git {
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 service_register
.git_provider .git_selector
.create_branch(repo.clone(), &push.branch.name) .run(git, &action_path, &action)
.await?; .await?;
} }
}
if let Some(gitea) = &select.gitea {
service_register service_register
.executor .gitea_selector
.execute(path.clone(), action_path.clone(), action.clone()) .run(gitea, &action_path, &action)
.await?; .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?;
}
}
service_register
.executor
.execute(path.clone(), action_path.clone(), action.clone())
.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?;
}
}
} }
} }
} }

View File

@ -19,13 +19,13 @@ impl BuilderCapabilities {
#[async_trait] #[async_trait]
impl Builder for BuilderCapabilities { impl Builder for BuilderCapabilities {
async fn build(&self, action_path: PathBuf, action: Action) -> eyre::Result<DynRunnableBin> { async fn build(&self, action_path: &PathBuf, action: &Action) -> eyre::Result<DynRunnableBin> {
match action { match action {
Action::Go { entry } => { Action::Go { entry } => {
let bin = GolangBinBuild::new() let bin = GolangBinBuild::new()
.build(GolangBinBuildOpts { .build(GolangBinBuildOpts {
entry, entry: entry.clone(),
src_path: action_path, src_path: action_path.clone(),
}) })
.await?; .await?;

View File

@ -47,8 +47,12 @@ impl GolangBin {
#[async_trait] #[async_trait]
impl RunnableBin for GolangBin { impl RunnableBin for GolangBin {
async fn run(&self, victim_path: PathBuf) -> eyre::Result<()> { async fn run(&self, victim_path: &PathBuf) -> eyre::Result<()> {
execute_shell(self.path.to_string_lossy().to_string(), Some(victim_path)).await?; execute_shell(
self.path.to_string_lossy().to_string(),
Some(victim_path.clone()),
)
.await?;
Ok(()) Ok(())
} }

View File

@ -9,14 +9,14 @@ use crate::schema::models::Action;
#[async_trait] #[async_trait]
pub trait RunnableBin { 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<dyn RunnableBin + Send + Sync>; pub type DynRunnableBin = Arc<dyn RunnableBin + Send + Sync>;
#[async_trait] #[async_trait]
pub trait Builder { pub trait Builder {
async fn build(&self, action_path: PathBuf, action: Action) -> eyre::Result<DynRunnableBin>; async fn build(&self, action_path: &PathBuf, action: &Action) -> eyre::Result<DynRunnableBin>;
} }
pub type DynBuilder = Arc<dyn Builder + Send + Sync>; pub type DynBuilder = Arc<dyn Builder + Send + Sync>;

View File

@ -23,19 +23,22 @@ impl DefaultExecutor {
impl Executor for DefaultExecutor { impl Executor for DefaultExecutor {
async fn execute( async fn execute(
&self, &self,
victim_path: PathBuf, victim_path: &PathBuf,
action_path: PathBuf, action_path: &PathBuf,
action: Action, action: &Action,
) -> eyre::Result<()> { ) -> eyre::Result<()> {
tracing::trace!( tracing::trace!(
victim_path = victim_path.to_string_lossy().to_string(), victim_path = victim_path.to_string_lossy().to_string(),
"execute" "execute"
); );
let bin = self.builder.build(action_path, action.clone()).await?; let bin = self.builder.build(action_path, action).await?;
match action { match action {
Action::Go { .. } => { Action::Go { .. } => {
GolangExecutor::new() GolangExecutor::new()
.execute(GolangExecutorOpts { bin, victim_path }) .execute(GolangExecutorOpts {
bin,
victim_path: victim_path.clone(),
})
.await? .await?
} }
} }

View File

@ -8,9 +8,9 @@ use crate::schema::models::Action;
pub trait Executor { pub trait Executor {
async fn execute( async fn execute(
&self, &self,
victim_path: PathBuf, victim_path: &PathBuf,
action_path: PathBuf, action_path: &PathBuf,
action: Action, action: &Action,
) -> eyre::Result<()>; ) -> eyre::Result<()>;
} }

View File

@ -15,7 +15,7 @@ impl GolangExecutor {
} }
pub async fn execute(&self, opts: GolangExecutorOpts) -> eyre::Result<()> { pub async fn execute(&self, opts: GolangExecutorOpts) -> eyre::Result<()> {
opts.bin.run(opts.victim_path).await?; opts.bin.run(&opts.victim_path).await?;
Ok(()) Ok(())
} }

View File

@ -29,7 +29,8 @@ impl LocalGitProvider {
#[async_trait::async_trait] #[async_trait::async_trait]
impl GitProvider for LocalGitProvider { 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"); tracing::debug!(url, "allocating dir");
let dir = self.storage_engine.allocate_dir().await?; let dir = self.storage_engine.allocate_dir().await?;
let options = self.options.clone(); let options = self.options.clone();
@ -65,7 +66,6 @@ impl GitProvider for LocalGitProvider {
builder.fetch_options(fo).with_checkout(checkout_builder); builder.fetch_options(fo).with_checkout(checkout_builder);
tracing::debug!( tracing::debug!(
url,
path = dirpath.as_os_str().to_string_lossy().to_string(), path = dirpath.as_os_str().to_string_lossy().to_string(),
"clone git repo" "clone git repo"
); );

View File

@ -24,7 +24,7 @@ pub type DynGiteaClient = Arc<dyn GiteaClient + Send + Sync>;
#[async_trait] #[async_trait]
pub trait GiteaProvider { 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( async fn create_branch(
&self, &self,
repo: Arc<Mutex<Repository>>, repo: Arc<Mutex<Repository>>,

View File

@ -30,7 +30,7 @@ impl DefaultGiteaProvider {
#[async_trait] #[async_trait]
impl GiteaProvider for DefaultGiteaProvider { 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 let (owner, repo_name) = repo
.split_once("/") .split_once("/")
.ok_or(eyre::anyhow!("repo is not a valid format"))?; .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()) .get_clone_url(owner.into(), repo_name.into())
.await?; .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)) Ok((path, repo))
} }

View File

@ -4,14 +4,12 @@ use async_trait::async_trait;
use git2::Repository; use git2::Repository;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use crate::schema::models::GitPushBranch;
pub mod git; pub mod git;
pub mod gitea; pub mod gitea;
#[async_trait] #[async_trait]
pub trait GitProvider { 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( async fn create_branch(
&self, &self,
repo: Arc<Mutex<Repository>>, repo: Arc<Mutex<Repository>>,

View File

@ -2,5 +2,6 @@ pub mod builder;
pub mod executor; pub mod executor;
pub mod git; pub mod git;
pub mod schema; pub mod schema;
pub mod selectors;
mod shell; mod shell;
pub mod storage; pub mod storage;

View File

@ -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(())
}
}

View File

@ -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(())
}
}

View File

@ -0,0 +1,3 @@
pub mod git_selector;
pub mod gitea_selector;

View File

@ -13,6 +13,7 @@ use octopush_core::{
DynGitProvider, DynGitProvider,
}, },
schema::parser::{DefaultSchemaParser, DynSchemaParser}, schema::parser::{DefaultSchemaParser, DynSchemaParser},
selectors::{git_selector::GitSelector, gitea_selector::GiteaSelector},
storage::{local::LocalStorageEngine, DynStorageEngine}, storage::{local::LocalStorageEngine, DynStorageEngine},
}; };
@ -23,6 +24,8 @@ pub struct ServiceRegister {
pub builder: DynBuilder, pub builder: DynBuilder,
pub executor: DynExecutor, pub executor: DynExecutor,
pub gitea_provider: DynGiteaProvider, pub gitea_provider: DynGiteaProvider,
pub git_selector: Arc<GitSelector>,
pub gitea_selector: Arc<GiteaSelector>,
} }
impl ServiceRegister { impl ServiceRegister {
@ -44,6 +47,12 @@ impl ServiceRegister {
storage_engine.clone(), storage_engine.clone(),
gitea_client.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 { Self {
storage_engine, storage_engine,
@ -52,6 +61,8 @@ impl ServiceRegister {
builder, builder,
executor, executor,
gitea_provider, gitea_provider,
git_selector,
gitea_selector,
} }
} }