Add github (#41)
All checks were successful
continuous-integration/drone/push Build is passing

Co-authored-by: kjuulh <contact@kjuulh.io>
Reviewed-on: #41
This commit is contained in:
2022-11-27 20:07:41 +00:00
parent a3ecad1355
commit bb51770505
13 changed files with 812 additions and 36 deletions

View File

@@ -239,9 +239,15 @@ impl GitProvider for LocalGitProvider {
remote.fetch(refspec, Some(&mut fo), None)?;
let fetch_head = repo.find_reference("FETCH_HEAD")?;
let commit = repo.reference_to_annotated_commit(&fetch_head)?;
Self::do_merge(&repo, &branch_name, commit)?;
match repo.find_reference("FETCH_HEAD") {
Ok(fetch_head) => {
let commit = repo.reference_to_annotated_commit(&fetch_head)?;
Self::do_merge(&repo, &branch_name, commit)?;
}
Err(e) => {
tracing::info!(error = e.to_string(), "upstream branch not found");
}
}
Ok(())
}

View File

@@ -0,0 +1,61 @@
use std::sync::Arc;
use async_trait::async_trait;
use octocrab::{Octocrab, OctocrabBuilder};
use super::GitHubClient;
pub struct DefaultGitHubClientOptions {
pub basicauth: Option<String>,
}
pub struct DefaultGitHubClient {
github: Arc<Octocrab>,
}
impl DefaultGitHubClient {
pub fn new(options: &DefaultGitHubClientOptions) -> eyre::Result<Self> {
let mut github = OctocrabBuilder::new();
if let Some(basicauth) = options.basicauth.clone() {
if let Some((username, password)) = basicauth.split_once(":") {
github = github.basic_auth(username.into(), password.into());
}
}
Ok(Self {
github: Arc::new(github.build()?),
})
}
}
#[async_trait]
impl GitHubClient for DefaultGitHubClient {
async fn get_clone_url(&self, owner: String, repo_name: String) -> eyre::Result<String> {
let repo = self.github.repos(&owner, &repo_name).get().await?;
let clone_url = repo
.ssh_url
.ok_or(eyre::anyhow!("clone_url is not set for repository"))?;
Ok(clone_url)
}
async fn create_pull_request(
&self,
owner: &String,
repo_name: &String,
pull_request_name: &String,
) -> eyre::Result<()> {
self.github
.pulls(owner, repo_name)
.create(
pull_request_name.clone(),
pull_request_name.to_lowercase().replace(" ", "-"),
"main",
)
.send()
.await?;
Ok(())
}
}

View File

@@ -0,0 +1,79 @@
use std::{path::PathBuf, sync::Arc};
use async_trait::async_trait;
use git2::Repository;
use tokio::sync::Mutex;
use crate::{git::DynGitProvider, schema::models::GitPushPullRequest, storage::DynStorageEngine};
use super::{DynGitHubClient, GitHubProvider};
pub struct DefaultGitHubProvider {
git_provider: DynGitProvider,
_storage_engine: DynStorageEngine,
github_client: DynGitHubClient,
}
impl DefaultGitHubProvider {
pub fn new(
git_provider: DynGitProvider,
storage_engine: DynStorageEngine,
github_client: DynGitHubClient,
) -> Self {
Self {
git_provider,
_storage_engine: storage_engine,
github_client,
}
}
}
#[async_trait]
impl GitHubProvider for DefaultGitHubProvider {
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"))?;
let clone_url = self
.github_client
.get_clone_url(owner.into(), repo_name.into())
.await?;
let (path, repo) = self.git_provider.clone_from_url(&clone_url).await?;
Ok((path, repo))
}
async fn create_branch(
&self,
repo: Arc<Mutex<Repository>>,
pull_request: &GitPushPullRequest,
) -> eyre::Result<()> {
tracing::trace!("creating branch");
self.git_provider
.create_branch(repo, &pull_request.name)
.await
}
async fn create_pull_request(
&self,
repo: Arc<Mutex<Repository>>,
repo_name: &String,
pull_request: &GitPushPullRequest,
) -> eyre::Result<()> {
let (owner, repo_name) = repo_name
.split_once("/")
.ok_or(eyre::anyhow!("repo is not a valid format"))?;
tracing::trace!("push_branch");
self.git_provider
.push_branch(repo, &pull_request.name)
.await?;
tracing::trace!("create_pull_request");
self.github_client
.create_pull_request(&owner.into(), &repo_name.into(), &pull_request.name)
.await
}
}

View File

@@ -0,0 +1,42 @@
pub mod github_client;
pub mod github_provider;
use std::{path::PathBuf, sync::Arc};
use async_trait::async_trait;
use git2::Repository;
use tokio::sync::Mutex;
use crate::schema::models::GitPushPullRequest;
#[async_trait]
pub trait GitHubClient {
async fn get_clone_url(&self, owner: String, repo_name: String) -> eyre::Result<String>;
async fn create_pull_request(
&self,
owner: &String,
repo_name: &String,
pull_request_name: &String,
) -> eyre::Result<()>;
}
pub type DynGitHubClient = Arc<dyn GitHubClient + Send + Sync>;
#[async_trait]
pub trait GitHubProvider {
async fn clone_from_qualified(&self, repo: &String) -> eyre::Result<(PathBuf, Repository)>;
async fn create_branch(
&self,
repo: Arc<Mutex<Repository>>,
branch: &GitPushPullRequest,
) -> eyre::Result<()>;
async fn create_pull_request(
&self,
repo: Arc<Mutex<Repository>>,
repo_name: &String,
pull_request: &GitPushPullRequest,
) -> eyre::Result<()>;
}
pub type DynGitHubProvider = Arc<dyn GitHubProvider + Send + Sync>;

View File

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

View File

@@ -0,0 +1,59 @@
use std::{path::PathBuf, sync::Arc};
use tokio::sync::Mutex;
use crate::{
executor::executor::DynExecutor,
git::{github::DynGitHubProvider, DynGitProvider},
schema::models::{Action, GitHub},
};
pub struct GitHubSelector {
github_provider: DynGitHubProvider,
git_provider: DynGitProvider,
executor: DynExecutor,
}
impl GitHubSelector {
pub fn new(
github_provider: DynGitHubProvider,
git_provider: DynGitProvider,
executor: DynExecutor,
) -> Self {
Self {
github_provider,
git_provider,
executor,
}
}
pub async fn run(
&self,
git: &GitHub,
action_path: &PathBuf,
action: &Action,
) -> eyre::Result<()> {
tracing::info!("fetching repos");
for repo in &git.repositories {
let gp = self.github_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

@@ -1,3 +1,4 @@
pub mod git_selector;
pub mod gitea_selector;
pub mod github_selector;