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::{
10    DomainResult,
11    FailureKind,
12};
13use super::health::ProviderHealth;
14use super::pipeline::{
15    Pipeline,
16    PipelineRun,
17    TriggerParams,
18};
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct ProviderConfig {
22    pub id: Option<i64>,
23    pub name: String,
24    pub provider_type: String,
25    pub token: String,
26    pub config: HashMap<String, String>,
27    #[serde(default = "default_refresh_interval")]
28    pub refresh_interval: i64,
29    #[serde(default)]
30    pub version: Option<i64>,
31}
32
33fn default_refresh_interval() -> i64 {
34    30
35}
36
37impl ProviderConfig {
38    pub fn display_name(&self) -> &str {
39        self.config
40            .get("display_name")
41            .map(|s| s.as_str())
42            .unwrap_or(&self.name)
43    }
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
47#[serde(rename_all = "lowercase")]
48pub enum FetchStatus {
49    Success,
50    Error,
51    Never,
52}
53
54#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
55pub struct ProviderImportResult {
56    pub added: Vec<String>,
57    pub skipped: Vec<String>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct ProviderSummary {
62    pub id: i64,
63    pub name: String,
64    pub provider_type: String,
65    pub icon: Option<String>,
66    pub pipeline_count: usize,
67    pub last_updated: Option<chrono::DateTime<chrono::Utc>>,
68    pub refresh_interval: i64,
69    pub configured_repositories: Vec<String>,
70    pub last_fetch_status: FetchStatus,
71    pub last_fetch_error: Option<String>,
72    pub last_fetch_at: Option<chrono::DateTime<chrono::Utc>>,
73    #[serde(default)]
74    pub paused_until: Option<chrono::DateTime<chrono::Utc>>,
75    #[serde(default)]
76    pub last_fetch_error_kind: Option<FailureKind>,
77    #[serde(default)]
78    pub health: ProviderHealth,
79    pub version: i64,
80}
81
82#[async_trait]
83pub trait Provider: Send + Sync {
84    async fn fetch_pipelines(&self) -> DomainResult<Vec<Pipeline>>;
85
86    async fn fetch_pipelines_paginated(
87        &self, page: usize, page_size: usize,
88    ) -> DomainResult<pipedash_plugin_api::PaginatedResponse<Pipeline>> {
89        use pipedash_plugin_api::PaginatedResponse;
90
91        let all_pipelines = self.fetch_pipelines().await?;
92        let total_count = all_pipelines.len();
93        let start = (page - 1) * page_size;
94        let end = start + page_size;
95
96        let pipelines = if start < total_count {
97            all_pipelines[start..end.min(total_count)].to_vec()
98        } else {
99            Vec::new()
100        };
101
102        Ok(PaginatedResponse::new(
103            pipelines,
104            page,
105            page_size,
106            total_count,
107        ))
108    }
109
110    async fn fetch_run_history(
111        &self, pipeline_id: &str, limit: usize,
112    ) -> DomainResult<Vec<PipelineRun>>;
113
114    async fn fetch_run_details(
115        &self, pipeline_id: &str, run_number: i64,
116    ) -> DomainResult<PipelineRun>;
117
118    async fn trigger_pipeline(&self, params: TriggerParams) -> DomainResult<String>;
119
120    async fn cancel_run(&self, pipeline_id: &str, run_number: i64) -> DomainResult<()>;
121
122    async fn review_run(
123        &self, pipeline_id: &str, run_number: i64, decision: pipedash_plugin_api::ReviewDecision,
124    ) -> DomainResult<()>;
125
126    async fn get_workflow_parameters(
127        &self, workflow_id: &str,
128    ) -> DomainResult<Vec<pipedash_plugin_api::WorkflowParameter>>;
129
130    async fn fetch_rate_limit(&self) -> DomainResult<Option<pipedash_plugin_api::RateLimit>>;
131
132    #[allow(dead_code)]
133    async fn validate_credentials(&self) -> DomainResult<bool>;
134
135    #[allow(dead_code)]
136    fn provider_type(&self) -> &str;
137
138    fn capabilities(&self) -> &pipedash_plugin_api::PluginCapabilities;
139
140    fn status_source(&self) -> Option<&pipedash_plugin_api::StatusSource>;
141
142    async fn check_health(&self) -> DomainResult<Vec<pipedash_plugin_api::ComponentHealth>>;
143}