[stable-2.10] Add coverage exporting to ansible-test
A new `--export` option for `ansible-test coverage combine` allows multi-step aggregation of code coverage for CI pipelines.
(cherry picked from commit fa2be89cd4
)
Co-authored-by: Matt Clay <matt@mystile.com>
This commit is contained in:
parent
8f767f7180
commit
cfa8075537
4 changed files with 38 additions and 3 deletions
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- ansible-test - Added a ``--export`` option to the ``ansible-test coverage combine`` command to facilitate multi-stage aggregation of coverage in CI pipelines.
|
|
@ -993,6 +993,9 @@ def add_extra_coverage_options(parser):
|
|||
action='store_true',
|
||||
help='generate empty report of all python/powershell source files')
|
||||
|
||||
parser.add_argument('--export',
|
||||
help='directory to export combined coverage files to')
|
||||
|
||||
|
||||
def add_httptester_options(parser, argparse):
|
||||
"""
|
||||
|
|
|
@ -61,6 +61,7 @@ class CoverageConfig(EnvironmentConfig):
|
|||
self.group_by = frozenset(args.group_by) if 'group_by' in args and args.group_by else set() # type: t.FrozenSet[str]
|
||||
self.all = args.all if 'all' in args else False # type: bool
|
||||
self.stub = args.stub if 'stub' in args else False # type: bool
|
||||
self.export = args.export if 'export' in args else None # type: str
|
||||
self.coverage = False # temporary work-around to support intercept_command in cover.py
|
||||
|
||||
|
||||
|
@ -210,6 +211,14 @@ def enumerate_powershell_lines(
|
|||
if not filename:
|
||||
continue
|
||||
|
||||
if isinstance(hits, dict) and not hits.get('Line'):
|
||||
# Input data was previously aggregated and thus uses the standard ansible-test output format for PowerShell coverage.
|
||||
# This format differs from the more verbose format of raw coverage data from the remote Windows hosts.
|
||||
hits = dict((int(key), value) for key, value in hits.items())
|
||||
|
||||
yield filename, hits
|
||||
continue
|
||||
|
||||
# PowerShell unpacks arrays if there's only a single entry so this is a defensive check on that
|
||||
if not isinstance(hits, list):
|
||||
hits = [hits]
|
||||
|
|
|
@ -19,6 +19,7 @@ from ..util import (
|
|||
|
||||
from ..util_common import (
|
||||
ResultType,
|
||||
write_json_file,
|
||||
write_json_test_results,
|
||||
)
|
||||
|
||||
|
@ -90,7 +91,12 @@ def _command_coverage_combine_python(args):
|
|||
|
||||
output_files = []
|
||||
|
||||
if args.export:
|
||||
coverage_file = os.path.join(args.export, '')
|
||||
suffix = '=coverage.combined'
|
||||
else:
|
||||
coverage_file = os.path.join(ResultType.COVERAGE.path, COVERAGE_OUTPUT_FILE_NAME)
|
||||
suffix = ''
|
||||
|
||||
path_checker = PathChecker(args, collection_search_re)
|
||||
|
||||
|
@ -109,7 +115,7 @@ def _command_coverage_combine_python(args):
|
|||
updated.add_arcs(dict((source[0], []) for source in sources))
|
||||
|
||||
if not args.explain:
|
||||
output_file = coverage_file + group
|
||||
output_file = coverage_file + group + suffix
|
||||
updated.write_file(output_file) # always write files to make sure stale files do not exist
|
||||
|
||||
if updated:
|
||||
|
@ -180,9 +186,15 @@ def _command_coverage_combine_powershell(args):
|
|||
coverage_data[source] = _default_stub_value(source_line_count)
|
||||
|
||||
if not args.explain:
|
||||
if args.export:
|
||||
output_file = os.path.join(args.export, group + '=coverage.combined')
|
||||
write_json_file(output_file, coverage_data, formatted=False)
|
||||
output_files.append(output_file)
|
||||
continue
|
||||
|
||||
output_file = COVERAGE_OUTPUT_FILE_NAME + group + '-powershell'
|
||||
|
||||
write_json_test_results(ResultType.COVERAGE, output_file, coverage_data)
|
||||
write_json_test_results(ResultType.COVERAGE, output_file, coverage_data, formatted=False)
|
||||
|
||||
output_files.append(os.path.join(ResultType.COVERAGE.path, output_file))
|
||||
|
||||
|
@ -267,10 +279,19 @@ def get_coverage_group(args, coverage_file):
|
|||
version=parts[3],
|
||||
)
|
||||
|
||||
export_names = dict(
|
||||
version=parts[3],
|
||||
)
|
||||
|
||||
group = ''
|
||||
|
||||
for part in COVERAGE_GROUPS:
|
||||
if part in args.group_by:
|
||||
group += '=%s' % names[part]
|
||||
elif args.export:
|
||||
group += '=%s' % export_names.get(part, 'various')
|
||||
|
||||
if args.export:
|
||||
group = group.lstrip('=')
|
||||
|
||||
return group
|
||||
|
|
Loading…
Reference in a new issue