Skip to main content

pipedash_core/domain/
provider.rs

1use std::collections::HashMap;
2
3use async_trait::async_trait;
4use serde::{
5    Deserialize,
6    Serialize,
7};
8
9use super::error::DomainResult;
10use super::pipeline::{
11    Pipeline,
12    PipelineRun,
13    TriggerParams,
14};
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct ProviderConfig {
18    pub id: Option<i64>,
19    pub name: String,
20    pub provider_type: String,
21    pub token: String,
22    pub config: HashMap<String, String>,
23    #[serde(default = "default_refresh_interval")]
24    pub refresh_interval: i64,
25    #[serde(default)]
26    pub version: Option<i64>,
27}
28
29fn default_refresh_interval() -> i64 {
30    30
31}
32
33impl ProviderConfig {
34    pub fn display_name(&self) -> &str {
35        self.config
36            .get("display_name")
37            .map(|s| s.as_str())
38            .unwrap_or(&self.name)
39    }
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43#[serde(rename_all = "lowercase")]
44pub enum FetchStatus {
45    Success,
46    Error,
47    Never,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct ProviderSummary {
52    pub id: i64,
53    pub name: String,
54    pub provider_type: String,
55    pub icon: Option<String>,
56    pub pipeline_count: usize,
57    pub last_updated: Option<chrono::DateTime<chrono::Utc>>,
58    pub refresh_interval: i64,
59    pub configured_repositories: Vec<String>,
60    pub last_fetch_status: FetchStatus,
61    pub last_fetch_error: Option<String>,
62    pub last_fetch_at: Option<chrono::DateTime<chrono::Utc>>,
63    pub version: i64,
64}
65
66#[async_trait]
67pub trait Provider: Send + Sync {
68    async fn fetch_pipelines(&self) -> DomainResult<Vec<Pipeline>>;
69
70    async fn fetch_pipelines_paginated(
71        &self, page: usize, page_size: usize,
72    ) -> DomainResult<pipedash_plugin_api::PaginatedResponse<Pipeline>> {
73        use pipedash_plugin_api::PaginatedResponse;
74
75        let all_pipelines = self.fetch_pipelines().await?;
76        let total_count = all_pipelines.len();
77        let start = (page - 1) * page_size;
78        let end = start + page_size;
79
80        let pipelines = if start < total_count {
81            all_pipelines[start..end.min(total_count)].to_vec()
82        } else {
83            Vec::new()
84        };
85
86        Ok(PaginatedResponse::new(
87            pipelines,
88            page,
89            page_size,
90            total_count,
91        ))
92    }
93
94    async fn fetch_run_history(
95        &self, pipeline_id: &str, limit: usize,
96    ) -> DomainResult<Vec<PipelineRun>>;
97
98    async fn fetch_run_details(
99        &self, pipeline_id: &str, run_number: i64,
100    ) -> DomainResult<PipelineRun>;
101
102    async fn trigger_pipeline(&self, params: TriggerParams) -> DomainResult<String>;
103
104    async fn cancel_run(&self, pipeline_id: &str, run_number: i64) -> DomainResult<()>;
105
106    async fn get_workflow_parameters(
107        &self, workflow_id: &str,
108    ) -> DomainResult<Vec<pipedash_plugin_api::WorkflowParameter>>;
109
110    #[allow(dead_code)]
111    async fn validate_credentials(&self) -> DomainResult<bool>;
112
113    #[allow(dead_code)]
114    fn provider_type(&self) -> &str;
115}