Browse Source

support autopkgtest

Implemented as follows:

* build-and-provide-package uses the new pbuilder-hookdir directory
  by default. The pbuilder-hookdir script B20autopkgtest runs the
  actual tests using autopkgtest iff debian/tests/control is
  present in the Debian package, otherwise skipping the test
  execution so behaviour of build-and-provide-package is the
  same as before.

  The hook directory defaults to /usr/share/jenkins-debian-glue/pbuilder-hookdir/
  and can be configured by the $PBUILDER_HOOKDIR setting.

  To skip any autopkgtest output handling the $SKIP_AUTOPKGTEST_RESULTS
  configuration can be set.

* build-and-provide-package: copies autopkgtest output into
  directory 'adt' for later processing via adtsummary_tap

* adtsummary_tap: this script generates a TAP report of
  the autopkgtest output, usage inside a Jenkins job as shell
  executer step like:

  mkdir -p report adt
  touch adt/summary # do not fail if no autopkgtest run took place
  adtsummary_tap adt/summary > report/autopkgtest.tap

  and using 'report/*.tap' for Post-build action "Publish TAP Results".

It's recommended to use a recent version of autopkgtest. The
one provided by Christoph Berg <myon@debian.org> at
http://apt.postgresql.org/pub/repos/apt/pool/main/a/autopkgtest/
(autopkgtest_2.2.3.pgdg+1 at the time of this commit)
is known to work fine and also includes a bugfix for:

| TypeError: coercing to Unicode: need string or buffer, instance found

which is reported as http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=696625
Please note that autopkgtest isn't required on the system providing
cowbuilder but instead *inside* the cowbuilder environment.

Thanks to Christoph Berg <myon@debian.org> for his initial work on
autopkgtest support in jenkins-debian-glue and his permission to
integrate it in the mainline project.
tags/v0.5.0
Michael Prokop 8 years ago
parent
commit
95a35fe16f
7 changed files with 112 additions and 4 deletions
  1. +2
    -0
      Makefile
  2. +1
    -0
      debian/jenkins-debian-glue-buildenv-taptools.install
  3. +1
    -0
      debian/jenkins-debian-glue.install
  4. +4
    -0
      examples/debian_glue
  5. +40
    -0
      pbuilder-hookdir/B20autopkgtest
  6. +26
    -4
      scripts/build-and-provide-package
  7. +38
    -0
      tap/adtsummary_tap

+ 2
- 0
Makefile View File

@@ -13,6 +13,8 @@ install: $(scripts)

mkdir -p $(DESTDIR)/usr/share/jenkins-debian-glue/examples/
install -m 0664 examples/* $(DESTDIR)/usr/share/jenkins-debian-glue/examples/
mkdir -p $(DESTDIR)/usr/share/jenkins-debian-glue/pbuilder-hookdir/
install -m 0775 pbuilder-hookdir/* $(DESTDIR)/usr/share/jenkins-debian-glue/pbuilder-hookdir/

uninstall: $(scripts)
for prog in $(PROGRAMS); do \


+ 1
- 0
debian/jenkins-debian-glue-buildenv-taptools.install View File

@@ -1,3 +1,4 @@
debian/tmp/usr/bin/adtsummary_tap usr/bin/
debian/tmp/usr/bin/checkbashism_tap usr/bin/
debian/tmp/usr/bin/perlcritic_tap usr/bin/
debian/tmp/usr/bin/tap_tool_dispatcher usr/bin/

+ 1
- 0
debian/jenkins-debian-glue.install View File

@@ -5,3 +5,4 @@ debian/tmp/usr/bin/generate-svn-snapshot usr/bin/
debian/tmp/usr/bin/increase-version-number usr/bin/
debian/tmp/usr/bin/repository_checker usr/bin/
debian/tmp/usr/share/jenkins-debian-glue/examples usr/share/jenkins-debian-glue/
debian/tmp/usr/share/jenkins-debian-glue/pbuilder-hookdir/ usr/share/jenkins-debian-glue/

+ 4
- 0
examples/debian_glue View File

@@ -17,3 +17,7 @@
# packages will be build then.
# If unset it will default to the architecture of the host system.
# MAIN_ARCHITECTURE="amd64"

# Hook scripts for pbuilder/cowbuilder, used e.g. for autopkgtest.
# Default:
# PBUILDER_HOOKDIR=/usr/share/jenkins-debian-glue/pbuilder-hookdir/

+ 40
- 0
pbuilder-hookdir/B20autopkgtest View File

@@ -0,0 +1,40 @@
#!/bin/sh
# Copyright 2013 Michael Prokop <mika@debian.org>
# Copyright 2012 Christoph Berg <myon@debian.org>
# Licensed under the terms of the MIT License.

set -ex

cd /tmp/buildd/*/debian/..

if [ ! -f debian/tests/control ]; then
echo "Package does not have autopkgtest support, debian/tests/control is missing"
exit 0
fi

if [ ! -f debian/files ]; then
echo "Package source is not built, debian/files is missing" >&2
exit 1
fi

set -- /tmp/adt-*/
TMPADT="$1"
if [ ! -d "$TMPADT" ]; then
echo "Didn't find any /tmp/adt-*/ directory. It should have been created before invoking cowbuilder." >&2
ls -la /tmp
exit 1
fi

# runner/adt-run uses apt-utils's apt-ftparchive and
# pbuilder's pbuilder-satisfydepends-classic
apt-get install -y autopkgtest apt-utils pbuilder

mkdir -p "$TMPADT/out"
binaries=$(awk '/\.deb / { print "--binary ../" $1 }' debian/files)

adt-run --tmp-dir $TMPADT/out --summary $TMPADT/summary \
$binaries --built-tree $PWD --- adt-virt-null || EXIT=$?

# 4 means some test failed, exit 0 here and let adtsummary2junit report the failure
[ ${EXIT:-0} = 4 ] && exit 0
exit ${EXIT:-0}

+ 26
- 4
scripts/build-and-provide-package View File

@@ -33,6 +33,10 @@ checks_and_defaults() {
if [ -z "${REPOSITORY:-}" ] ; then
REPOSITORY='/srv/repository'
fi

if [ -z "${PBUILDER_HOOKDIR:-}" ] ; then
PBUILDER_HOOKDIR='/usr/share/jenkins-debian-glue/pbuilder-hookdir/'
fi
}

clean_workspace() {
@@ -50,6 +54,7 @@ bailout() {

echo "*** Getting rid of files in $WORKSPACE/binaries/ to avoid problems in next run. ***"
rm -f "$WORKSPACE"/binaries/*
${SUDO_CMD:-} rm -rf /tmp/adt-$$

[ -n "$start_seconds" ] && SECONDS="$[$(cut -d . -f 1 /proc/uptime)-$start_seconds]" || SECONDS="unknown"
echo "*** Finished execution of $0 at $(date) [running ${SECONDS} seconds] ***"
@@ -191,7 +196,8 @@ cowbuilder_init() {
echo "*** Creating cowbuilder base $COWBUILDER_BASE for arch $arch and distribution $COWBUILDER_DIST ***"
sudo cowbuilder --create --basepath "${COWBUILDER_BASE}" --distribution "${COWBUILDER_DIST}" \
--debootstrapopts --arch --debootstrapopts "$arch" \
--debootstrapopts --variant=buildd ${pbuildercfg:-}
--debootstrapopts --variant=buildd ${pbuildercfg:-} \
--hookdir "${PBUILDER_HOOKDIR}"
[ $? -eq 0 ] || bailout 1 "Error: Failed to create cowbuilder base ${COWBUILDER_BASE}."
else
echo "*** Updating cowbuilder cow base ***"
@@ -265,14 +271,27 @@ identify_build_type() {
rm -rf "${TMPDIR}"
}

autopkgtest_results() {
if [ -n "${SKIP_AUTOPKGTEST_RESULTS:-}" ] ; then
echo "** Skipping autopkgtest_results as requested via SKIP_AUTOPKGTEST_RESULTS ***"
return 0
fi

# copy autopkgtest results from /tmp
rm -rf adt
${SUDO_CMD:-} chmod -R go+rX /tmp/adt-$$
cp -a /tmp/adt-$$ adt
}

cowbuilder_run() {
echo "*** cowbuilder build phase for arch $architecture ***"
mkdir -p "$WORKSPACE"/binaries/
mkdir -p "$WORKSPACE"/binaries/ /tmp/adt-$$

# make sure we build arch specific packages only when necessary
identify_build_type

if $SKIP_ARCH_BUILD ; then
autopkgtest_results
bailout 0 "Nothing to do, architecture all binary packages only for non-primary architecture."
fi

@@ -280,13 +299,15 @@ cowbuilder_run() {
i386)
linux32 sudo cowbuilder --buildresult "$WORKSPACE"/binaries/ \
--build $sourcefile \
--basepath "${COWBUILDER_BASE}" --debbuildopts "${DEBBUILDOPTS:-}"
--basepath "${COWBUILDER_BASE}" --debbuildopts "${DEBBUILDOPTS:-}" \
--hookdir "${PBUILDER_HOOKDIR}" --bindmounts /tmp/adt-$$
[ $? -eq 0 ] || bailout 1 "Error: Failed to build with cowbuilder."
;;
amd64|all|*)
sudo cowbuilder --buildresult "$WORKSPACE"/binaries/ \
--build $sourcefile \
--basepath "${COWBUILDER_BASE}" --debbuildopts "${DEBBUILDOPTS:-}"
--basepath "${COWBUILDER_BASE}" --debbuildopts "${DEBBUILDOPTS:-}" \
--hookdir "${PBUILDER_HOOKDIR}" --bindmounts /tmp/adt-$$
[ $? -eq 0 ] || bailout 1 "Error: Failed to build with cowbuilder."
;;
*)
@@ -485,6 +506,7 @@ else
fi

binaries_to_workspace
autopkgtest_results

bailout 0



+ 38
- 0
tap/adtsummary_tap View File

@@ -0,0 +1,38 @@
#!/usr/bin/env ruby

if ARGV[0].nil?
$stderr.puts "Usage: #{File.basename $0} <autopkgtest_summary_file>"
exit 1
end

file = ARGV[0]
counter = 1
found_error = 0

begin
output = File.open("#{file}", "r").read
rescue
$stderr.puts "Error: can't read file #{file}"
exit 1
end

num_lines = output.lines.count

if num_lines == 0
puts "1..0 # Skipped: no autopkgtest output found"
exit 0
end

puts "1..#{num_lines}"
output.gsub(/:\n/, ':').each_line do |critic|
if critic =~ /.*PASS.*/
cmd = /(.*)? (PASS)$/.match(critic)[1]
puts "ok #{counter} #{cmd}"
counter += 1
elsif critic =~ /.*FAIL status.*/
test = /(.*)? (FAIL status:)(.*)?/.match(critic)[1]
cmd = /(.*)? (FAIL status:)(.*)?/.match(critic)[3]
puts "not ok #{counter} #{test} #{cmd}"
counter += 1
end
end

Loading…
Cancel
Save