diff --git a/runbot/container.py b/runbot/container.py index 1a38358a..3de78ca9 100644 --- a/runbot/container.py +++ b/runbot/container.py @@ -270,7 +270,7 @@ def tests(args): if args.coverage: omit = ['--omit', '*__manifest__.py'] python_params = [ '-m', 'coverage', 'run', '--branch', '--source', '/data/build'] + omit - posts = [['python%s' % py_version, "-m", "coverage", "html", "-d", "/data/build/coverage", "--ignore-errors"]] + posts = [['python%s' % py_version, "-m", "coverage", "html", "-d", "/data/build/coverage", "--ignore-errors"], ['python%s' % py_version, "-m", "coverage", "xml", "--ignore-errors"]] os.makedirs(os.path.join(args.build_dir, 'coverage'), exist_ok=True) elif args.flamegraph: flame_log = '/data/build/logs/flame.log' diff --git a/runbot/models/build_config.py b/runbot/models/build_config.py index 5e6aed36..02f84005 100644 --- a/runbot/models/build_config.py +++ b/runbot/models/build_config.py @@ -388,7 +388,7 @@ class ConfigStep(models.Model): if extra_params: cmd.extend(shlex.split(extra_params)) - cmd.posts.append(self._post_install_command(build, modules_to_install, py_version)) # coverage post, extra-checks, ... + cmd.posts.extend(self._post_install_commands(build, modules_to_install, py_version)) # coverage post, extra-checks, ... dump_dir = '/data/build/logs/%s/' % db_name sql_dest = '%s/dump.sql' % dump_dir filestore_path = '/data/build/datadir/filestore/%s' % db_name @@ -421,6 +421,10 @@ class ConfigStep(models.Model): kwargs['log_type'] = 'link' build._log('', **kwargs) + if self.coverage: + message = 'Coverage xml: $$fa-download' + build._log('end_job', message, log_type='link', path='/data/build/logs/coverage.xml') + if self.flamegraph: link = self._perf_data_url(build, 'log.gz') message = 'Flamegraph data: $$fa-download$$' @@ -433,14 +437,16 @@ class ConfigStep(models.Model): def _modules_to_install(self, build): return set(build._get_modules_to_test(modules_patterns=self.install_modules)) - def _post_install_command(self, build, modules_to_install, py_version=None): + def _post_install_commands(self, build, modules_to_install, py_version=None): + cmds = [] if self.coverage: py_version = py_version if py_version is not None else build._get_py_version() # prepare coverage result cov_path = build._path('coverage') os.makedirs(cov_path, exist_ok=True) - return ['python%s' % py_version, "-m", "coverage", "html", "-d", "/data/build/coverage", "--ignore-errors"] - return [] + cmds.append(['python%s' % py_version, "-m", "coverage", "html", "-d", "/data/build/coverage", "--ignore-errors"]) + cmds.append(['python%s' % py_version, "-m", "coverage", "xml", "-o", "/data/build/logs/coverage.xml", "--ignore-errors"]) + return cmds def _perfs_data_path(self, ext='log'): return '/data/build/logs/flame_%s.%s' % (self.name, ext) diff --git a/runbot/tests/test_build_config_step.py b/runbot/tests/test_build_config_step.py index 29dba737..0e8c1a42 100644 --- a/runbot/tests/test_build_config_step.py +++ b/runbot/tests/test_build_config_step.py @@ -153,12 +153,10 @@ class TestBuildConfigStep(RunbotCase): }) def docker_run(cmd, log_path, *args, **kwargs): - cmds = cmd.build().split(' && ') - dest = self.parent_build.dest self.assertEqual(cmd.pres, [['sudo', 'pip3', 'install', '-r', 'bar/requirements.txt']]) self.assertEqual(cmd.cmd[:10], ['python3', '-m', 'coverage', 'run', '--branch', '--source', '/data/build', '--omit', '*__manifest__.py', 'bar/server.py']) - #['bar/server.py', '--addons-path', 'bar', '--no-xmlrpcs', '--no-netrpc', '-d', '08732-master-d0d0ca-coverage', '--test-enable', '--stop-after-init', '--log-level=test', '--max-cron-threads=0'] - self.assertEqual(cmd.posts, [['python3', '-m', 'coverage', 'html', '-d', '/data/build/coverage', '--ignore-errors']]) + self.assertIn(['python3', '-m', 'coverage', 'html', '-d', '/data/build/coverage', '--ignore-errors'], cmd.posts) + self.assertIn(['python3', '-m', 'coverage', 'xml', '-o', '/data/build/logs/coverage.xml', '--ignore-errors'], cmd.posts) self.assertEqual(log_path, 'dev/null/logpath') self.patchers['docker_run'].side_effect = docker_run