File: buildlogs-summarise

package info (click to toggle)
xbuilder 1.0.1
  • links: PTS
  • area: main
  • in suites: buster, stretch
  • size: 220 kB
  • ctags: 21
  • sloc: sh: 331; perl: 300; makefile: 7; awk: 3
file content (194 lines) | stat: -rwxr-xr-x 9,881 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#!/usr/bin/perl

# noddy script to generate html summary page of logs

use strict;
use warnings;
use diagnostics;
use POSIX qw(strftime);
use Getopt::Long;

use vars qw($package $version $arch $date $datestring $buildstate $message $summarystate 
       $today $todayreadable $now %loglist $logname @packages $buildok $unneeded $builddeps $sourcefail $buildfail $packagecount 
       %pkgfilter $pkgfilter $pkg $pkgstatus $logregex $buildtime);

# allow specifying a (reprepro) package filter 
GetOptions( "pkgfilter=s" => \$pkgfilter); # --pkgfilter=filename

if ($pkgfilter && -r $pkgfilter) {
    open (FILTER,"<", "$pkgfilter") or die "Can't open $pkgfilter: $!";
    while (<FILTER>) {
	chomp;
	($pkg, $pkgstatus)=split;
	$pkgfilter{$pkg}=1;
    }
    close FILTER;
}


#my ($day, $month, $year) = (localtime)[3,4,5];
#my $today = sprintf("%04d%02d%02d", $year+1900, $month+1, $day);
my $today = strftime( "%Y%m%d", localtime);
my $todayreadable = readabledate($today);

# regex to cope with rebuildd's annoying log-file naming scheme with 
# dash separators and dashes in version strings and distronames.
# dashes in version are always followed by a digit
# reponames always start with a letter 
my $logregex = qr/^  # start 
      ([\S]+)       # package ($1)
      _                  # package_ver separator
      (                  # version number ($2)
	  (
	   [:\w\d\.\+~]  # chars in version strings
	   |             # or 
	   -(?=\d)       # a dash with a digit after it ($3, annoyingly)
	  )+             # at least one character
      )     
      -                  # dash separator
      ([-\w]+)           # repo name (including dashes) $4
      -                  # dash separator
      (\w+)              # architecture $5
      -                  # dash separator
      (\d{8})            # date (20120522) $6
      -                  # dash separator
      (\d\d)(\d\d).*     # hours and minutes $7 $8
      $                  # end 
      /x ;              # (allowing multiline comments)


print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\"http://www.w3.org/TR/html4/loose.dtd\"";
print "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"><title>Multiarch Cross-buildd logs</title></head><body>\n";
print "<h2>Build logs by packagename</h2><p>Generated $todayreadable</p>\n";
if ($pkgfilter) {print "<p>Package list filtered by $pkgfilter.</p>";}
print "<p><a href=\"#summary\">Summary count</a></p>\n";
print "<div id=\"table\"><table border=\"1\">";
print "<tr><th>Package</th><th>Version</th><th>Architecture</th><th>Date</th><th>Summary</th><th>Message</th></tr>\n";



# parse all the logfiles, noting one per package
my @files =<*.log>;
foreach $logname (@files) {
    $package=$version=$arch=$date=$datestring="";
    if ($logname =~ m/$logregex/) {
        $package=$1;
        $version=$2;
        $arch=$5;
        $date="$6";
        $datestring="$6&nbsp;$7:$8";
    }

    $loglist{$package} = $logname unless ($pkgfilter && ! exists $pkgfilter{$package});
}

my $packagecount=$buildok=$unneeded=$builddeps=$sourcefail=0;
# parse noted logs and print into page
@packages = sort (keys %loglist);

foreach $package (@packages) {
    $logname = $loglist{$package};
    $packagecount++;
    $package=$version=$arch=$date=$datestring="";
    if ($logname =~ m/$logregex/) {
        $package=$1;
        $version=$2;
        $arch=$5;
        $date="$6";
        $datestring="$6&nbsp;$7:$8";
    }
    
    ($buildstate,$message,$buildtime) = parselog($logname);

    $summarystate=$buildstate;
    if ($summarystate eq "BUILD OK") {$buildok++} 
    if ($summarystate eq "NOT ATTEMPTED") {$unneeded++} 
    if ($summarystate eq "BUILD DEPS FAILED") {$builddeps++} 
    if ($summarystate eq "SOURCE FAILED") {$sourcefail++} 
    print "<tr><td><a href=\"$logname\">$package</a></td><td>$version</td><td>$arch</td><td>".readabledate($date)."</td><td ".cellcolour($summarystate).">$summarystate</td><td>$message</td></tr>\n"; 
}

$buildfail=$packagecount-($buildok+$unneeded+$builddeps+$sourcefail);
print "</table></div>\n<a name=\"summary\"><p>Of $packagecount source packages: Build OK: $buildok, Build Failed: $buildfail, Deps failed: $builddeps, Not needed(Arch:all): $unneeded, No Source: $sourcefail</p>";
print "<p><ul><li>Build OK: The source package cross-built</li><li>Build Failed: A cross-build was attempted but did not succeed</li><li>Deps Failed: The cross-build dependencies could not be installed, so no build attempted</li><li>Source Failed: the correct version of source was not available (usually a transient issue)</li></ul></p>\n</body></html>";


sub cellcolour {
    my $state=$_[0];
    my $col="#FFFFFF";
    if ($state eq "BUILD DEPS FAILED") {$col="#FF6600";} # orange
    if ($state eq "BUILD OK") {$col="#00FF33";} # green
    if ($state eq "NOT ATTEMPTED") {$col="#CCFF33";} # light green
    if ($state eq "BUILD FAILED") {$col="#CC0000";} # red
    if ($state eq "SOURCE FAILED") {$col="#FFFF66";} # yellow
    return ("bgcolor=\"$col\"");
}

sub readabledate {
    my $date=$_[0];
    if ( length($date)==8 ) { return substr($date, 0,4)."-".substr($date, 4,2)."-".substr($date, 6,2); };
    }

# parse a build log for build-stage info and errors
# takes a filehandle
sub parselog {
    my ($enddate,$endtime,$block,$diskspace,$buildtime,$buildstate,$misseddeps,$message,$buildprofile) = ("","","","","","","","","");
    open (LOG,"<", "$logname") or die "Can't open $logname: $!";
    while (<LOG>) {
        my $line= $_; 
        # print("parsing line:".$_);
	if ( $line =~ /^│ (Changes|Package contents|Update chroot|Fetch source files|Install core build dependencies|Install cross build-dependencies|Build environment|Build|Summary|Cleanup) .*$/) 
            { $block = $1 };

        SWITCH: {

            $block eq "Fetch source files" && do {
                if ( $line =~ /^Can't find source for (.*)$/ ) { $buildstate="SOURCE FAILED"; $message="$line"  };
                last SWITCH;
            };
            (($block eq "Install cross build-dependencies") || ( $block eq "Install core build dependencies" )) && do {
                # if ( $line =~ /^$/ ) {  };
                if ( $line =~ /APT::Build-Profile=(\w+)/ ) { $buildprofile="Build Profile: $1. " };
                if ( $line =~ /^ (.*) but it is not (installable|going to be installed)$/ ) { $buildstate="BUILD DEPS FAILED"; $message="$line" };
                if ( $line =~ /dpkg: error processing ([\w\.-]+) (--configure):/ ) { $buildstate="BUILD DEPS FAILED"; $message="Build-deps failed to install. Possibly: $1" };
                # should only use this if above one failed to get a message - how to do?
                if ( $line =~ /^E: Failed to process build dependencies$/  && $message eq "" ) { $buildstate="BUILD DEPS FAILED"; $message="Build-deps failed to install" };
                # if ( $line =~ /^ (.*) but it is not going to be installed$/ ) { $buildstate="BUILD DEPS FAILED"; $message="$line" };
                if ( $line =~ /^E: Build-Depends dependency for ([\w\.-]+) cannot be satisfied because the package ([\w\.-]+) cannot be found$/ ) 
                    { $buildstate="BUILD DEPS FAILED"; $message="package $2 cannot be found" };
                last SWITCH;
            };
            $block eq "Build" && do {
                if ( $line =~ /^dpkg-checkbuilddeps: Unmet build dependencies: (.*)$/ ) { $buildstate="BUILD DEPS FAILED"; $message="dpkg-checkbuildeps missing: $1" };
                if ( $line =~ /^strip: Unable to recognise the format of the input file/ ) { $buildstate="BUILD FAILED";  $message="Wrong-architecture strip for binary" };
                if ( $line =~ /binary-is-wrong-architecture/ ) { $buildstate="BUILD FAILED"; $message="Wrong-architecture binaries found" };
                if (( $line =~ /^E: Build failure \(dpkg-buildpackage died\)$/ ) && $message eq "") { $buildstate="BUILD FAILED"; $message="dpkg-buildpackage failed" };
                if ( $line =~ /^I: Built successfully/ ) { $buildstate="BUILD OK" };
                last SWITCH;
            };
            $block eq "Cleanup" && do {
	        if ( $line =~ /^E: .*: ([\w-]+) not in arch list or does not match any arch wildcards: (.*) -- skipping$/ ) { $buildstate="NOT ATTEMPTED"; $message="$1 not in arch list for this package"  };
                last SWITCH;
            };
            $block eq "Summary" && do {
 	        # if ( $line =~ /^Build started at ([\d-]+) ([\d:]+).\d*$/ ) { ($startday,$starttime) = ($1,$2) };
	        if ( $line =~ /^Build needed ([\d:]+), (\d+)k disc space$/ ) { ($buildtime, $diskspace) = ($1,$2) };
	        if ( $line =~ /^Finished at (\d{8})-(\d{4})$/ ) { ($enddate, $endtime) = ($1,$2) };
                last SWITCH;
            };
            # Not in sbuild block so probably a manual build log
            $block eq "" && do {
                if ( $line =~ /^dpkg-buildpackage: binary only upload/ ) {  $buildstate="BUILD OK"; $message="Manual build"  };  # for manual builds done outside sbuild
                if ( $line =~ /^I: Built successfully/ ) { $buildstate="BUILD OK"; $message="Manual build" };   # for manual builds done outside sbuild
                if ( $line =~ /^Build Profile: (\w+)$/ ) { $buildprofile="Build Profile: $1. " };
                if ( $line =~ /DEB_BUILD_PROFILE=(\w+)/ ) { $buildprofile="Build Profile: $1. " };
                last SWITCH;
            };
        }
       if ( $line =~ /^E: ABORT: Received INT signal \(requesting cleanup and shutdown\)$/ ) { $buildstate="ABORTED";  $message="build interrupted" };
    }
    close (LOG);
    if ( $buildstate eq "" ) { $buildstate="BUILD FAILED"; $message="State not determined - probably failed or aborted" };
    if ( $buildprofile ) { $message=$buildprofile . $message }; 
    return ($buildstate, $message, $buildtime)
}