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