Skip to main content

max / makenotwork

2.8 KB · 90 lines History Blame Raw
1 //! Test-suite alert/recovery messages. Domain half of the Alerter split;
2 //! shared dispatch/cooldown plumbing lives in the parent module.
3 //!
4 //! Distinct from [`super::test_duration`], which fires on a suite that still
5 //! passes but has slowed down. These fire on pass/fail transitions.
6
7 use tracing::instrument;
8
9 use super::{AlertCategory, AlertMeta, Alerter};
10
11 impl Alerter {
12 #[instrument(skip_all)]
13 pub async fn send_test_failure_alert(
14 &self,
15 target: &str,
16 label: &str,
17 failed: Option<i64>,
18 exit_code: Option<i64>,
19 detail: &str,
20 ) {
21 let alert_key = format!("tests:{target}");
22 let subject = match failed {
23 Some(n) => format!("[PoM] {label}: {n} test(s) failing"),
24 None => format!("[PoM] {label}: test suite failed to complete"),
25 };
26 let body = format!(
27 "Target: {label} ({target})\n\
28 Failed: {}\n\
29 Exit code: {}\n\
30 Detail: {detail}\n\
31 Instance: {}\n\
32 Time: {}\n\n\
33 - PoM",
34 failed.map_or_else(|| "unknown".to_string(), |n| n.to_string()),
35 exit_code.map_or_else(|| "none".to_string(), |c| c.to_string()),
36 self.instance_name,
37 chrono::Utc::now().to_rfc3339(),
38 );
39
40 // A suite that never produced a count did not run at all (SSH refused,
41 // missing checkout, timeout), which is worse than a known count of
42 // failures: it means the target is unverified rather than broken.
43 let priority = if failed.is_some() { "high" } else { "critical" };
44
45 self.fire_failure(
46 &subject,
47 &body,
48 priority,
49 "pom-tests",
50 Some(target),
51 AlertMeta {
52 key: &alert_key,
53 category: AlertCategory::TestFailure,
54 from: None,
55 to: None,
56 error: Some(detail),
57 },
58 )
59 .await;
60 }
61
62 #[instrument(skip_all)]
63 pub async fn send_test_recovery(&self, target: &str, label: &str) {
64 let alert_key = format!("tests:{target}");
65 let subject = format!("[PoM] {label}: test suite passing again");
66 let body = format!(
67 "Target: {label} ({target})\n\
68 The test suite passed on its latest scheduled run.\n\
69 Instance: {}\n\
70 Time: {}\n\n\
71 - PoM",
72 self.instance_name,
73 chrono::Utc::now().to_rfc3339(),
74 );
75
76 self.fire_recovery(
77 &subject,
78 &body,
79 AlertMeta {
80 key: &alert_key,
81 category: AlertCategory::TestRecovery,
82 from: None,
83 to: None,
84 error: None,
85 },
86 )
87 .await;
88 }
89 }
90