create branch

This commit is contained in:
Kasper Juul Hermansen 2022-11-23 22:17:06 +01:00
parent 18ec10914b
commit 6e13263009
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
9 changed files with 126 additions and 37 deletions

Binary file not shown.

View File

@ -7,7 +7,6 @@ func main() {
Echo("# Readme"). Echo("# Readme").
WriteFile("README.md") WriteFile("README.md")
println("i did something!")
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -1,11 +1,12 @@
apiVersion: action apiVersion: action
name: write-a-readme name: write-a-readme
select: select:
git:
repositories: repositories:
- git@git.front.kjuulh.io:kjuulh/octopush-test.git - git@git.front.kjuulh.io:kjuulh/octopush-test.git
# providers: push:
# - gitea: https://git.front.kjuulh.io branch:
# organisation: "cibus" name: "write a readme"
actions: action:
- type: go type: go
entry: "main.go" entry: "main.go"

View File

@ -1,8 +1,9 @@
use std::path::PathBuf; use std::{path::PathBuf, sync::Arc};
use clap::{Arg, ArgAction, ArgMatches, Command}; use clap::{Arg, ArgAction, ArgMatches, Command};
use octopush_core::schema; use octopush_core::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")
@ -36,29 +37,49 @@ pub async fn execute_subcommand(args: &ArgMatches) -> eyre::Result<()> {
schema::models::Schema::Action { schema::models::Schema::Action {
name, name,
select, select,
actions, action,
} => { } => {
tracing::debug!(name, "running action"); tracing::debug!(name, "running action");
tracing::info!("fetching repos"); tracing::info!("fetching repos");
let mut repo_clones = Vec::with_capacity(select.repositories.len()); let mut paths = Vec::new();
for repo in select.repositories {
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(); let gp = service_register.git_provider.clone();
repo_clones.push(tokio::spawn(async move { gp.clone_from_url(repo).await })); repo_clones.push(tokio::spawn(async move { gp.clone_from_url(repo).await }));
} }
let mut paths = Vec::new();
for repo_clone in repo_clones { for repo_clone in repo_clones {
let path = repo_clone.await??; let path = repo_clone.await??;
paths.push(path); paths.push(path);
} }
}
for (path, repo) in 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)
.await?;
}
}
for path in paths {
for action in actions.clone() {
service_register service_register
.executor .executor
.execute(path.clone(), action_path.clone(), action) .execute(path.clone(), action_path.clone(), action.clone())
.await?; .await?;
if let Some(git) = select.git.clone() {
if let Some(push) = git.push {
service_register
.git_provider
.push_branch(repo, &push.branch)
.await?;
}
} }
} }
} }

View File

@ -1,8 +1,9 @@
use std::path::PathBuf; use std::{path::PathBuf, sync::Arc};
use git2::{Cred, RemoteCallbacks}; use git2::{Cred, RemoteCallbacks, Repository};
use tokio::sync::Mutex;
use crate::storage::DynStorageEngine; use crate::{schema::models::GitPushBranch, storage::DynStorageEngine};
use super::GitProvider; use super::GitProvider;
@ -18,12 +19,12 @@ impl GitHubGitProvider {
#[async_trait::async_trait] #[async_trait::async_trait]
impl GitProvider for GitHubGitProvider { impl GitProvider for GitHubGitProvider {
async fn clone_from_url(&self, url: String) -> eyre::Result<PathBuf> { async fn clone_from_url(&self, url: String) -> eyre::Result<(PathBuf, Repository)> {
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 dirpath = dir.clone().path(); let dirpath = dir.clone().path();
let _ = tokio::task::spawn_blocking(move || { let repo = tokio::task::spawn_blocking(move || {
let mut callbacks = RemoteCallbacks::new(); let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(|url, username_from_url, _allowed_types| { callbacks.credentials(|url, username_from_url, _allowed_types| {
tracing::debug!(username_from_url, url, "pulling key from ssh-agent"); tracing::debug!(username_from_url, url, "pulling key from ssh-agent");
@ -47,6 +48,43 @@ impl GitProvider for GitHubGitProvider {
tracing::debug!("done pulling repo"); tracing::debug!("done pulling repo");
Ok(dir.path()) Ok((dir.path(), repo))
}
async fn create_branch(
&self,
repo: Arc<Mutex<Repository>>,
branch: &GitPushBranch,
) -> eyre::Result<()> {
let repo = repo.lock().await;
let head_commit_oid = repo
.head()?
.target()
.ok_or(eyre::anyhow!("could not get access to target commit"))?;
let head_commit = repo.find_commit(head_commit_oid)?;
let newbranch = repo.branch(
&branch.name.to_lowercase().replace(" ", "-"),
&head_commit,
true,
)?;
repo.set_head(
newbranch
.into_reference()
.name()
.ok_or(eyre::anyhow!("could not get name of reference"))?,
)?;
Ok(())
}
async fn push_branch(
&self,
repo: Arc<Mutex<Repository>>,
branch: &GitPushBranch,
) -> eyre::Result<()> {
let repo = repo.lock().await;
Ok(())
} }
} }

View File

@ -1,12 +1,26 @@
use std::{path::PathBuf, sync::Arc}; use std::{path::PathBuf, sync::Arc};
use async_trait::async_trait; use async_trait::async_trait;
use git2::Repository;
use tokio::sync::Mutex;
use crate::schema::models::GitPushBranch;
pub mod github; pub mod github;
#[async_trait] #[async_trait]
pub trait GitProvider { pub trait GitProvider {
async fn clone_from_url(&self, url: String) -> eyre::Result<PathBuf>; async fn clone_from_url(&self, url: String) -> eyre::Result<(PathBuf, Repository)>;
async fn create_branch(
&self,
repo: Arc<Mutex<Repository>>,
branch: &GitPushBranch,
) -> eyre::Result<()>;
async fn push_branch(
&self,
repo: Arc<Mutex<Repository>>,
branch: &GitPushBranch,
) -> eyre::Result<()>;
} }
pub type DynGitProvider = Arc<dyn GitProvider + Send + Sync>; pub type DynGitProvider = Arc<dyn GitProvider + Send + Sync>;

View File

@ -3,10 +3,26 @@ use serde::{Deserialize, Serialize};
pub type Repository = String; pub type Repository = String;
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct SelectAction { pub struct GitPushBranch {
pub name: String,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct GitPush {
pub branch: GitPushBranch,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct Git {
pub push: Option<GitPush>,
pub repositories: Vec<Repository>, pub repositories: Vec<Repository>,
} }
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct SelectAction {
pub git: Option<Git>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum Action { pub enum Action {
@ -21,6 +37,6 @@ pub enum Schema {
Action { Action {
name: String, name: String,
select: SelectAction, select: SelectAction,
actions: Vec<Action>, action: Action,
}, },
} }

View File

@ -60,7 +60,7 @@ actions:
select: SelectAction { select: SelectAction {
repositories: vec!["git@git.front.kjuulh.io:kjuulh/octopush-test.git".into()] repositories: vec!["git@git.front.kjuulh.io:kjuulh/octopush-test.git".into()]
}, },
actions: vec![Action::Go { action: vec![Action::Go {
entry: "main.go".into() entry: "main.go".into()
}] }]
} }

View File

@ -43,7 +43,7 @@ pub async fn execute_shell(cmd: String, path: Option<PathBuf>) -> eyre::Result<(
}); });
while let Some(line) = reader.next_line().await? { while let Some(line) = reader.next_line().await? {
tracing::trace!("{}", line) tracing::trace!("something: {}", line)
} }
Ok(()) Ok(())