Rewrite rust #38
@ -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
|
|
||||||
.git_provider
|
|
||||||
.create_branch(repo.clone(), &push.branch.name)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
service_register
|
service_register
|
||||||
.executor
|
.git_selector
|
||||||
.execute(path.clone(), action_path.clone(), action.clone())
|
.run(git, &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 {
|
if let Some(gitea) = &select.gitea {
|
||||||
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
|
service_register
|
||||||
.executor
|
.gitea_selector
|
||||||
.execute(path.clone(), action_path.clone(), action.clone())
|
.run(gitea, &action_path, &action)
|
||||||
.await?;
|
.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?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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?;
|
||||||
|
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -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>;
|
||||||
|
@ -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?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
);
|
);
|
||||||
|
@ -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>>,
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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>>,
|
||||||
|
@ -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;
|
||||||
|
48
crates/octopush_core/src/selectors/git_selector.rs
Normal file
48
crates/octopush_core/src/selectors/git_selector.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
}
|
59
crates/octopush_core/src/selectors/gitea_selector.rs
Normal file
59
crates/octopush_core/src/selectors/gitea_selector.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
}
|
3
crates/octopush_core/src/selectors/mod.rs
Normal file
3
crates/octopush_core/src/selectors/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod git_selector;
|
||||||
|
pub mod gitea_selector;
|
||||||
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user