1use crate::errors::*;
2use anyhow::bail;
3use chrono::NaiveDateTime;
4use colored::Colorize;
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use std::ops::Deref;
8use std::str::FromStr;
9
10#[derive(Debug, Serialize, Deserialize)]
11pub enum Success {
12 Ok,
13}
14
15#[derive(Debug, Serialize, Deserialize)]
16pub struct Worker {
17 pub key: String,
18 pub addr: String,
19 pub status: Option<String>,
20 pub last_ping: NaiveDateTime,
21 pub online: bool,
22}
23
24#[derive(Debug, Serialize, Deserialize)]
25pub struct WorkQuery {
26 pub supported_backends: Vec<String>,
27}
28
29#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
30pub enum JobAssignment {
31 Nothing,
32 Rebuild(Box<QueueItem>),
33}
34
35#[derive(Debug, Serialize, Deserialize)]
36pub struct SuiteImport {
37 pub distro: String,
38 pub suite: String,
39 pub groups: Vec<PkgGroup>,
40}
41
42#[derive(Debug, Serialize, Deserialize)]
43pub struct ListPkgs {
44 pub name: Option<String>,
45 pub status: Option<Status>,
46 pub distro: Option<String>,
47 pub suite: Option<String>,
48 pub architecture: Option<String>,
49}
50
51#[derive(Debug, Serialize, Deserialize)]
52pub struct QueueList {
53 pub now: NaiveDateTime,
54 pub queue: Vec<QueueItem>,
55}
56
57#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
58pub struct QueueItem {
59 pub id: i32,
60 pub pkgbase: PkgGroup,
61 pub version: String,
62 pub queued_at: NaiveDateTime,
63 pub worker_id: Option<i32>,
64 pub started_at: Option<NaiveDateTime>,
65 pub last_ping: Option<NaiveDateTime>,
66}
67
68#[derive(Debug, Serialize, Deserialize)]
69pub struct ListQueue {
70 pub limit: Option<i64>,
71}
72
73#[derive(Debug, Serialize, Deserialize)]
74pub struct PushQueue {
75 pub name: String,
76 pub version: Option<String>,
77 pub priority: i32,
78 pub distro: String,
79 pub suite: String,
80 pub architecture: Option<String>,
81}
82
83#[derive(Debug, Serialize, Deserialize)]
84pub struct DropQueueItem {
85 pub name: String,
86 pub version: Option<String>,
87 pub distro: String,
88 pub suite: String,
89 pub architecture: Option<String>,
90}
91
92#[derive(Debug, Serialize, Deserialize)]
93pub struct RequeueQuery {
94 pub name: Option<String>,
95 pub status: Option<Status>,
96 pub priority: i32,
97 pub distro: Option<String>,
98 pub suite: Option<String>,
99 pub architecture: Option<String>,
100 pub reset: bool,
101}
102
103#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
104pub enum BuildStatus {
105 Good,
106 Bad,
107 Fail,
108}
109
110#[derive(Debug, Serialize, Deserialize)]
111pub struct Rebuild {
112 pub status: BuildStatus,
113 pub diffoscope: Option<String>,
114 pub attestation: Option<String>,
115}
116
117#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
118pub struct PkgRelease {
119 pub name: String,
120 pub version: String,
121 pub status: Status,
122 pub distro: String,
123 pub suite: String,
124 pub architecture: String,
125 pub artifact_url: String,
126 pub build_id: Option<i32>,
127 pub built_at: Option<NaiveDateTime>,
128 pub has_diffoscope: bool,
129 pub has_attestation: bool,
130}
131
132impl PkgRelease {
133 pub fn new(
134 name: String,
135 version: String,
136 distro: String,
137 suite: String,
138 architecture: String,
139 artifact_url: String,
140 ) -> PkgRelease {
141 PkgRelease {
142 name,
143 version,
144 status: Status::Unknown,
145 distro,
146 suite,
147 architecture,
148 artifact_url,
149 build_id: None,
150 built_at: None,
151 has_diffoscope: false,
152 has_attestation: false,
153 }
154 }
155}
156
157#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
158pub struct PkgGroup {
159 pub name: String,
160 pub version: String,
161
162 pub distro: String,
163 pub suite: String,
164 pub architecture: String,
165
166 pub input_url: Option<String>,
167 pub artifacts: Vec<PkgArtifact>,
168}
169impl PkgGroup {
170 pub fn new(
171 name: String,
172 version: String,
173 distro: String,
174 suite: String,
175 architecture: String,
176 input_url: Option<String>,
177 ) -> PkgGroup {
178 PkgGroup {
179 name,
180 version,
181 distro,
182 suite,
183 architecture,
184 input_url,
185 artifacts: Vec::new(),
186 }
187 }
188
189 pub fn add_artifact(&mut self, artifact: PkgArtifact) {
190 if !self.artifacts.contains(&artifact) {
192 self.artifacts.push(artifact);
193 }
194 }
195
196 pub fn input_url(&self) -> Result<&str> {
197 if let Some(input_url) = &self.input_url {
198 Ok(input_url.as_str())
199 } else if !self.artifacts.is_empty() {
200 let mut artifacts = Vec::from_iter(self.artifacts.iter().collect::<Vec<_>>());
201 artifacts.sort_by_key(|a| &a.name);
202 let input = artifacts.into_iter().next().unwrap();
204 Ok(&input.url)
205 } else {
206 bail!("Package group has no artifacts")
207 }
208 }
209}
210
211#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
212pub struct PkgArtifact {
213 pub name: String,
214 pub version: String,
215 pub url: String,
216}
217
218impl Rebuild {
219 pub fn new(status: BuildStatus) -> Rebuild {
220 Rebuild {
221 status,
222 diffoscope: None,
223 attestation: None,
224 }
225 }
226}
227
228#[derive(Debug, Serialize, Deserialize)]
229pub struct BuildReport {
230 pub queue: QueueItem,
231 pub build_log: String,
232 pub rebuilds: Vec<(PkgArtifact, Rebuild)>,
233}
234
235#[derive(Debug, Serialize, Deserialize)]
236pub struct DashboardResponse {
237 pub suites: HashMap<String, SuiteStats>,
238 pub active_builds: Vec<QueueItem>,
239 pub queue_length: usize,
240 pub now: NaiveDateTime,
241}
242
243#[derive(Debug, Default, Serialize, Deserialize)]
244pub struct SuiteStats {
245 pub good: usize,
246 pub unknown: usize,
247 pub bad: usize,
248}
249
250#[derive(Debug, Default, Serialize, Deserialize)]
251pub struct PingRequest {
252 pub queue_id: i32,
253}
254
255#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, clap::ValueEnum)]
256pub enum Status {
257 #[serde(rename = "GOOD")]
258 #[clap(name = "GOOD")]
259 Good,
260 #[serde(rename = "BAD")]
261 #[clap(name = "BAD")]
262 Bad,
263 #[serde(rename = "UNKWN")]
264 #[clap(name = "UNKWN")]
265 Unknown,
266}
267
268impl Status {
269 pub fn fancy(&self) -> String {
270 match self {
271 Status::Good => "GOOD ".green().to_string(),
272 Status::Bad => "BAD ".red().to_string(),
273 Status::Unknown => "UNKWN".yellow().to_string(),
274 }
275 }
276}
277
278impl Deref for Status {
279 type Target = str;
280
281 fn deref(&self) -> &'static str {
282 match self {
283 Status::Good => "GOOD",
284 Status::Bad => "BAD",
285 Status::Unknown => "UNKWN",
286 }
287 }
288}
289
290impl FromStr for Status {
291 type Err = Error;
292
293 fn from_str(s: &str) -> Result<Status> {
294 match s {
295 "GOOD" => Ok(Status::Good),
296 "BAD" => Ok(Status::Bad),
297 "UNKWN" => Ok(Status::Unknown),
298 "FAIL" => Ok(Status::Bad), _ => bail!("Unknown status: {:?}", s),
300 }
301 }
302}
303
304#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
305pub struct PublicKeys {
306 pub current: Vec<String>,
307}