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