1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
11pub struct Job {
12 pub id: u64,
14
15 pub name: String,
17
18 pub status: JobStatus,
20
21 pub stage: String,
23
24 #[serde(rename = "ref")]
26 pub ref_name: String,
27
28 #[serde(default)]
30 pub sha: Option<String>,
31
32 pub created_at: DateTime<Utc>,
34
35 pub started_at: Option<DateTime<Utc>>,
37
38 pub finished_at: Option<DateTime<Utc>>,
40
41 pub duration: Option<f64>,
43
44 pub queued_duration: Option<f64>,
46
47 pub web_url: String,
49
50 #[serde(default)]
52 pub user: Option<JobUser>,
53
54 #[serde(default)]
56 pub runner: Option<JobRunner>,
57
58 #[serde(default)]
60 pub allow_failure: bool,
61
62 #[serde(default)]
64 pub tag_list: Vec<String>,
65
66 #[serde(default)]
68 pub artifacts: Vec<Artifact>,
69
70 #[serde(default)]
72 pub coverage: Option<f64>,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
77pub struct JobUser {
78 pub id: u64,
80
81 pub username: String,
83
84 pub name: String,
86
87 pub state: String,
89
90 pub avatar_url: Option<String>,
92
93 pub web_url: String,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
99pub struct JobRunner {
100 pub id: u64,
102
103 pub description: String,
105
106 #[serde(default)]
108 pub active: bool,
109
110 #[serde(default)]
112 pub is_shared: bool,
113
114 #[serde(default)]
116 pub name: Option<String>,
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
121pub struct Artifact {
122 pub filename: String,
124
125 pub size: u64,
127
128 #[serde(default)]
130 pub file_type: Option<String>,
131
132 #[serde(default)]
134 pub file_format: Option<String>,
135}
136
137#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
141#[serde(rename_all = "snake_case")]
142pub enum JobStatus {
143 Created,
145
146 Pending,
148
149 Running,
151
152 Success,
154
155 Failed,
157
158 Canceled,
160
161 Skipped,
163
164 Manual,
166
167 Scheduled,
169}
170
171impl JobStatus {
172 pub fn is_finished(self) -> bool {
184 matches!(
185 self,
186 Self::Success | Self::Failed | Self::Canceled | Self::Skipped
187 )
188 }
189
190 pub fn is_active(self) -> bool {
202 matches!(self, Self::Created | Self::Pending | Self::Running)
203 }
204
205 pub fn is_successful(self) -> bool {
216 self == Self::Success
217 }
218
219 pub fn is_failed(self) -> bool {
230 self == Self::Failed
231 }
232}
233
234impl std::fmt::Display for JobStatus {
235 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
236 match self {
237 Self::Created => write!(f, "created"),
238 Self::Pending => write!(f, "pending"),
239 Self::Running => write!(f, "running"),
240 Self::Success => write!(f, "success"),
241 Self::Failed => write!(f, "failed"),
242 Self::Canceled => write!(f, "canceled"),
243 Self::Skipped => write!(f, "skipped"),
244 Self::Manual => write!(f, "manual"),
245 Self::Scheduled => write!(f, "scheduled"),
246 }
247 }
248}
249
250#[cfg(test)]
251mod tests {
252 use super::*;
253
254 #[test]
255 fn test_job_status_is_finished() {
256 assert!(JobStatus::Success.is_finished());
257 assert!(JobStatus::Failed.is_finished());
258 assert!(JobStatus::Canceled.is_finished());
259 assert!(JobStatus::Skipped.is_finished());
260
261 assert!(!JobStatus::Running.is_finished());
262 assert!(!JobStatus::Pending.is_finished());
263 }
264
265 #[test]
266 fn test_job_status_is_active() {
267 assert!(JobStatus::Running.is_active());
268 assert!(JobStatus::Pending.is_active());
269 assert!(JobStatus::Created.is_active());
270
271 assert!(!JobStatus::Success.is_active());
272 assert!(!JobStatus::Failed.is_active());
273 }
274
275 #[test]
276 fn test_job_status_display() {
277 assert_eq!(JobStatus::Success.to_string(), "success");
278 assert_eq!(JobStatus::Failed.to_string(), "failed");
279 assert_eq!(JobStatus::Running.to_string(), "running");
280 }
281
282 #[test]
283 fn test_job_status_serialization() {
284 let status = JobStatus::Success;
285 let json = serde_json::to_string(&status).unwrap();
286 assert_eq!(json, "\"success\"");
287
288 let deserialized: JobStatus = serde_json::from_str(&json).unwrap();
289 assert_eq!(deserialized, JobStatus::Success);
290 }
291}