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