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