Classify errors found into groups
[buildd-scripts.git] / bin / analyze_results
1 #! /usr/bin/perl
2
3 # Script to analyze failed build logs. Look for specific regexps to
4 # classify things
5
6 use strict;
7 use warnings;
8 use Data::Dumper;
9
10 my $logs = "/home/build/logs";
11 my $logs_fail = "$logs/FAIL";
12 my $num_fail = 0;
13 my $existing_bugs = 0;
14 use constant {
15     ERR_ARCH_MISMATCH      => 1,
16     ERR_INFRA              => 2,
17     ERR_BD_PROBLEM         => 3,
18     ERR_DETECT_WRONG_ARCH  => 4,
19     ERR_CRASH              => 5,
20     ERR_BUILD_PROBLEM      => 6,
21     ERR_TEST_PROBLEM       => 7,
22     ERR_BUILD_TIMEOUT      => 8,
23 };
24
25 my @err_descriptions;
26 $err_descriptions [ERR_ARCH_MISMATCH]     = "Architecture mismatches";
27 $err_descriptions [ERR_INFRA]             = "Infrastructure errors";
28 $err_descriptions [ERR_BD_PROBLEM]        = "Problems with build-deps";
29 $err_descriptions [ERR_DETECT_WRONG_ARCH] = "Builds detected wrong architecture";
30 $err_descriptions [ERR_CRASH]             = "Crashes detected";
31 $err_descriptions [ERR_BUILD_PROBLEM]     = "Problems detected during build phase";
32 $err_descriptions [ERR_TEST_PROBLEM]      = "Problems detected during test phase";
33 $err_descriptions [ERR_BUILD_TIMEOUT]     = "Package builds timed out";
34
35 # Known failure modes to look for
36 my @logcheck = (
37     {
38         # "rchitecture mismatch" -> should never build on this arch
39         # Stop working on this log at this point
40         string   => 'rchitecture mismatch',
41         message  => 'Architecture mismatch',
42         check    => 1,
43         stop     => 1,
44         type     => ERR_ARCH_MISMATCH,
45     },
46     {
47         string   => 'not in arch list or does not match any',
48         message  => 'Architecture mismatch',
49         check    => 1,
50         stop     => 1,
51         type     => ERR_ARCH_MISMATCH,
52     },
53     {
54         # "binary build with no binary artifacts found" -> no packages
55         # built. Why not picked up already above?.
56         # Stop working on this log at this point
57         string   => 'binary build with no binary artifacts found',
58         message  => 'No binaries built',
59         check    => 1,
60         stop     => 1,
61         type     => ERR_ARCH_MISMATCH,
62     },
63     {
64         string   => 'schroot.*File is not owned by user root',
65         message  => 'Schroot setup failure',
66         check    => 1,
67         stop     => 1,
68         type     => ERR_INFRA,
69     },
70     {
71         string   => 'No space left on device',
72         message  => 'Build ran out of disk space',
73         check    => 1,
74         stop     => 1,
75         type     => ERR_INFRA,
76     },
77     {
78         string   => 'aarch64-unknown-linux-gnu',
79         message  => 'Wrong arch detected',
80         check    => 1,
81         stop     => 1,
82         type     => ERR_DETECT_WRONG_ARCH,
83     },
84     {
85         string   => 'binutils-aarch64',
86         message  => 'Wrong arch detected',
87         check    => 0,
88         stop     => 1,
89         type     => ERR_DETECT_WRONG_ARCH,
90     },
91     {
92         string   => 'lib.linux-aarch64',
93         message  => 'Wrong arch detected',
94         check    => 1,
95         stop     => 1,
96         type     => ERR_DETECT_WRONG_ARCH,
97     },
98     {
99         # "Bus error" -> alignment bug
100         string   => 'Bus error',
101         message  => 'Alignment problem',
102         check    => 1,
103         stop     => 1,
104         type     => ERR_CRASH,
105     },
106     {
107         # "Segmentation fault" -> code problem
108         string   => 'Segmentation fault',
109         pstring  => 'Setting up (\S+)',
110         message  => 'Segmentation fault when installing RESULT',
111         check    => 1,
112         stop     => 1,
113         type     => ERR_CRASH,
114     },
115     {
116         # "Segmentation fault" -> code problem
117         string   => 'Segmentation fault',
118         message  => 'Segmentation fault',
119         check    => 1,
120         stop     => 1,
121         type     => ERR_CRASH,
122     },
123     {
124         # "Illegal instruction" -> bad build target?
125         string   => 'Illegal instruction',
126         pstring  => 'Setting up (\S+)',
127         message  => 'Illegal instruction when installing RESULT',
128         check    => 1,
129         stop     => 1,
130         type     => ERR_CRASH,
131     },
132     {
133         # "Illegal instruction" -> bad build target?
134         string   => 'Illegal instruction',
135         message  => 'Illegal instruction',
136         check    => 1,
137         stop     => 1,
138         type     => ERR_CRASH,
139     },
140     {
141         # Installing build-deps failed
142         string   => 'dpkg: error processing package (\S+)',
143         message  => 'Build-dep failed to install (RESULT)',
144         check    => 1,
145         stop     => 0,
146         type     => ERR_BD_PROBLEM,
147     },
148     {
149         # Installing build-deps failed
150         string   => 'E: pbuilder-satisfydepends failed.',
151         message  => 'Pbuilder build-deps failed',
152         check    => 1,
153         stop     => 1,
154         type     => ERR_BD_PROBLEM,
155     },
156     {
157         # Installing build-deps failed
158         string   => 'E: Unmet dependencies',
159         message  => 'Build-deps failed',
160         check    => 1,
161         stop     => 1,
162         type     => ERR_BD_PROBLEM,
163     },
164     {
165         # Installing build-deps failed
166         string   => 'unsat-dependency: (\S+)',
167         message  => 'Missing build-dep (RESULT)',
168         check    => 1,
169         stop     => 1,
170         type     => ERR_BD_PROBLEM,
171     },
172     {
173         # Build failed - missing build-dep?
174         string   => 'build dependencies/conflicts unsatisfied',
175         message  => 'Build-deps not satisfiable',
176         check    => 1,
177         stop     => 1,
178         type     => ERR_BD_PROBLEM,
179     },
180     {
181         # Build failed - missing build-dep?
182         string   => 'ld: cannot find',
183         message  => 'Build failure: missing library - missing build-dep?',
184         check    => 1,
185         stop     => 1,
186         type     => ERR_BUILD_PROBLEM,
187     },
188     {
189         # Build failed - missing build-dep?
190         string   => 'fatal error:.*No such file or directory',
191         message  => 'Build failure: missing header - missing build-dep?',
192         check    => 1,
193         stop     => 1,
194         type     => ERR_BUILD_PROBLEM,
195     },
196     {
197         # Build failed - missing build-dep?
198         string   => 'SEVERE: Cannot resolve dependencies',
199         message  => 'Build failure - missing build-dep?',
200         check    => 1,
201         stop     => 1,
202         type     => ERR_BUILD_PROBLEM,
203     },
204     {
205         # Build failed - can't exec something...
206         string   => 'error trying to exec.*execvp: No',
207         message  => 'Build failure (missing binary)',
208         check    => 1,
209         stop     => 1,
210         type     => ERR_BUILD_PROBLEM,
211     },
212     {
213         # Build failed
214         string   => 'BUILD FAILED',
215         message  => 'Build failure (java/javadoc)',
216         check    => 1,
217         stop     => 1,
218         type     => ERR_BUILD_PROBLEM,
219     },
220     {
221         # Build failed
222         string   => 'make.*returned exit code',
223         message  => 'Build failure (other)',
224         check    => 1,
225         stop     => 0,
226         type     => ERR_BUILD_PROBLEM,
227     },
228     {
229         # Build failed
230         string   => '^make.*\*\*\*.* \[debian/rules.*Error \d+$',
231         message  => 'Build failure (other)',
232         check    => 1,
233         stop     => 0,
234         type     => ERR_BUILD_PROBLEM,
235     },
236     {
237         # Build failed
238         string   => 'dpkg-source: error: unrepresentable changes to source',
239         message  => 'dpkg-source failure',
240         check    => 1,
241         stop     => 1,
242         type     => ERR_BUILD_PROBLEM,
243     },
244     {
245         # Build failed
246         string   => 'fakeroot debian/rules binary',
247         message  => 'Build failure (other)',
248         check    => 0,
249         stop     => 1,
250         type     => ERR_BUILD_PROBLEM,
251     },
252     {
253         # Test failure
254         string   => 'OSError: \[Errno 13\] Permission denied',
255         message  => 'Python EPERM test failure',
256         check    => 1,
257         stop     => 1,
258         type     => ERR_TEST_PROBLEM,
259     },
260     {
261         # Test failure
262         string   => 'dh_auto_test:.*returned exit code \d+',
263         message  => 'Test failure',
264         check    => 1,
265         stop     => 1,
266         type     => ERR_TEST_PROBLEM,
267     },
268     {
269         # Timeout. pbuilder is too dumb to do this properly :-(
270         string   => 'I: Terminating build process due to timeout',
271         message  => 'Pbuilder build timeout',
272         check    => 1,
273         stop     => 1,
274         type     => ERR_BUILD_TIMEOUT,
275     },
276     {
277         # Timeout from sbuild
278         string   => 'Build killed with signal TERM after \d+ minutes of inactivity',
279         message  => 'Sbuild build timeout',
280         check    => 1,
281         stop     => 1,
282         type     => ERR_BUILD_TIMEOUT,
283     },
284 );
285
286 my %log_results;
287
288 #foreach my $checktmp (@logcheck) {
289 #    my %check = %$checktmp;
290 #    print "looking for \"$check{string}\"\n";
291 #    print "  with log message \"$check{message}\"\n";
292 #    print "  check this regexp: $check{check}\n";
293 #    print "  stop if found: $check{stop}\n";
294 #}
295
296 print "<html>\n";
297 print "<head>\n";
298 print "<title>Build log analysis</title>\n";
299 print "</head>\n";
300 print "<body>\n";
301 print "<h1>Build log analysis</h1>\n";
302 print "<p><a href=\"#summary\">Summary</a></p>\n";
303 print "<h2>Packages</h2>\n";
304 print "<ol>\n";
305
306 foreach my $input (@ARGV) {
307     open (IN, "< $input") or die "Can't read $input: $!\n";
308     $num_fail++;
309     my $stop = 0;
310     my $lineno = 0;
311     my $errors = 0;
312     my $oldline = "";
313     my %file_results;
314     print "<li>Looking at <a href=\"$input\">$input</a>:\n";
315     print "<ul>\n";
316     while (defined (my $line = <IN>) and !$stop) {
317         $lineno++;
318         foreach my $checktmp (@logcheck) {
319             my %check = %$checktmp;
320             if ($check{check}) {
321                 if (!$stop
322                     and ($line =~ m/$check{string}/)
323                     and (!$check{pstring} or $oldline =~ m/$check{pstring}/)) {
324 #                   print "  Line $lineno: found \"$check{string}\"\n";
325                     my $match = $1;
326                     my $message = $check{message};
327                     $message =~ s,RESULT,$match,g;
328                     $file_results{$message} = $check{type};
329                     if ($check{type} == ERR_BUILD_TIMEOUT and $errors == 0) {
330                         print "  <li>Line $lineno: $message\n";
331                         print "  <li>Build killed by timeout before any errors at line $lineno\n";
332                     } else {
333                         print "  <li>Line $lineno: $message\n";
334                         $errors++;
335                     }
336                     if ($check{stop}) {
337 #                       print "  stopping processing\n";
338                         $stop = 1;
339                     }
340                 }
341             }
342         }
343         $oldline = $line;
344     }
345     close IN;
346     # End of checking this package
347     print "  <li><strong>Found errors: $errors</strong>\n";
348     if (!$errors) {
349         print " (maybe just timed out during build?)\n";
350     }
351
352     # Look for a note for manually-added logfile analysis
353     my $note = $input;
354     $note =~ s,\.log$,.note,;
355     if (-f $note) {
356         open (IN, "< $note") or die "Can't open $note for reading: $!\n";
357         while (defined (my $line = <IN>)) {
358             chomp $line;
359             if ($line =~ m,#(\d+),) {
360                 my $bugno = $1;
361                 $existing_bugs++;
362                 $line =~ s,#(\d+),<a href="https://bugs.debian.org/$1">#$1</a>,g;
363             }
364             print "  <li>$line\n";
365         }
366         close IN;
367     }
368
369     print "</ul>\n";
370     foreach my $key (keys %file_results) {
371         $log_results{$file_results{$key}}{$key} += 1;
372 #       print "now have $log_results{$key} for \"$key\"\n";
373     }
374 }
375 print "</ol>\n";
376
377 print "<a name=\"summary\"</a>\n";
378 print "<h2>Summary of results from $num_fail failed builds:</h2>\n";
379 print "<ul>\n";
380 print "<li>  Found $existing_bugs existing bugs in the Debian BTS</li>\n";
381 foreach my $type (sort keys %log_results) {
382     print "  <h3>$err_descriptions[$type]</h3>\n";
383     my $tmp = $log_results{$type};
384     my %result = %$tmp;
385     foreach my $key (sort { $result{$b} <=> $result{$a} }keys %result) {
386         print "  <li>Found $result{$key} log(s) showing $key\n";
387     }
388 }
389 print "</ul>\n";
390 print "</body>\n";
391 print "</html>\n";