diff --git a/Jenkinsfile b/Jenkinsfile index 84f3f499ce..19270edb9d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,11 +2,21 @@ def OSList = [ 'windows', - 'ubuntu18', 'ubuntu20', 'ubuntu22', - 'rhel7', 'rhel8', 'rhel9', - // 'alpine3.9-armhf', 'alpine3.9-x86_64', 'alpine3.9-x86', - 'debian9-64', 'debian10-64', 'debian11-64', - 'test-asan', 'test-tsan', 'test-ubsan', + 'ubuntu18', + 'ubuntu20', + 'ubuntu22', + 'rhel7', + 'rhel8', + 'rhel9', + // 'alpine3.9-armhf', + // 'alpine3.9-x86_64', + // 'alpine3.9-x86', + 'debian9-64', + 'debian10-64', + 'debian11-64', + 'test-asan', + 'test-tsan', + 'test-ubsan', ] def AdminList = [ @@ -92,12 +102,8 @@ pipeline { } stage("${OS} Test") { - sh "./deploy/build.sh --os=${OS} --test --eventport=\$((4100+\${EXECUTOR_NUMBER}))" - - // TODO: Why does this hang on windows? - if (env.OS != "windows") { - archiveArtifacts artifacts: 'tests/**/*.log,tests/**/test-suite.tap,tests/**/core' - } + EVENT_PORT = OSList.indexOf(OS) + 4100 + sh "./deploy/build.sh --os=${OS} --test --eventport=${EVENT_PORT}" } } } @@ -107,6 +113,19 @@ pipeline { } post { always { + + script { + for (OS in OSList) { + ws("${WORKSPACE}/${OS}") { + sh "./deploy/tap-to-junit.py --junit-suite-name=${OS}" + junit skipPublishingChecks: true, testResults: 'mdsplus-junit.xml' + } + } + } + + // Collect TAP results, valgrind core dumps + archiveArtifacts artifacts: "**/test-suite.tap,**/core", followSymlinks: false + cleanWs disableDeferredWipeout: true, deleteDirs: true } } diff --git a/deploy/tap-to-junit.py b/deploy/tap-to-junit.py new file mode 100755 index 0000000000..4e114893c8 --- /dev/null +++ b/deploy/tap-to-junit.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 + +import argparse +import os +import sys + +from pathlib import Path + +import xml.etree.ElementTree as xml + +parser = argparse.ArgumentParser() + +parser.add_argument( + '--junit-suite-name', + metavar='', + help='', +) + +args = parser.parse_args() + +# Using pathlib.Path.glob instead of glob.glob because it doesn't follow symlinks +# and the windows build directory has recursive symlinks +tap_filename_list = Path('.').glob('**/*.trs') + +all_tests = {} +failed_test_count = 0 + +for tap_filename in tap_filename_list: + + name = os.path.relpath(os.path.splitext(tap_filename)[0], os.getcwd()) + + log_filename = os.path.splitext(tap_filename)[0] + '.log' + if not os.path.exists(log_filename): + print(log_filename, 'not found') + log_filename = None + + result = None + + lines = open(tap_filename, 'rt').readlines() + for line in lines: + line = line.strip() + if line.startswith(':test-result: '): + result = line.removeprefix(':test-result: ') + + if result == 'FAIL': + failed_test_count += 1 + + all_tests[name] = { + 'log': log_filename, + 'result': result, + } + +root = xml.Element('testsuites') +root.attrib['tests'] = str(len(all_tests)) +root.attrib['failures'] = str(failed_test_count) + +testsuite = xml.SubElement(root, 'testsuite') + +# TODO: Improve +testsuite.attrib['name'] = 'mdsplus' +if args.junit_suite_name is not None: + testsuite.attrib['name'] = args.junit_suite_name + +for test_name, test in all_tests.items(): + testcase = xml.SubElement(testsuite, 'testcase') + testcase.attrib['name'] = test_name + + system_out = xml.SubElement(testcase, 'system-out') + system_out.text = open(test['log']).read() + + if test['result'] == 'FAIL': + failure = xml.SubElement(testcase, 'failure') + failure.attrib['message'] = 'Failed' + + if test['result'] == 'SKIP': + failure = xml.SubElement(testcase, 'skipped') + failure.attrib['message'] = 'Skipped' + +print(f'Writing JUnit output to mdsplus-junit.xml') +with open('mdsplus-junit.xml', 'wb') as f: + f.write(xml.tostring(root)) \ No newline at end of file