From 4b24d1f6218c3aefb6d4a96b7c02590608ac4f0f Mon Sep 17 00:00:00 2001 From: Akshat Chaudhary <220212015@geu.ac.in> Date: Fri, 31 Jul 2026 02:07:19 +0530 Subject: [PATCH] Aggregate JUnit results at parent test level (#6238) - In archiveChildJobTap(), copy JUnit XML artifacts from each parallel child job to the parent workspace alongside the existing TAP copy. Uses optional:true so child jobs without JUnit output are silently skipped. - After all child artifacts are gathered, publish an aggregated JUnit report at the parent build level using skipMarkingBuildUnstable:true and allowEmptyResults:true to avoid interfering with the pipeline's own status logic (ref #6244). The JUnit glob patterns match those already used at the child level (L1147): **/work/**/*.jtr.xml, **/result/**/*.jtr.xml, **/junitreports/**/*.xml, **/external_test_reports/**/*.xml --- buildenv/jenkins/JenkinsfileBase | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/buildenv/jenkins/JenkinsfileBase b/buildenv/jenkins/JenkinsfileBase index bb981dc6b7..426799bcdd 100644 --- a/buildenv/jenkins/JenkinsfileBase +++ b/buildenv/jenkins/JenkinsfileBase @@ -1789,6 +1789,15 @@ def archiveChildJobTap(childJobs, originalStatus = 'SUCCESS') { echo 'Exception: ' + e.toString() echo "Cannot copy *.tap or AQACert.log from ${name} with buildid ${buildId} . Skipping copyArtifacts..." } + // Aggregate JUnit XML results from child job to parent level (see #6238) + try { + timeout(time: 1, unit: 'HOURS') { + copyArtifacts (projectName: "${name}", selector: specific("${buildId}"), filter: "**/work/**/*.jtr.xml, **/result/**/*.jtr.xml, **/junitreports/**/*.xml, **/external_test_reports/**/*.xml", target:"${name}/${buildId}", optional: true) + } + } catch (Exception e) { + echo 'Exception: ' + e.toString() + echo "Cannot copy JUnit XML from ${name} with buildid ${buildId} . Skipping..." + } def childBuildUrl = "${env.JENKINS_URL}job/${name}/${buildId}" def badgeUrl = "${childBuildUrl}/badge/icon" def duration = cjob.getDuration() ?: "" @@ -1810,6 +1819,13 @@ def archiveChildJobTap(childJobs, originalStatus = 'SUCCESS') { childJobStatus += "" currentBuild.description = (currentBuild.description) ? currentBuild.description + "
" + childJobStatus : childJobStatus + // Publish aggregated JUnit results from all child jobs at the parent level (see #6238) + try { + junit skipMarkingBuildUnstable: true, allowEmptyResults: true, keepLongStdio: true, testResults: '**/work/**/*.jtr.xml, **/result/**/*.jtr.xml, **/junitreports/**/*.xml, **/external_test_reports/**/*.xml' + } catch (Exception e) { + echo "Caught exception when aggregating JUnit results at parent level: ${e.message}" + } + // In case rerun job status be worse than original job status if ( originalStatus != "SUCCESS" && isWorseThan( currentStatus, originalStatus)) { currentStatus = originalStatus