1use std::collections::HashMap;
2
3use chrono::{
4 DateTime,
5 Utc,
6};
7use serde::{
8 Deserialize,
9 Serialize,
10};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
13#[serde(rename_all = "lowercase")]
14pub enum PipelineStatus {
15 Success,
16 Failed,
17 Running,
18 Pending,
19 Cancelled,
20 Skipped,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct AvailablePipeline {
25 pub id: String,
26 pub name: String,
27 pub description: Option<String>,
28 pub organization: Option<String>,
29 pub repository: Option<String>,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct Pipeline {
34 pub id: String,
35 pub provider_id: i64,
36 pub provider_type: String,
37 pub name: String,
38 pub status: PipelineStatus,
39 pub last_run: Option<DateTime<Utc>>,
40 pub last_updated: DateTime<Utc>,
41 pub repository: String,
42 pub branch: Option<String>,
43 pub workflow_file: Option<String>,
44 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
45 pub metadata: HashMap<String, serde_json::Value>,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct PipelineRun {
50 pub id: String,
51 pub pipeline_id: String,
52 pub run_number: i64,
53 pub status: PipelineStatus,
54 pub started_at: DateTime<Utc>,
55 pub concluded_at: Option<DateTime<Utc>>,
56 pub duration_seconds: Option<i64>,
57 pub logs_url: String,
58 pub commit_sha: Option<String>,
59 pub commit_message: Option<String>,
60 pub branch: Option<String>,
61 pub actor: Option<String>,
62 #[serde(skip_serializing_if = "Option::is_none")]
63 pub inputs: Option<serde_json::Value>,
64 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
65 pub metadata: HashMap<String, serde_json::Value>,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct TriggerParams {
70 pub workflow_id: String,
71 pub inputs: Option<serde_json::Value>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct BuildAgent {
76 pub id: String,
77 pub name: String,
78 pub hostname: String,
79 pub status: String,
80 pub job_id: Option<String>,
81 pub last_seen: DateTime<Utc>,
82 pub metadata: HashMap<String, String>,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct BuildQueue {
87 pub id: String,
88 pub waiting: usize,
89 pub running: usize,
90 pub avg_wait_time: Option<i64>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct BuildArtifact {
95 pub id: String,
96 pub run_id: String,
97 pub filename: String,
98 pub size_bytes: i64,
99 pub download_url: String,
100 pub content_type: Option<String>,
101 pub created_at: DateTime<Utc>,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct Organization {
106 pub id: String,
107 pub name: String,
108 pub description: Option<String>,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112#[serde(tag = "type", rename_all = "lowercase")]
113pub enum WorkflowParameterType {
114 String {
115 #[serde(default)]
116 default: Option<String>,
117 },
118 Boolean {
119 #[serde(default)]
120 default: bool,
121 },
122 Choice {
123 options: Vec<String>,
124 #[serde(default)]
125 default: Option<String>,
126 },
127 Number {
128 #[serde(default)]
129 default: Option<f64>,
130 },
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct WorkflowParameter {
135 pub name: String,
136 pub label: Option<String>,
137 pub description: Option<String>,
138 #[serde(flatten)]
139 pub param_type: WorkflowParameterType,
140 #[serde(default)]
141 pub required: bool,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct PaginationParams {
146 pub page: usize,
147 pub page_size: usize,
148}
149
150impl PaginationParams {
151 pub fn validate(&self) -> Result<(), String> {
152 if self.page == 0 {
153 return Err("Page must be >= 1".to_string());
154 }
155 if self.page_size == 0 {
156 return Err("Page size must be >= 1".to_string());
157 }
158 if self.page_size > 200 {
159 return Err("Page size must be <= 200".to_string());
160 }
161 Ok(())
162 }
163
164 pub fn calculate_offset(&self) -> Result<usize, String> {
165 self.page
166 .checked_sub(1)
167 .and_then(|p| p.checked_mul(self.page_size))
168 .ok_or_else(|| "Pagination offset overflow".to_string())
169 }
170}
171
172impl Default for PaginationParams {
173 fn default() -> Self {
174 Self {
175 page: 1,
176 page_size: 100,
177 }
178 }
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct PaginatedResponse<T> {
183 pub items: Vec<T>,
184 pub page: usize,
185 pub page_size: usize,
186 pub total_count: usize,
187 pub total_pages: usize,
188 pub has_more: bool,
189}
190
191impl<T> PaginatedResponse<T> {
192 pub fn new(items: Vec<T>, page: usize, page_size: usize, total_count: usize) -> Self {
193 let items_count = items.len();
194 let total_pages = if page_size > 0 {
195 total_count.div_ceil(page_size)
196 } else {
197 1
198 };
199 let has_more = items_count == page_size;
200
201 Self {
202 items,
203 page,
204 page_size,
205 total_count,
206 total_pages,
207 has_more,
208 }
209 }
210
211 pub fn empty() -> Self {
212 Self {
213 items: Vec::new(),
214 page: 1,
215 page_size: 100,
216 total_count: 0,
217 total_pages: 0,
218 has_more: false,
219 }
220 }
221}
222
223pub type PaginatedAvailablePipelines = PaginatedResponse<AvailablePipeline>;
224
225#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
226pub struct Permission {
227 pub name: String,
228 pub description: String,
229 pub required: bool,
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct PermissionCheck {
234 pub permission: Permission,
235 pub granted: bool,
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct PermissionStatus {
240 pub permissions: Vec<PermissionCheck>,
241 pub all_granted: bool,
242 pub checked_at: DateTime<Utc>,
243 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
244 pub metadata: HashMap<String, String>,
245}
246
247#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct Feature {
249 pub id: String,
250 pub name: String,
251 pub description: String,
252 pub required_permissions: Vec<String>,
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct FeatureAvailability {
257 pub feature: Feature,
258 pub available: bool,
259 pub missing_permissions: Vec<String>,
260}