From e54a1cb82ea4b96cfed6e8901c4c4b5155c82c10 Mon Sep 17 00:00:00 2001 From: boxbeam Date: Mon, 29 Apr 2024 11:50:50 -0400 Subject: [PATCH] fix(webserver): detect gitlab client errors more accurately --- ee/tabby-webserver/src/cron/db/gitlab.rs | 40 ++++++++++++++++++++---- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/ee/tabby-webserver/src/cron/db/gitlab.rs b/ee/tabby-webserver/src/cron/db/gitlab.rs index 6d73b6dbf25e..c503917b739e 100644 --- a/ee/tabby-webserver/src/cron/db/gitlab.rs +++ b/ee/tabby-webserver/src/cron/db/gitlab.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use anyhow::Result; use chrono::Utc; use gitlab::{ - api::{projects::Projects, AsyncQuery, Pagination}, + api::{projects::Projects, ApiError, AsyncQuery, Pagination}, GitlabBuilder, }; use juniper::ID; @@ -46,7 +46,7 @@ async fn refresh_repositories_for_provider( let provider = service.get_provider(provider_id).await?; let repos = match fetch_all_repos(&provider).await { Ok(repos) => repos, - Err(e) if e.to_string().contains("401 Unauthorized") => { + Err(e) if e.is_client_error() => { service .update_provider_status(provider.id.clone(), false) .await?; @@ -56,13 +56,13 @@ async fn refresh_repositories_for_provider( provider.display_name )) .await; - return Err(e); + return Err(e.into()); } Err(e) => { context .stderr_writeline(format!("Failed to fetch repositories from gitlab: {e}")) .await; - return Err(e); + return Err(e.into()); } }; for repo in repos { @@ -96,16 +96,44 @@ struct Repository { http_url_to_repo: String, } +#[derive(thiserror::Error, Debug)] +enum GitlabError { + #[error(transparent)] + Rest(#[from] gitlab::api::ApiError), + #[error(transparent)] + Gitlab(#[from] gitlab::GitlabError), + #[error(transparent)] + Projects(#[from] gitlab::api::projects::ProjectsBuilderError), +} + +impl GitlabError { + fn is_client_error(&self) -> bool { + match self { + GitlabError::Rest(source) + | GitlabError::Gitlab(gitlab::GitlabError::Api { source }) => { + matches!( + source, + ApiError::Auth { .. } + | ApiError::Client { + source: gitlab::RestError::AuthError { .. } + } + | ApiError::Gitlab { .. } + ) + } + _ => false, + } + } +} + async fn fetch_all_repos( provider: &GitlabRepositoryProvider, -) -> Result, anyhow::Error> { +) -> Result, GitlabError> { let Some(token) = &provider.access_token else { return Ok(vec![]); }; let gitlab = GitlabBuilder::new("gitlab.com", token) .build_async() .await?; - Ok(gitlab::api::paged( Projects::builder().membership(true).build()?, Pagination::All,