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