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 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
# Deb-o-Matic - AutoPkgTest module
#
# Copyright (C) 2014 Leo Iannacone
#
# Authors: Leo Iannacone <l3on@ubuntu.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Run autpkgtest and stores output on top of the built
# package in the pool directory.
#
# Can be configured by adding this section to the config file:
#
# [autopkgtest]
# options: [adt-run options]
# logging: [True|False] # enable builder log into the logs directory
# gpghome: /path/to/gnupg-home # set the gnupg home for adt-run
#
import os
from subprocess import call
from time import strftime
from shutil import rmtree
from tempfile import NamedTemporaryFile
class DebomaticModule_AutoPkgTest:
def __init__(self):
self.after = ['Piuparts']
self.options = []
self.logging = False
self.dsc = None
self.gpghome = '/var/cache/debomatic/autopkgtest'
def _set_up_commons(self, args):
"""Set up common variables for pre and post build hooks"""
# the package result dir
self.resultdir = os.path.join(args['directory'],
'pool',
args['package'])
# output is the final output file log
self.output = os.path.join(self.resultdir,
args['package']) + '.autopkgtest'
def _set_up_testbed(self, args):
"""Performs:
- check if dsc exists and declares a Testsuite
- get autopkgtest options from the config
- set up needed variables and files
Returns True if test can be executed, False otherwise"""
# check if dsc exists and it contains the Testsuite field
autopkgtest_found = False
for filename in os.listdir(self.resultdir):
if filename.endswith('.dsc'):
self.dsc = os.path.join(self.resultdir, filename)
with open(self.dsc, 'r') as fd:
for line in fd:
if line.find('Testsuite: autopkgtest') >= 0:
autopkgtest_found = True
break
break
if not self.dsc or not autopkgtest_found:
return False
# get autopkgtest options
if args['opts'].has_section('autopkgtest'):
def get_option(o):
if args['opts'].has_option('autopkgtest', o):
return args['opts'].get('autopkgtest', o).strip()
return ''
self.options = get_option('options').split()
self.logging = get_option('logging').lower() == 'true'
# gpghome is where adt has its own gpg and it is also used
# as tmp directory to put the scripts
gpghome = get_option('gpghome')
if gpghome:
self.gpghome = gpghome
# set up atd-run output dir
self.resultdir_adt = os.path.join(self.resultdir, 'adt_out_dir')
# summary is where test summary is stored, relative to resultdir_adt
self.summary = 'log_summary'
# script is the main script launched through the builder, a tmp file
tmpfd = NamedTemporaryFile(dir=self.gpghome, delete=False)
tmpfd.close()
self.script = tmpfd.name
self._make_script()
return True
def _make_script(self):
"""Makes a bash script to being easily called through the builder.
The script installs autopkgtest and then run adt-run."""
adt = ['adt-run']
adt += ('--gnupg-home', self.gpghome)
adt += ('--summary', os.path.join(self.resultdir_adt, self.summary))
adt += ('--output-dir', self.resultdir_adt)
adt += self.options
# add debs
adt += (os.path.join(self.resultdir, f)
for f in os.listdir(self.resultdir)
if f.endswith('.deb'))
adt += (self.dsc, '---', 'null')
self.adt = ' '.join(adt)
content = ["#!/bin/bash"]
content.append('apt-get install -y autopkgtest')
content.append(self.adt)
if not os.path.isdir(self.gpghome):
os.makedirs(self.gpghome)
with open(self.script, 'w') as fd:
fd.write('\n'.join(content))
def _finish(self):
"""Clean up the system"""
if os.path.isfile(self.script):
os.remove(self.script)
if (os.path.isdir(self.resultdir_adt)):
rmtree(self.resultdir_adt)
def post_build(self, args):
if not args['success']:
return
self._set_up_commons(args)
if not self._set_up_testbed(args):
return
# the output file descriptor
output = open(self.output, 'w')
def write_header(header, symbol='~'):
header = '{}{: ^70}{}'.format(symbol, header, symbol)
output.write(symbol * len(header) + '\n')
output.write(header + '\n')
output.write(symbol * len(header) + '\n')
output.flush()
def append_file(source, new_lines_at_the_end=True):
if not source.startswith('/'):
source = os.path.join(self.resultdir_adt, source)
if os.path.isfile(source):
with open(source, 'r') as fd:
for line in fd:
output.write(line)
if new_lines_at_the_end:
output.write('\n\n')
output.flush()
# write the current adt-run command
write_header('Command')
output.write(self.adt)
output.write('\n\n\n')
output.flush()
# call the builder and run adt-run
builder = args['opts'].get('default', 'builder')
base = '--basepath' if builder == 'cowbuilder' else '--basetgz'
with open(os.devnull, 'w') as fd:
cmd = [builder, '--execute', '--override-config']
cmd += (base, '%s/%s' % (args['directory'], args['distribution']))
cmd += ('--architecture', args['architecture'])
cmd += ('--buildplace', '%s/build' % args['directory'])
cmd += ('--aptcache', '%s/aptcache' % args['directory'])
cmd += ('--hookdir', args['opts'].get('default', 'pbuilderhooks'))
cmd += ('--configfile', args['cfg'])
cmd += ('--bindmount', self.gpghome)
cmd += ('--bindmount', self.resultdir)
if self.logging:
cmd += ('--logfile', '%s/logs/%s.%s' % (args['directory'],
'autopkgtest', strftime('%Y%m%d_%H%M%S')))
cmd += ('--', '/bin/bash', self.script)
call(cmd, stdout=fd, stderr=fd)
# build the log properly, first append the summary
write_header('Tests summary')
append_file(self.summary)
# then the log
write_header('Full log')
append_file('log')
# then the others
all_files = [f for f in os.listdir(self.resultdir_adt) if
os.path.isfile(os.path.join(self.resultdir_adt, f))
and f not in ['log', self.summary]]
for curr_file in all_files:
write_header('File: %s' % curr_file)
append_file(curr_file, curr_file != all_files[-1])
output.close()
self._finish()
|