Skip to main content

rebuilderd_common/api/v0/
mod.rs

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        // this list is always fairly short, so using contains should be fine
191        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            // we've checked that artifacts is not empty
203            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), // v0 had no concept of FAIL
299            _ => 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}