Skip to content

Commit

Permalink
Finish implementing
Browse files Browse the repository at this point in the history
  • Loading branch information
boxbeam committed Apr 25, 2024
1 parent 784174e commit 78797f7
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 51 deletions.
4 changes: 3 additions & 1 deletion ee/tabby-db/migrations/0028_gitlab-provider.down.sql
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
-- Add down migration script here
DROP TABLE gitlab_provided_repositories;
DROP TABLE gitlab_repository_provider;

20 changes: 18 additions & 2 deletions ee/tabby-webserver/src/cron/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use futures::Future;
use tokio_cron_scheduler::Job;
use tracing::{debug, error};

use super::github::refresh_all_repositories;
use super::github;
use super::gitlab;
use crate::schema::gitlab_repository_provider::GitlabRepositoryProviderService;
use crate::schema::{
auth::AuthenticationService, github_repository_provider::GithubRepositoryProviderService,
job::JobService,
Expand Down Expand Up @@ -60,7 +62,21 @@ pub async fn update_integrated_github_repositories_job(
github_repository_provider,
|github_repository_provider| async move {
debug!("Syncing github repositories...");
refresh_all_repositories(github_repository_provider).await
github::refresh_all_repositories(github_repository_provider).await
},
)
.await
}

pub async fn update_integrated_gitlab_repositories_job(
gitlab_repository_provider: Arc<dyn GitlabRepositoryProviderService>,
) -> Result<Job> {
service_job(
"0 * * * * *",
gitlab_repository_provider,
|gitlab_repository_provider| async move {
debug!("Syncing gitlab repositories...");
gitlab::refresh_all_repositories(gitlab_repository_provider).await
},
)
.await
Expand Down
73 changes: 32 additions & 41 deletions ee/tabby-webserver/src/cron/gitlab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ use std::sync::Arc;

use anyhow::Result;
use chrono::Utc;
use gitlab::AsyncGitlab;
use gitlab::{
api::{projects::Projects, AsyncQuery, Pagination},
GitlabBuilder,
};
use juniper::ID;
use octocrab::{models::Repository, GitHubError, Octocrab};
use serde::Deserialize;
use tracing::warn;

use crate::schema::{
github_repository_provider::{GithubRepositoryProvider, GithubRepositoryProviderService},
gitlab_repository_provider::{GitlabRepositoryProvider, GitlabRepositoryProviderService},
use crate::schema::gitlab_repository_provider::{
GitlabRepositoryProvider, GitlabRepositoryProviderService,
};

pub async fn refresh_all_repositories(
Expand All @@ -35,18 +37,15 @@ async fn refresh_repositories_for_provider(
let provider = service.get_gitlab_repository_provider(provider_id).await?;
let repos = match fetch_all_repos(&provider).await {
Ok(repos) => repos,
Err(octocrab::Error::GitHub {
source: source @ GitHubError { .. },
..
}) if source.status_code.is_client_error() => {
Err(e) if e.to_string().contains("401 Unauthorized") => {
service
.reset_gitlab_repository_provider_access_token(provider.id.clone())
.await?;
warn!(
"GitLab credentials for provider {} are expired or invalid",
provider.display_name
);
return Err(source.into());
return Err(e);
}
Err(e) => {
warn!("Failed to fetch repositories from github: {e}");
Expand All @@ -55,49 +54,41 @@ async fn refresh_repositories_for_provider(
};
for repo in repos {
let id = repo.id.to_string();
let Some(url) = repo.git_url else {
continue;
};
let url = url.to_string();

service
.upsert_gitlab_provided_repository(provider.id.clone(), id, repo.name, url)
.upsert_gitlab_provided_repository(
provider.id.clone(),
id,
repo.name,
repo.http_url_to_repo,
)
.await?;
}

Ok(())
}

// FIXME(wsxiaoys): Convert to async stream
#[derive(Deserialize)]
struct Repository {
id: u128,
name: String,
http_url_to_repo: String,
}

async fn fetch_all_repos(
provider: &GitlabRepositoryProvider,
) -> Result<Vec<Repository>, octocrab::Error> {
) -> Result<Vec<Repository>, anyhow::Error> {
let Some(token) = &provider.access_token else {
return Ok(vec![]);
};
let octocrab = Octocrab::builder()
.user_access_token(token.to_string())
.build()?;
let gitlab = GitlabBuilder::new("gitlab.com", token)
.build_async()
.await?;

let mut page = 1;
let mut repos = vec![];

loop {
let response = octocrab
.current()
.list_repos_for_authenticated_user()
.visibility("all")
.page(page)
.send()
.await?;

let pages = response.number_of_pages().unwrap_or_default() as u8;
repos.extend(response.items);

page += 1;
if page > pages {
break;
}
}
Ok(repos)
Ok(gitlab::api::paged(
Projects::builder().membership(true).build()?,
Pagination::All,
)
.query_async(&gitlab)
.await?)
}
13 changes: 9 additions & 4 deletions ee/tabby-webserver/src/cron/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use std::sync::Arc;
use tokio_cron_scheduler::{Job, JobScheduler};

use crate::schema::{
auth::AuthenticationService, github_repository_provider::GithubRepositoryProviderService,
job::JobService, worker::WorkerService,
auth::AuthenticationService, job::JobService, repository::RepositoryService,
worker::WorkerService,
};

async fn new_job_scheduler(jobs: Vec<Job>) -> anyhow::Result<JobScheduler> {
Expand All @@ -25,7 +25,7 @@ pub async fn run_cron(
auth: Arc<dyn AuthenticationService>,
job: Arc<dyn JobService>,
worker: Arc<dyn WorkerService>,
github_repository_provider: Arc<dyn GithubRepositoryProviderService>,
repository: Arc<dyn RepositoryService>,
local_port: u16,
) {
let mut jobs = vec![];
Expand All @@ -50,11 +50,16 @@ pub async fn run_cron(
.expect("failed to create stale job runs cleanup job");
jobs.push(job4);

let job5 = db::update_integrated_github_repositories_job(github_repository_provider)
let job5 = db::update_integrated_github_repositories_job(repository.github())
.await
.expect("Failed to create github repository refresh job");
jobs.push(job5);

let job6 = db::update_integrated_gitlab_repositories_job(repository.gitlab())
.await
.expect("Failed to create gitlab repository refresh job");
jobs.push(job6);

new_job_scheduler(jobs)
.await
.expect("failed to start job scheduler");
Expand Down
2 changes: 1 addition & 1 deletion ee/tabby-webserver/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl WebserverHandle {
ctx.auth(),
ctx.job(),
ctx.worker(),
ctx.repository().github(),
ctx.repository(),
local_port,
)
.await;
Expand Down
2 changes: 2 additions & 0 deletions ee/tabby-webserver/src/schema/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use tabby_search::FileSearch;
use super::{
git_repository::GitRepositoryService,
github_repository_provider::GithubRepositoryProviderService,
gitlab_repository_provider::GitlabRepositoryProviderService,
};

#[derive(GraphQLObject, Debug)]
Expand All @@ -33,5 +34,6 @@ impl From<FileSearch> for FileEntrySearchResult {
pub trait RepositoryService: Send + Sync + RepositoryAccess {
fn git(&self) -> Arc<dyn GitRepositoryService>;
fn github(&self) -> Arc<dyn GithubRepositoryProviderService>;
fn gitlab(&self) -> Arc<dyn GitlabRepositoryProviderService>;
fn access(self: Arc<Self>) -> Arc<dyn RepositoryAccess>;
}
11 changes: 9 additions & 2 deletions ee/tabby-webserver/src/service/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@ use async_trait::async_trait;
use tabby_common::config::{RepositoryAccess, RepositoryConfig};
use tabby_db::DbConn;

use super::github_repository_provider;
use super::{github_repository_provider, gitlab_repository_provider};
use crate::schema::{
git_repository::GitRepositoryService,
github_repository_provider::GithubRepositoryProviderService, repository::RepositoryService,
github_repository_provider::GithubRepositoryProviderService,
gitlab_repository_provider::GitlabRepositoryProviderService, repository::RepositoryService,
};

struct RepositoryServiceImpl {
git: Arc<dyn GitRepositoryService>,
github: Arc<dyn GithubRepositoryProviderService>,
gitlab: Arc<dyn GitlabRepositoryProviderService>,
}

pub fn create(db: DbConn) -> Arc<dyn RepositoryService> {
Arc::new(RepositoryServiceImpl {
git: Arc::new(db.clone()),
github: Arc::new(github_repository_provider::create(db.clone())),
gitlab: Arc::new(gitlab_repository_provider::create(db.clone())),
})
}

Expand Down Expand Up @@ -58,6 +61,10 @@ impl RepositoryService for RepositoryServiceImpl {
fn github(&self) -> Arc<dyn GithubRepositoryProviderService> {
self.github.clone()
}

fn gitlab(&self) -> Arc<dyn GitlabRepositoryProviderService> {
self.gitlab.clone()
}
}

#[cfg(test)]
Expand Down

0 comments on commit 78797f7

Please sign in to comment.