ci_manager/ci_provider/
util.rs1use time::{format_description::well_known, OffsetDateTime};
2
3use crate::*;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Date {
8 pub year: u16,
9 pub month: u8,
10 pub day: u8,
11}
12
13impl fmt::Display for Date {
14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 let Date { year, month, day } = self;
16 write!(f, "{year}-{month:02}-{day:02}")
17 }
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
22pub enum DateFilter {
23 Created(Date),
24 Updated(Date),
25 None,
26}
27
28impl fmt::Display for DateFilter {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 match self {
31 DateFilter::Created(date) => write!(f, "created:{date}"),
32 DateFilter::Updated(date) => write!(f, "updated:{date}"),
33 DateFilter::None => f.write_str(""), }
35 }
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
62pub enum LabelFilter<I, S>
63where
64 I: IntoIterator<Item = S> + Clone,
65 S: AsRef<str> + fmt::Display + fmt::Debug,
66{
67 Any(I),
69 All(I),
71 None(PhantomData<I>),
76}
77
78impl LabelFilter<Vec<String>, String> {
79 pub fn none() -> Self {
81 LabelFilter::None(PhantomData)
82 }
83}
84
85impl<I, S> fmt::Display for LabelFilter<I, S>
86where
87 I: IntoIterator<Item = S> + Clone,
88 S: AsRef<str> + fmt::Display + fmt::Debug,
89{
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 match self {
92 LabelFilter::Any(labels) => write!(
93 f,
94 "label:{}",
95 labels
96 .clone()
97 .into_iter()
98 .map(|l| format!("\"{l}\""))
99 .collect::<Vec<String>>()
100 .join(",")
101 ),
102 LabelFilter::All(labels) => write!(
103 f,
104 "{}",
105 labels
106 .clone()
107 .into_iter()
108 .map(|l| format!("label:\"{l}\""))
109 .collect::<Vec<String>>()
110 .join(" ")
111 ),
112 LabelFilter::None(_) => f.write_str(""), }
114 }
115}
116
117pub fn timestamp_from_log(log: &str) -> Result<OffsetDateTime> {
134 static RE: Lazy<Regex> =
135 Lazy::new(|| Regex::new(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z").unwrap());
136 let captures = RE.captures(log);
137 if let Some(captures) = captures {
138 let timestamp = captures
139 .get(0)
140 .context("Could not extract timestamp")?
141 .as_str();
142 OffsetDateTime::parse(timestamp, &well_known::Iso8601::DEFAULT)
143 .with_context(|| format!("Could not parse timestamp: {timestamp}"))
144 } else {
145 bail!("Could not extract timestamp from log: {log}")
146 }
147}
148
149#[derive(Debug, Clone, PartialEq, Eq)]
150pub struct JobLog {
151 pub name: String,
152 pub content: String,
153}
154
155impl JobLog {
156 pub fn new(name: String, content: String) -> Self {
157 Self { name, content }
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164 use pretty_assertions::{assert_eq, assert_ne};
165
166 #[test]
167 fn test_date_display() {
168 let date = Date {
169 year: 2021,
170 month: 6,
171 day: 2,
172 };
173 assert_eq!(date.to_string(), "2021-06-02");
174 }
175
176 #[test]
177 fn test_date_filter_display() {
178 let date = Date {
179 year: 2021,
180 month: 6,
181 day: 2,
182 };
183 let date_filter = DateFilter::Created(date);
184 assert_eq!(date_filter.to_string(), "created:2021-06-02");
185 }
186
187 #[test]
188 fn test_label_filter_any_display() {
189 let label_filter = LabelFilter::Any(["kind/bug", "area/bake"]);
190 assert_eq!(label_filter.to_string(), r#"label:"kind/bug","area/bake""#);
191 }
192
193 #[test]
194 fn test_label_filter_all_display() {
195 let label_filter = LabelFilter::All(["kind/bug", "area/bake"]);
196 assert_eq!(
197 label_filter.to_string(),
198 r#"label:"kind/bug" label:"area/bake""#
199 );
200 }
201
202 #[test]
203 fn test_label_filter_all_1_display() {
204 let label_filter = LabelFilter::All(["kind/bug"]);
205 assert_eq!(label_filter.to_string(), r#"label:"kind/bug""#);
206 }
207}