/usr/bin/sbuildlogs-summarise is in xbuilder 1.0.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 195 | #!/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 $rebuilddlogregex = 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)
my $sbuildlogregex = qr/^ # start
([\S]+) # package ($1)
.log # package_ver separator
$ # 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/$sbuildlogregex/) {
$package=$1;
}
$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/$sbuildlogregex/) {
$package=$1;
}
($buildstate,$message,$buildtime,$version,$arch,$date) = 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) = ("","","","","","","","","");
my ($arch,$version,$date) = ("","","");
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 =~ /^Version: ([\S]+)$/ ) { $version=$1 };
if ( $line =~ /^Host Architecture: ([\S]+)$/ ) { $arch=$1 };
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, $version, $arch, $enddate)
}
|