chiark / gitweb /
87d33a7b935f5bc9e55598a4c48730354ec62f86
[autopkgtest.git] / runner / adt-testreport-onepackage
1 #!/bin/bash
2
3 set -e
4
5 salt=''
6 tmp=tmp
7 var=var
8 rsync=rsync
9 disable=true
10 interactive=true
11 target=source
12 suppressrepeatedemails=false
13 arch=`dpkg --print-architecture`
14
15 for config in "$@"; do
16         case "$config" in
17         *=*)    eval "$config"  ;;
18         *)      . "$config"     ;;
19         esac
20 done
21
22 if $disable; then
23         echo >&2 'disabled because config inadequate (no disable=false)'
24         exit 1
25 fi
26
27 : ${destdirtail:=$distro-$target}
28 : ${destdirfin:="$destdircommon$destdirtail"}
29
30 case $target in
31 source)
32         sources=Sources
33         descx=''
34         ;;
35 binary-*)
36         sources=Packages
37         descx="${target#binary-}"
38         ;;
39 *)
40         echo >&2 'target must be source or binary-*'
41         exit 1
42 esac
43
44 exec 3>&1
45 printf >&3 "starting "
46
47 rm -rf "$tmp"
48 mkdir "$tmp"
49
50 >"$tmp"/_log_raw
51
52 if $interactive; then
53         echo '(log diverted to stdout)' >>"$tmp"/_log_raw
54 else
55         exec >>"$tmp"/_log_raw
56 fi
57 exec 4>&1
58
59 progress () {
60         echo "++++++ $1 ++++++"
61 }
62
63 gurl () {
64         progress "fetching $1"
65         curl -fsS "$1" >"$2"
66 }
67
68 gurl "$mirror/dists/$distro/$suite/$target/$sources.gz" "$tmp"/_$sources.gz
69 zcat "$tmp"/_$sources.gz >"$tmp"/_$sources-in
70
71 lastinfo="$var"/lastinfo-$target
72 : "${scorelog:="$var"/scores-$target}"
73
74 now=`date +%s`
75 >>"$lastinfo"
76
77 progress selecting
78
79 if test $target = source; then
80         blacklist="$blacklistsourcepackages"
81 else
82         blacklist="$blacklistbinarypackages"
83 fi
84
85 if [ "x$pkg" = x ]; then
86  pkg="`perl -e '
87         use IO::Handle;
88
89         $pre= "[-+.0-9a-z]+";
90         $vre= "[-+.0-9a-zA-Z:~]+";
91
92         sub f1() { $fn=shift @ARGV; open F, $fn or die "$fn $!"; }
93         sub f2() { F->error and die "$fn $!"; close F or die "$fn $!"; }
94
95         $scorelog= "'"$scorelog"'";
96         if (length $scorelog) { open SCORE, "> $scorelog.new" or die $!; }
97         sub pscore ($;$) {
98                 return unless length $scorelog;
99                 printf SCORE "%$_[1]s", $_[0] or die $!;
100         }
101
102         sub readpkglist ($$) {
103                 my ($arrayref, $filename) = @_;
104                 return unless length $filename;
105                 unshift @ARGV, $filename; f1();
106                 while (<F>) {
107                         next if m/^\#/ or !m/\S/;
108                         die unless m/^($pre)\s*$/;
109                         $arrayref->{$1}= 1;
110                 }
111                 f2();
112         }
113         readpkglist(\%suppress, "'"$suppresspackages"'");
114         readpkglist(\%blacklist, "'"$blacklist"'");
115
116         f1();
117         while (<F>) {
118                 die unless m/^($pre) ($vre) (\d+)( .*)?$/;
119                 $lastver{$1}= $2;
120                 $lasttime{$1}= $3;
121                 $extras{$1}= $4." ";
122         }
123         f2();
124         f1();
125         $best_score= -2e9;
126         sub scorepackage () {
127                 return if length $skip;
128                 return if $blacklist{$package};
129                 return if $score < $best_score
130                      or ($score==$best_score and \
131                          $package gt $best_package);
132 #printf STDERR " <----- best score=%s best_score=%s\n", $score, $best_score;
133                 pscore(" (best)");
134                 $best_score= $score;
135                 $best_package= $package;
136         }
137         sub endpackage () {
138                 return unless (defined $package
139                                 or defined $version
140                                 or defined $skip
141                                 or defined $source);
142                 die unless defined $package;
143                 die unless defined $version;
144                 $source= $package if !defined $source;
145
146                 $score= '$now' - $lasttime{$package};
147                 pscore("$package ",-30);
148                 pscore("$source ",-25);
149                 pscore("$score",10);
150
151                 if ($score>1e7) {
152                         $score= 1e7;
153                         $scorechars.='c';
154                 }
155                 pscore(" $lastver{$package}",-25);
156                 pscore(" $version ",-25);
157                 $scorechars= "";
158                 if ($lastver{$package} ne $version) {
159                         $score *= 5;
160                         $scorechars.="U";
161                 }
162                 if ($extras{$package} =~ m/ nt /) {
163                         $scorechars.="n";
164                 } else {
165                         $score *= 10;
166                 }
167                 if ($suppress{$source}) {
168                         $score -= 2e7;
169                         $scorechars.="s";
170                 }
171                 $scorechars.="[$skip]" if length $skip;
172
173                 pscore("-$scorechars",-7);
174                 pscore("$score",10);
175
176 #print STDERR "SCORE package=$package score $score source=$source\n";
177                 scorepackage();
178                 pscore("\n");
179                 undef $package;
180                 undef $version;
181                 undef $skip;
182                 undef $source;
183         }
184         while (<F>) {
185                 if (m/^Package: ($pre)$/) {
186                         die if defined $package;
187                         $package= $1;
188                 } elsif (m/^Version: ($vre)$/) {
189                         die if defined $version;
190                         $version= $1;
191                 } elsif (m/^Source: ($pre)$/) {
192                         die if defined $source;
193                         $source= $1;
194                 } elsif (m/^Architecture:.*/ &&
195                          !m/\s(?:'$arch'|all|any)\s/) {
196 #printf STDERR " <----- skip %s %s\n", $&, "'$arch'";
197                         $skip .= 'a';
198                 } elsif (m/^$/) {
199                         endpackage();
200                 }
201         }
202         f2();
203         endpackage();
204         if (length $scorelog) {
205                 close SCORE or die $!;
206                 rename "$scorelog.new","$scorelog" or die $!;
207         }
208         die unless length $best_package;
209         open L, ">&4" or die $!;
210         printf L "selected %s (age %s, score %d)\n",
211                 $best_package,
212                 exists($lastime{$best_package})
213                 ? '$now' - $lasttime{$best_package}
214                 : "<never-yet>",
215                 $best_score;
216         print "$best_package\n" or die $!;
217  ' "$lastinfo" "$tmp"/_$sources-in`"
218 else
219         printf >&4 "package forced: %s\n" "$pkg"
220 fi
221
222 sed -n "/^Package: $pkg\$/,/^\$/p" \
223  <"$tmp"/_$sources-in >"$tmp"/_this-stanza
224
225 echo
226 cat "$tmp"/_this-stanza
227
228 getfield () {
229         eval 'p'$1'="`
230                 sed -n '\''s/^'$1': //p'\'' \
231                  <"$tmp"/_this-stanza
232         `"'
233 }
234
235 printf >&3 "selected \"%s\" " $pkg
236
237 tp="$tmp/$pkg"
238 mkdir "$tp" "$tp/src" "$tp/tmp" "$tp/out"
239
240 getfield Version
241
242 getfield Source
243 if [ "x$pSource" != x ]; then
244         src="$pSource"
245 else
246         src="$pkg"
247 fi
248
249 if test $target = source; then
250         getfield Directory
251         leafnames="`
252                 sed -n '/^Files:/,/^([^ ].*)?$/{ /^ /{
253                         s/^ [0-9a-z][0-9a-z]*  *[0-9][0-9]* //; p
254                         }}' \
255                  <"$tmp"/_this-stanza
256         `"
257         for leafname in $leafnames; do
258                 df="$tp/src/$leafname"
259                 case "$leafname" in
260                 */*|.*) echo >&2 "bad leafname: $leafname"; exit 1;;
261                 *.dsc) fot="$df";;
262                 esac
263                 gurl "$mirror/$pDirectory/$leafname" "$df"
264         done
265         testmode=--source
266         testmode2=''
267         desc="$pkg"
268         : ${upload_if_ok:=true}
269         email_package_header="$email_sourcepackage_header"
270 else
271         getfield Filename
272         fot="$tp/src/$pkg.deb"
273         gurl "$mirror/$pFilename" "$fot"
274         testmode='--binaries=install --binary'
275         testmode2=--instantiate
276         desc="$pkg $descx"
277         : ${upload_if_ok:=false}
278         email_package_header="$email_binarypackage_header"
279 fi
280
281 if [ "x$maintainer_email_override" = x ]; then
282         getfield Maintainer
283         maintainer_email=pMaintainer
284 else
285         maintainer_email=maintainer_email_override
286 fi
287
288 printf >&3 "adt-run "
289
290 progress "starting test"
291
292 xrc () {
293         printf "+ %s\n" "$*"
294         set +e
295         "$@"
296         rc=$?
297         set -e
298 }
299
300 echo 'fatal: adt-run did not start properly' >"$tmp"/_summary
301
302 xrc adt-run --tmp-dir "$tp"/tmp                         \
303         --output-dir "$tp"/out                          \
304         --log-file "$tp"/log                            \
305         --summary "$tmp"/_summary                       \
306         $adtrun_extra_opts                              \
307         $testmode "$fot" $testmode2                     \
308  ---                                                    \
309  adt-virt-xenlvm                                        \
310         $adtvirt_extra_opts                             \
311         --distro="$distro"                              \
312  --                                                     \
313  2>&1 3>&- 4>&-
314
315 printf >&3 "%s " $rc
316
317 ourx=0
318 upload=true
319 : ${upload_if_notests:=false}
320 extras=''
321
322 case "$rc" in
323 0)      summary='all OK';                       email=''
324                                         upload=$upload_if_ok            ;;
325 2)      summary='OK (some skipped)';            email=''
326                                         upload=$upload_if_ok            ;;
327 8)      summary='package declares no tests';    email=''
328                                 upload=$upload_if_notests; extras='nt'  ;;
329 4|6)    summary='test(s) failed!';      email="$maintainer_email"       ;;
330 12)     summary='erroneous package!';   email="$maintainer_email"       ;;
331 16)     summary='testbed failed!';      email="administrator_email"     ;;
332 *)      summary='unexpected failure!';  email="administrator_email"; ourx=20;;
333 esac
334
335 progress "RESULTS $summary"
336
337 if  [ "x$suppresspackages" != x ] \
338  && grep -x "$src" "$suppresspackages" >/dev/null; then
339         printf >&3 "email-suppressed "
340         email=''
341 fi
342
343 if $upload; then
344         progress "bundling"
345         printf "\n%s\n" "$summary" >>"$tmp"/_summary
346
347         edest=${email%_email}
348         esummary="$var"/emailed/last-$pkg,$edest
349         if [ "x$edest" = x ]; then
350                 printf >&3 "email-none "
351                 rm -f "$var"/emailed/last-$pkg,*
352                 esummary=''
353         elif $suppressrepeatedemails \
354           && [ -f "$esummary" ] \
355           && diff -u "$esummary" "$tmp"/_summary >"$var"/emailed/diff-$pkg; then
356                 printf >&3 "email-same $email "
357                 email=''
358                 esummary=''
359         else
360                 cp "$tmp"/_summary "$esummary".new
361         fi
362
363         ln -f "$tmp"/_summary "$tp"/summary
364
365         for odir in tmp out; do
366                 if test -d "$tp"/$odir; then
367                         GZIP=-2 tar -f "$tp"/$odir.tar.gz -C "$tp" -zc $odir
368                         rm -r "$tp"/$odir
369                 fi
370         done
371
372         progress "uploading"
373         printf >&3 "uploading"
374         $rsync -rltH --safe-links --delete "$tp" "$destrsynchead/$destdirfin/"
375         printf >&3 " "
376 fi
377
378 if [ "x$email" != x ]; then
379         progress "contacting $email"
380         eval "email_addr=\$$email"
381         printf >&3 "email \"%s\" " "$email_addr"
382         cat >"$tmp"/_email_header <<END
383 From: $from
384 To: $email_addr
385 Subject: autopkgtest $distro $desc: $summary
386
387 END
388
389         email_package_header="${email_package_header//@p/$pkg}"
390         email_package_header="${email_package_header//@s/$src}"
391         email_package_header="${email_package_header//@v/$pVersion}"
392         email_package_header="${email_package_header//@a/@}"
393         printf >"$tmp"/_email "%s" "$email_package_header"
394
395         cat >>"$tmp"/_email <<END
396  Test executed for:  $distro  $target  $pkg
397  Outcome: $summary
398 END
399         sed -e 's/^/  /' "$tmp"/_summary >>"$tmp"/_email
400         cat >>"$tmp"/_email <<END
401
402 This message is automatically generated by the autopkgtest package
403 testing system.  You are receiving it because:
404 END
405         case "$email" in
406                 pMaintainer)
407                         cat >>"$tmp"/_email <<END
408  You are listed in the Maintainer field of the $pkg package in $distro
409  and the test results appear to indicate a problem with the package.
410 END
411                         ;;
412                 maintainer_email_override)
413                         cat >>"$tmp"/_email <<END
414  The test results appear to indicate a problem with the package
415  and reports for package maintainers for $distro are being directed to
416  $maintainer_email_override
417 END
418                         ;;
419                 administrator_email)
420                         cat >>"$tmp"/_email <<END
421  You are the administrator for the autopkgtest installation.
422 END
423                         ;;
424                 *)
425                         echo >&2 "huh email $email is what why?"
426                         exit 1
427                         ;;
428         esac
429         cat >>"$tmp/_email" <<END
430
431 The test log, which is intended to be sufficient to diagnose most
432 failures, can be found below.  However, in case this is not
433 sufficient, another copy can be found along with output files, saved
434 temporary files, and so on, at:
435  $desthttphead/$destdirfin/
436 $email_extra_info
437 If you have any questions about this service please contact me at:
438  $from
439
440 Regards,
441 $salutation
442
443 -8<-
444 END
445 fi
446
447 printf >>"$var"/log "%s=%s rc=%s emailed='%s'\n" \
448         "$target" "$pkg" $rc "$email_addr"
449
450 if [ "x$ourx" = x0 ]; then
451         sed -e "/^$pkg /d" <"$lastinfo" >"$lastinfo".new
452         printf "%s %s %s %s\n" "$pkg" "$pVersion" "$now" "$extras" \
453                 >>"$lastinfo".new
454         mv "$lastinfo".new "$lastinfo"
455         progress "tested."
456 else
457         progress "fault ($ourx)."
458 fi
459
460 perl <"$tmp"/_log_raw >"$tmp"/_log -pe '
461         s/[^\012\040-\133\135-\176]/
462                 $& eq "\t" ? "\\t" :
463                 $& eq "\r" ? "\\r" :
464                 $& eq "\b" ? "\\b" :
465                 $& eq "\\" ? "\\\\" :
466                 sprintf "\\x%02x", ord $&
467         /ge'
468
469 if [ "x$email" = x ]; then
470         if $interactive; then
471                 cat "$tmp"/_log >&2
472         fi
473 else
474         cat >>"$tmp"/_email 2>&1 "$tmp"/_log ||:
475
476         if [ "x$email_signing_key" != x ]; then
477                 printf >&3 "signing "
478                 echo >>"$tmp/_email"
479                 gpg -u"$email_signing_key" --clearsign \
480                         <"$tmp/_email" >"$tmp/_email.asc"
481                 mv -f "$tmp/_email.asc" "$tmp/_email"
482         fi
483         cat "$tmp/_email_header" "$tmp/_email" >"$tmp/_email.new"
484         mv -f "$tmp/_email.new" "$tmp/_email"
485
486         if $interactive; then
487                 cat "$tmp"/_email >&2
488         else
489                 sendmail -odi -oem -t -oi <"$tmp"/_email
490                 if [ "x$esummary" != x ]; then
491                         printf >&3 "email-recorded "
492                         mv "$esummary".new "esummary"
493                 fi
494         fi
495 fi
496
497 printf >&3 "done %s.\n" $ourx
498 exit $ourx