1use regex::Regex;
2
3use super::{FailurePattern, FailureStrategy, Pattern, SuccessPattern, SuccessStrategy};
4
5pub fn builtin_patterns() -> Vec<Pattern> {
7 vec![
8 Pattern {
10 command_match: Regex::new(r"(?:^|\b)pytest\b")
11 .expect("valid regex: pytest command_match"),
12 success: Some(SuccessPattern {
13 strategy: SuccessStrategy::Regex {
14 pattern: Regex::new(r"(?P<passed>\d+) passed.*in (?P<time>[\d.]+)s")
15 .expect("valid regex: pytest success pattern"),
16 summary: "{passed} passed, {time}s".into(),
17 },
18 }),
19 failure: Some(FailurePattern {
20 strategy: FailureStrategy::Tail { lines: 30 },
21 }),
22 },
23 Pattern {
25 command_match: Regex::new(r"\bcargo\s+test\b")
26 .expect("valid regex: cargo test command_match"),
27 success: Some(SuccessPattern {
28 strategy: SuccessStrategy::Regex {
29 pattern: Regex::new(
30 r"test result: ok\. (?P<passed>\d+) passed; (?P<failed>\d+) failed.*finished in (?P<time>[\d.]+)s",
31 )
32 .expect("valid regex: cargo test success pattern"),
33 summary: "{passed} passed, {time}s".into(),
34 },
35 }),
36 failure: Some(FailurePattern {
37 strategy: FailureStrategy::Tail { lines: 40 },
38 }),
39 },
40 Pattern {
42 command_match: Regex::new(r"\bgo\s+test\b")
43 .expect("valid regex: go test command_match"),
44 success: Some(SuccessPattern {
45 strategy: SuccessStrategy::Regex {
46 pattern: Regex::new(r"ok\s+\S+\s+(?P<time>[\d.]+)s")
47 .expect("valid regex: go test success pattern"),
48 summary: "ok ({time}s)".into(),
49 },
50 }),
51 failure: Some(FailurePattern {
52 strategy: FailureStrategy::Tail { lines: 30 },
53 }),
54 },
55 Pattern {
57 command_match: Regex::new(r"\b(?:jest|vitest|npx\s+(?:jest|vitest))\b")
58 .expect("valid regex: jest/vitest command_match"),
59 success: Some(SuccessPattern {
60 strategy: SuccessStrategy::Regex {
61 pattern: Regex::new(
62 r"Tests:\s+(?P<passed>\d+) passed.*Time:\s+(?P<time>[\d.]+)\s*s",
63 )
64 .expect("valid regex: jest/vitest success pattern"),
65 summary: "{passed} passed, {time}s".into(),
66 },
67 }),
68 failure: Some(FailurePattern {
69 strategy: FailureStrategy::Tail { lines: 30 },
70 }),
71 },
72 Pattern {
74 command_match: Regex::new(r"\bruff\s+check\b")
75 .expect("valid regex: ruff check command_match"),
76 success: Some(SuccessPattern {
77 strategy: SuccessStrategy::Regex {
78 pattern: Regex::new(r"All checks passed")
79 .expect("valid regex: ruff check success pattern"),
80 summary: String::new(), },
82 }),
83 failure: None, },
85 Pattern {
87 command_match: Regex::new(r"\beslint\b")
88 .expect("valid regex: eslint command_match"),
89 success: Some(SuccessPattern {
90 strategy: SuccessStrategy::Regex {
91 pattern: Regex::new(r"(?s).*")
92 .expect("valid regex: eslint success pattern (always matches)"),
93 summary: String::new(),
94 },
95 }),
96 failure: None,
97 },
98 Pattern {
100 command_match: Regex::new(r"\bcargo\s+build\b")
101 .expect("valid regex: cargo build command_match"),
102 success: Some(SuccessPattern {
103 strategy: SuccessStrategy::Regex {
104 pattern: Regex::new(r"(?s).*")
105 .expect("valid regex: cargo build success pattern (always matches)"),
106 summary: String::new(),
107 },
108 }),
109 failure: Some(FailurePattern {
110 strategy: FailureStrategy::Head { lines: 20 },
111 }),
112 },
113 Pattern {
115 command_match: Regex::new(r"\bgo\s+build\b")
116 .expect("valid regex: go build command_match"),
117 success: Some(SuccessPattern {
118 strategy: SuccessStrategy::Regex {
119 pattern: Regex::new(r"(?s).*")
120 .expect("valid regex: go build success pattern (always matches)"),
121 summary: String::new(),
122 },
123 }),
124 failure: Some(FailurePattern {
125 strategy: FailureStrategy::Head { lines: 20 },
126 }),
127 },
128 Pattern {
130 command_match: Regex::new(r"\btsc\b")
131 .expect("valid regex: tsc command_match"),
132 success: Some(SuccessPattern {
133 strategy: SuccessStrategy::Regex {
134 pattern: Regex::new(r"(?s).*")
135 .expect("valid regex: tsc success pattern (always matches)"),
136 summary: String::new(),
137 },
138 }),
139 failure: Some(FailurePattern {
140 strategy: FailureStrategy::Head { lines: 20 },
141 }),
142 },
143 Pattern {
145 command_match: Regex::new(r"\bcargo\s+clippy\b")
146 .expect("valid regex: cargo clippy command_match"),
147 success: Some(SuccessPattern {
148 strategy: SuccessStrategy::Regex {
149 pattern: Regex::new(r"(?s).*")
150 .expect("valid regex: cargo clippy success pattern (always matches)"),
151 summary: String::new(),
152 },
153 }),
154 failure: None,
155 },
156 nodejs_test_pattern(r"npm\s+test"),
158 nodejs_test_pattern(r"yarn\s+test"),
159 nodejs_test_pattern(r"pnpm\s+test"),
160 nodejs_test_pattern(r"bun\s+test"),
161 Pattern {
163 command_match: Regex::new(r"\bcargo\s+tarpaulin\b")
164 .expect("valid regex: cargo tarpaulin command_match"),
165 success: Some(SuccessPattern {
166 strategy: SuccessStrategy::Regex {
167 pattern: Regex::new(r"Overall coverage: (?P<cov>[\d.]+)%")
168 .expect("valid regex: cargo tarpaulin success pattern"),
169 summary: "{cov}% coverage".into(),
170 },
171 }),
172 failure: Some(FailurePattern {
173 strategy: FailureStrategy::Tail { lines: 20 },
174 }),
175 },
176 Pattern {
178 command_match: Regex::new(r"\bcargo\s+fmt\b")
179 .expect("valid regex: cargo fmt command_match"),
180 success: Some(SuccessPattern {
181 strategy: SuccessStrategy::Regex {
182 pattern: Regex::new(r"(?s).*")
183 .expect("valid regex: cargo fmt success pattern (always matches)"),
184 summary: String::new(),
185 },
186 }),
187 failure: Some(FailurePattern {
188 strategy: FailureStrategy::Grep {
189 pattern: Regex::new(r"Diff in").expect("valid regex: cargo fmt failure pattern"),
190 },
191 }),
192 },
193 Pattern {
195 command_match: Regex::new(r"\bmypy\b")
196 .expect("valid regex: mypy command_match"),
197 success: Some(SuccessPattern {
198 strategy: SuccessStrategy::Regex {
199 pattern: Regex::new(r"Success: no issues found")
200 .expect("valid regex: mypy success pattern"),
201 summary: "Success: no issues found".into(),
202 },
203 }),
204 failure: Some(FailurePattern {
205 strategy: FailureStrategy::Head { lines: 20 },
206 }),
207 },
208 Pattern {
210 command_match: Regex::new(r"\brubocop\b")
211 .expect("valid regex: rubocop command_match"),
212 success: Some(SuccessPattern {
213 strategy: SuccessStrategy::Regex {
214 pattern: Regex::new(r"(?P<offenses>\d+) offenses detected")
215 .expect("valid regex: rubocop success pattern"),
216 summary: "{offenses} offenses".into(),
217 },
218 }),
219 failure: Some(FailurePattern {
220 strategy: FailureStrategy::Head { lines: 30 },
221 }),
222 },
223 Pattern {
225 command_match: Regex::new(r"\bruff\s+format\b")
226 .expect("valid regex: ruff format command_match"),
227 success: Some(SuccessPattern {
228 strategy: SuccessStrategy::Regex {
229 pattern: Regex::new(r"(?P<count>\d+) files reformatted")
230 .expect("valid regex: ruff format success pattern"),
231 summary: "{count} files reformatted".into(),
232 },
233 }),
234 failure: Some(FailurePattern {
235 strategy: FailureStrategy::Head { lines: 20 },
236 }),
237 },
238 Pattern {
240 command_match: Regex::new(r"\bprettier\b")
241 .expect("valid regex: prettier command_match"),
242 success: Some(SuccessPattern {
243 strategy: SuccessStrategy::Regex {
244 pattern: Regex::new(r"(?s).*")
245 .expect("valid regex: prettier success pattern (always matches)"),
246 summary: String::new(),
247 },
248 }),
249 failure: Some(FailurePattern {
250 strategy: FailureStrategy::Head { lines: 20 },
251 }),
252 },
253 Pattern {
255 command_match: Regex::new(r"\bnpm\s+run\s+build\b")
256 .expect("valid regex: npm run build command_match"),
257 success: Some(SuccessPattern {
258 strategy: SuccessStrategy::Regex {
259 pattern: Regex::new(r"(?s).*")
260 .expect("valid regex: npm run build success pattern (always matches)"),
261 summary: String::new(),
262 },
263 }),
264 failure: Some(FailurePattern {
265 strategy: FailureStrategy::Head { lines: 20 },
266 }),
267 },
268 Pattern {
270 command_match: Regex::new(r"\byarn\s+build\b")
271 .expect("valid regex: yarn build command_match"),
272 success: Some(SuccessPattern {
273 strategy: SuccessStrategy::Regex {
274 pattern: Regex::new(r"Done in (?P<time>[\d.]+)s")
275 .expect("valid regex: yarn build success pattern"),
276 summary: "Done in {time}s".into(),
277 },
278 }),
279 failure: Some(FailurePattern {
280 strategy: FailureStrategy::Head { lines: 20 },
281 }),
282 },
283 nodejs_quiet_build_pattern(r"pnpm\s+build"),
285 nodejs_quiet_build_pattern(r"bun\s+build"),
287 ]
288}
289
290fn nodejs_test_pattern(command_match: &str) -> Pattern {
296 Pattern {
297 command_match: Regex::new(command_match)
298 .unwrap_or_else(|e| panic!("valid regex: {command_match} command_match: {e}")),
299 success: Some(SuccessPattern {
300 strategy: SuccessStrategy::Regex {
301 pattern: Regex::new(
302 r"(?s)Tests:\s+(?P<passed>\d+) passed.*Time:\s+(?P<time>[\d.]+)\s*s",
303 )
304 .expect("valid regex: nodejs test success pattern"),
305 summary: "{passed} passed, {time}s".into(),
306 },
307 }),
308 failure: Some(FailurePattern {
309 strategy: FailureStrategy::Tail { lines: 30 },
310 }),
311 }
312}
313
314fn nodejs_quiet_build_pattern(command_match: &str) -> Pattern {
319 Pattern {
320 command_match: Regex::new(command_match)
321 .unwrap_or_else(|e| panic!("valid regex: {command_match} command_match: {e}")),
322 success: Some(SuccessPattern {
323 strategy: SuccessStrategy::Regex {
324 pattern: Regex::new(r"(?s).*")
325 .expect("valid regex: nodejs quiet build success pattern (always matches)"),
326 summary: String::new(),
327 },
328 }),
329 failure: Some(FailurePattern {
330 strategy: FailureStrategy::Head { lines: 20 },
331 }),
332 }
333}