Skip to main content

rebuilderd_common/api/v1/models/
build.rs

1use chrono::NaiveDateTime;
2#[cfg(feature = "diesel")]
3use diesel::{
4    AsExpression, FromSqlRow, Queryable, deserialize::FromSql, serialize::Output, serialize::ToSql,
5    sql_types::Text, sqlite::Sqlite, sqlite::SqliteValue,
6};
7use serde::{Deserialize, Serialize};
8use std::error::Error;
9use std::fmt;
10use std::fmt::Formatter;
11
12#[derive(Debug, Serialize, Deserialize)]
13pub struct RebuildReport {
14    pub queue_id: i32,
15    pub built_at: NaiveDateTime,
16    pub build_log: Vec<u8>,
17    pub status: BuildStatus,
18    pub artifacts: Vec<RebuildArtifactReport>,
19}
20
21#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, clap::ValueEnum)]
22#[cfg_attr(feature = "diesel", derive(FromSqlRow, AsExpression))]
23#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
24#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::sqlite::Sqlite)))]
25pub enum BuildStatus {
26    #[serde(rename = "GOOD")]
27    #[clap(name = "GOOD")]
28    Good,
29
30    #[serde(rename = "BAD")]
31    #[clap(name = "BAD")]
32    Bad,
33
34    #[serde(rename = "FAIL")]
35    #[clap(name = "FAIL")]
36    Fail,
37
38    #[serde(rename = "UNKWN")]
39    #[clap(name = "UNKWN")]
40    Unknown,
41}
42
43impl BuildStatus {
44    pub fn as_str(&self) -> &str {
45        match self {
46            BuildStatus::Good => "GOOD",
47            BuildStatus::Bad => "BAD",
48            BuildStatus::Fail => "FAIL",
49            BuildStatus::Unknown => "UNKWN",
50        }
51    }
52}
53
54#[derive(Debug, Clone)]
55pub struct BuildStatusParseError {
56    value: String,
57}
58
59impl fmt::Display for BuildStatusParseError {
60    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
61        let value = &self.value;
62        write!(f, "could not parse \"{value}\" as a build status")
63    }
64}
65
66impl Error for BuildStatusParseError {}
67
68impl TryFrom<&str> for BuildStatus {
69    type Error = BuildStatusParseError;
70
71    fn try_from(value: &str) -> Result<Self, Self::Error> {
72        match value {
73            "GOOD" => Ok(BuildStatus::Good),
74            "BAD" => Ok(BuildStatus::Bad),
75            "FAIL" => Ok(BuildStatus::Fail),
76            "UNKWN" => Ok(BuildStatus::Unknown),
77            _ => Err(BuildStatusParseError {
78                value: value.to_string(),
79            }),
80        }
81    }
82}
83
84#[cfg(feature = "diesel")]
85impl FromSql<Text, Sqlite> for BuildStatus {
86    fn from_sql(bytes: SqliteValue) -> diesel::deserialize::Result<Self> {
87        let t = <String as FromSql<Text, Sqlite>>::from_sql(bytes)?;
88        Ok(t.as_str().try_into()?)
89    }
90}
91
92#[cfg(feature = "diesel")]
93impl ToSql<Text, Sqlite> for BuildStatus {
94    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> diesel::serialize::Result {
95        out.set_value(self.as_str());
96        Ok(diesel::serialize::IsNull::No)
97    }
98}
99
100#[derive(Debug, Serialize, Deserialize)]
101pub struct RebuildArtifactReport {
102    pub name: String,
103    pub diffoscope: Option<Vec<u8>>,
104    pub attestation: Option<Vec<u8>>,
105    pub status: ArtifactStatus,
106}
107
108#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, clap::ValueEnum)]
109#[cfg_attr(feature = "diesel", derive(FromSqlRow, AsExpression))]
110#[cfg_attr(feature = "diesel", diesel(sql_type = Text))]
111#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::sqlite::Sqlite)))]
112pub enum ArtifactStatus {
113    #[serde(rename = "GOOD")]
114    #[clap(name = "GOOD")]
115    Good,
116
117    #[serde(rename = "BAD")]
118    #[clap(name = "BAD")]
119    Bad,
120
121    #[serde(rename = "UNKWN")]
122    #[clap(name = "UNKWN")]
123    Unknown,
124}
125
126impl ArtifactStatus {
127    pub fn as_str(&self) -> &str {
128        match self {
129            ArtifactStatus::Good => "GOOD",
130            ArtifactStatus::Bad => "BAD",
131            ArtifactStatus::Unknown => "UNKWN",
132        }
133    }
134}
135
136#[derive(Debug, Clone)]
137pub struct ArtifactStatusParseError {
138    value: String,
139}
140
141impl fmt::Display for ArtifactStatusParseError {
142    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
143        let value = &self.value;
144        write!(f, "could not parse \"{value}\" as an artifact status")
145    }
146}
147
148impl Error for ArtifactStatusParseError {}
149
150impl TryFrom<&str> for ArtifactStatus {
151    type Error = ArtifactStatusParseError;
152
153    fn try_from(value: &str) -> Result<Self, Self::Error> {
154        match value {
155            "GOOD" => Ok(ArtifactStatus::Good),
156            "BAD" => Ok(ArtifactStatus::Bad),
157            "UNKWN" => Ok(ArtifactStatus::Unknown),
158            _ => Err(ArtifactStatusParseError {
159                value: value.to_string(),
160            }),
161        }
162    }
163}
164
165#[cfg(feature = "diesel")]
166impl FromSql<Text, Sqlite> for ArtifactStatus {
167    fn from_sql(bytes: SqliteValue) -> diesel::deserialize::Result<Self> {
168        let t = <String as FromSql<Text, Sqlite>>::from_sql(bytes)?;
169        Ok(t.as_str().try_into()?)
170    }
171}
172
173#[cfg(feature = "diesel")]
174impl ToSql<Text, Sqlite> for ArtifactStatus {
175    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> diesel::serialize::Result {
176        out.set_value(self.as_str());
177        Ok(diesel::serialize::IsNull::No)
178    }
179}
180
181#[derive(Debug, Serialize, Deserialize)]
182#[cfg_attr(feature = "diesel", derive(Queryable))]
183#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::sqlite::Sqlite)))]
184pub struct Rebuild {
185    pub id: i32,
186    pub name: String,
187    pub version: String,
188    pub distribution: String,
189    pub release: Option<String>,
190    pub component: Option<String>,
191    pub architecture: String,
192    pub backend: String,
193    pub retries: i32,
194    pub started_at: Option<NaiveDateTime>,
195    pub built_at: Option<NaiveDateTime>,
196    pub status: Option<BuildStatus>,
197}
198
199#[derive(Debug, Serialize, Deserialize)]
200#[cfg_attr(feature = "diesel", derive(Queryable))]
201#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::sqlite::Sqlite)))]
202pub struct RebuildArtifact {
203    pub id: i32,
204    pub name: String,
205    pub has_diffoscope: bool,
206    pub has_attestation: bool,
207    pub status: Option<ArtifactStatus>,
208}