WIP: gitea

This commit is contained in:
Kasper Juul Hermansen 2022-11-24 22:10:34 +01:00
parent 0f8db6be08
commit 1a3084e651
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
9 changed files with 155 additions and 13 deletions

View File

@ -1,6 +1,20 @@
apiVersion: action
name: write-a-readme
select:
github:
repositories:
- kjuulh/octopush-test
push:
pull-request:
name: "write a readme"
gitea:
repositories:
- kjuulh/octopush-test
push:
pull-request:
name: "write a readme"
git:
repositories:
- git@git.front.kjuulh.io:kjuulh/octopush-test.git

View File

@ -42,8 +42,7 @@ pub async fn execute_subcommand(args: &ArgMatches) -> eyre::Result<()> {
tracing::debug!(name, "running action");
tracing::info!("fetching repos");
let mut paths = Vec::new();
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 {
@ -53,11 +52,27 @@ pub async fn execute_subcommand(args: &ArgMatches) -> eyre::Result<()> {
for repo_clone in repo_clones {
let path = repo_clone.await??;
paths.push(path);
git_paths.push(path);
}
}
for (path, repo) in paths {
let mut gitea_paths = Vec::new();
if let Some(gitea) = &select.gitea {
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).await },
))
}
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 {

View File

@ -1,24 +1,24 @@
use std::{path::PathBuf, sync::Arc};
use git2::{Cred, RemoteCallbacks, Repository, Signature};
use git2::{Cred, PushOptions, RemoteCallbacks, Repository};
use tokio::sync::Mutex;
use crate::{schema::models::GitPushBranch, storage::DynStorageEngine};
use super::GitProvider;
pub struct GitHubGitProvider {
pub struct LocalGitProvider {
storage_engine: DynStorageEngine,
}
impl GitHubGitProvider {
impl LocalGitProvider {
pub fn new(storage_engine: DynStorageEngine) -> Self {
Self { storage_engine }
}
}
#[async_trait::async_trait]
impl GitProvider for GitHubGitProvider {
impl GitProvider for LocalGitProvider {
async fn clone_from_url(&self, url: String) -> eyre::Result<(PathBuf, Repository)> {
tracing::debug!(url, "allocating dir");
let dir = self.storage_engine.allocate_dir().await?;
@ -86,12 +86,13 @@ impl GitProvider for GitHubGitProvider {
) -> eyre::Result<()> {
let repo = repo.lock().await;
tracing::trace!("pulling signature from local git");
let signature = repo.signature()?;
tracing::trace!("fetching index and adding changed files to working tree");
let mut index = repo.index()?;
index.add_path(PathBuf::from(".").as_path())?;
index.add_all(&["."], git2::IndexAddOption::DEFAULT, None)?;
index.write()?;
let tree = index.write_tree()?;
let tree = repo.find_tree(tree)?;
@ -101,6 +102,7 @@ impl GitProvider for GitHubGitProvider {
.map(|t| repo.find_commit(t))
})???;
tracing::trace!("writing commit object");
repo.commit(
None,
&signature,
@ -110,6 +112,24 @@ impl GitProvider for GitHubGitProvider {
&[&parents],
)?;
let mut remote = repo.find_remote("origin")?;
let head = repo.head()?;
let refspec = &[head
.name()
.ok_or(eyre::anyhow!("could not find head.name"))?];
let mut remote_callbacks = RemoteCallbacks::new();
remote_callbacks.credentials(|url, username_from_url, _allowed_types| {
tracing::debug!(username_from_url, url, "pulling key from ssh-agent");
Cred::ssh_key_from_agent(username_from_url.unwrap())
});
let mut push_options = PushOptions::new();
push_options.remote_callbacks(remote_callbacks);
tracing::trace!("pushing to remote");
remote.push(refspec, Some(&mut push_options))?;
Ok(())
}
}

View File

@ -0,0 +1,7 @@
pub struct DefaultGiteaClient {}
impl DefaultGiteaClient {
pub fn new() -> Self {
Self {}
}
}

View File

@ -0,0 +1,17 @@
pub mod client;
pub mod provider;
use std::sync::Arc;
use async_trait::async_trait;
pub trait GiteaClient {}
pub type DynGiteaClient = Arc<dyn GiteaClient + Send + Sync>;
#[async_trait]
pub trait GiteaProvider {
async fn clone_from_qualified(repo: String) -> eyre::Result<String>;
}
pub type DynGiteaProvider = Arc<dyn GiteaProvider + Send + Sync>;

View File

@ -0,0 +1,32 @@
use async_trait::async_trait;
use crate::{git::DynGitProvider, storage::DynStorageEngine};
use super::{DynGiteaClient, GiteaProvider};
pub struct DefaultGiteaProvider {
git_provider: DynGitProvider,
storage_engine: DynStorageEngine,
gitea_client: DynGiteaClient,
}
impl DefaultGiteaProvider {
pub fn new(
git_provider: DynGitProvider,
storage_engine: DynStorageEngine,
gitea_client: DynGiteaClient,
) -> Self {
Self {
git_provider,
storage_engine,
gitea_client,
}
}
}
#[async_trait]
impl GiteaProvider for DefaultGiteaProvider {
async fn clone_from_qualified(repo: String) -> eyre::Result<String> {
todo!()
}
}

View File

@ -6,7 +6,8 @@ use tokio::sync::Mutex;
use crate::schema::models::GitPushBranch;
pub mod github;
pub mod git;
pub mod gitea;
#[async_trait]
pub trait GitProvider {

View File

@ -7,6 +7,11 @@ pub struct GitPushBranch {
pub name: String,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct GitPushPullRequest {
pub name: String,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct GitPush {
pub branch: GitPushBranch,
@ -18,9 +23,33 @@ pub struct Git {
pub repositories: Vec<Repository>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct GitHubPush {
pub branch: GitPushPullRequest,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct GiteaPush {
pub branch: GitPushPullRequest,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct GitHub {
pub push: Option<GitHubPush>,
pub repositories: Vec<Repository>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct Gitea {
pub push: Option<GiteaPush>,
pub repositories: Vec<Repository>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct SelectAction {
pub git: Option<Git>,
pub github: Option<GitHub>,
pub gitea: Option<Gitea>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]

View File

@ -3,7 +3,11 @@ use std::sync::Arc;
use octopush_core::{
builder::{builder_capabilities::BuilderCapabilities, DynBuilder},
executor::{default_executor::DefaultExecutor, executor::DynExecutor},
git::{github::GitHubGitProvider, DynGitProvider},
git::{
git::LocalGitProvider,
gitea::{provider::DefaultGiteaProvider, DynGiteaProvider},
DynGitProvider,
},
schema::parser::{DefaultSchemaParser, DynSchemaParser},
storage::{local::LocalStorageEngine, DynStorageEngine},
};
@ -14,15 +18,17 @@ pub struct ServiceRegister {
pub schema_parser: DynSchemaParser,
pub builder: DynBuilder,
pub executor: DynExecutor,
pub gitea_provider: DynGiteaProvider,
}
impl ServiceRegister {
pub fn new() -> Self {
let storage_engine = Arc::new(LocalStorageEngine::new("/tmp/octopush".into()));
let git_provider = Arc::new(GitHubGitProvider::new(storage_engine.clone()));
let git_provider = Arc::new(LocalGitProvider::new(storage_engine.clone()));
let schema_parser = Arc::new(DefaultSchemaParser::new());
let builder = Arc::new(BuilderCapabilities::new());
let executor = Arc::new(DefaultExecutor::new(builder.clone()));
let gitea_provider = Arc::new(DefaultGiteaProvider::new(git_provider.clone()));
Self {
storage_engine,
@ -30,6 +36,7 @@ impl ServiceRegister {
schema_parser,
builder,
executor,
gitea_provider,
}
}