From d8615aeb7bbb74e0560eacb550a4a644b678458d Mon Sep 17 00:00:00 2001 From: Andrew Leonard <31470007+andrew-m-leonard@users.noreply.github.com> Date: Thu, 9 Mar 2023 15:27:32 +0000 Subject: [PATCH] Propagate downstream build & test results for pipeline. (#649) Co-authored-by: Shriti Chandra --- pipelines/build/common/build_base_file.groovy | 27 ++++++++++++------- .../common/openjdk_build_pipeline.groovy | 4 +-- pipelines/jobs/pipeline_job_template.groovy | 4 +-- .../jobs/release_pipeline_job_template.groovy | 4 +-- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/pipelines/build/common/build_base_file.groovy b/pipelines/build/common/build_base_file.groovy index 406ae3f24..e27165a63 100644 --- a/pipelines/build/common/build_base_file.groovy +++ b/pipelines/build/common/build_base_file.groovy @@ -828,13 +828,15 @@ class Builder implements Serializable { // Pass down DEFAULTS_JSON buildJobParams.add(['$class': 'TextParameterValue', name: 'DEFAULTS_JSON', value: JsonOutput.prettyPrint(JsonOutput.toJson(DEFAULTS_JSON)) ]) + def copyArtifactSuccess = false def downstreamJob = context.build job: downstreamJobName, propagate: false, parameters: buildJobParams - if (downstreamJob.getResult() == 'SUCCESS') { - // copy artifacts from build - context.println '[NODE SHIFT] MOVING INTO CONTROLLER NODE...' - context.node('worker') { - context.catchError { + context.println "Downstream job ${downstreamJobName} completed, result = "+downstreamJob.getResult() + + // copy artifacts from build regardless of job result + context.println '[NODE SHIFT] MOVING INTO CONTROLLER NODE...' + context.node('worker') { + context.catchError(message: "Error during copy and archive artifacts for build job: ${downstreamJobName}") { //Remove the previous artifacts try { context.timeout(time: pipelineTimeouts.REMOVE_ARTIFACTS_TIMEOUT, unit: 'HOURS') { @@ -877,12 +879,19 @@ class Builder implements Serializable { } catch (FlowInterruptedException e) { throw new Exception("[ERROR] Archive artifact timeout (${pipelineTimeouts.ARCHIVE_ARTIFACTS_TIMEOUT} HOURS) for ${downstreamJobName}has been reached. Exiting...") } + + copyArtifactSuccess = true } + } + context.println '[NODE SHIFT] OUT OF CONTROLLER NODE!' + + if ((downstreamJob.getResult() != 'SUCCESS' || !copyArtifactSuccess) && propagateFailures) { + context.error("Propagating downstream job result: ${downstreamJobName}, Result: "+downstreamJob.getResult()+" CopyArtifactsSuccess: "+copyArtifactSuccess) + if (copyArtifactSuccess && downstreamJob.getResult() == 'UNSTABLE' && (currentBuild.result == 'SUCCESS' || currentBuild.result == 'UNSTABLE' )) { + currentBuild.result = 'UNSTABLE' + } else { + currentBuild.result = 'FAILURE' } - context.println '[NODE SHIFT] OUT OF CONTROLLER NODE!' - } else if (propagateFailures) { - context.error("Build failed due to downstream failure of ${downstreamJobName}") - currentBuild.result = 'FAILURE' } } } diff --git a/pipelines/build/common/openjdk_build_pipeline.groovy b/pipelines/build/common/openjdk_build_pipeline.groovy index 2f301cf4e..5d1bfa8ec 100644 --- a/pipelines/build/common/openjdk_build_pipeline.groovy +++ b/pipelines/build/common/openjdk_build_pipeline.groovy @@ -302,7 +302,7 @@ class Build { context.catchError { context.build job: jobName, - propagate: false, + propagate: true, parameters: [ context.string(name: 'SDK_RESOURCE', value: 'upstream'), context.string(name: 'UPSTREAM_JOB_NUMBER', value: "${env.BUILD_NUMBER}"), @@ -423,7 +423,7 @@ class Build { } context.catchError { def testJob = context.build job: jobName, - propagate: false, + propagate: true, parameters: [ context.string(name: 'UPSTREAM_JOB_NUMBER', value: "${env.BUILD_NUMBER}"), context.string(name: 'UPSTREAM_JOB_NAME', value: "${env.JOB_NAME}"), diff --git a/pipelines/jobs/pipeline_job_template.groovy b/pipelines/jobs/pipeline_job_template.groovy index c989217cd..491993f1f 100644 --- a/pipelines/jobs/pipeline_job_template.groovy +++ b/pipelines/jobs/pipeline_job_template.groovy @@ -1,7 +1,7 @@ import groovy.json.JsonOutput gitRefSpec = '' -propagateFailures = false +propagateFailures = true runTests = enableTests runParallel = enableTestDynamicParallel runInstaller = true @@ -112,7 +112,7 @@ pipelineJob("${BUILD_FOLDER}/${JOB_NAME}") { booleanParam('cleanWorkspaceBeforeBuild', false, 'Clean out the workspace before the build') booleanParam('cleanWorkspaceAfterBuild', false, 'Clean out the workspace after the build') booleanParam('cleanWorkspaceBuildOutputAfterBuild', cleanWsBuildOutput, 'Clean out the workspace/build/src/build and workspace/target output only, after the build') - booleanParam('propagateFailures', propagateFailures, 'If true, a failure of ANY downstream build (but NOT test) will cause the whole build to fail') + booleanParam('propagateFailures', propagateFailures, 'If true, a failure of ANY downstream build will cause the whole build to fail') booleanParam('keepTestReportDir', false, 'If true, test report dir (including core files where generated) will be kept even when the testcase passes, failed testcases always keep the report dir. Does not apply to JUnit jobs which are always kept, eg.openjdk.') booleanParam('keepReleaseLogs', true, 'If true, "Release" type pipeline Jenkins logs will be marked as "Keep this build forever".') stringParam('adoptBuildNumber', '', 'Empty by default. If you ever need to re-release then bump this number. Currently this is only added to the build metadata file.') diff --git a/pipelines/jobs/release_pipeline_job_template.groovy b/pipelines/jobs/release_pipeline_job_template.groovy index ddc85010c..799b983a5 100644 --- a/pipelines/jobs/release_pipeline_job_template.groovy +++ b/pipelines/jobs/release_pipeline_job_template.groovy @@ -1,7 +1,7 @@ import groovy.json.JsonOutput String gitRefSpec = '' -Boolean propagateFailures = false +Boolean propagateFailures = true Boolean runTests = true Boolean runParallel = true Boolean runInstaller = true @@ -88,7 +88,7 @@ pipelineJob("${BUILD_FOLDER}/${JOB_NAME}") { booleanParam('cleanWorkspaceBeforeBuild', false, 'Clean out the workspace before the build') booleanParam('cleanWorkspaceAfterBuild', false, 'Clean out the workspace after the build') booleanParam('cleanWorkspaceBuildOutputAfterBuild', cleanWsBuildOutput, 'Clean out the workspace/build/src/build and workspace/target output only, after the build') - booleanParam('propagateFailures', propagateFailures, 'If true, a failure of ANY downstream build (but NOT test) will cause the whole build to fail') + booleanParam('propagateFailures', propagateFailures, 'If true, a failure of ANY downstream build will cause the whole build to fail') booleanParam('keepTestReportDir', false, 'If true, test report dir (including core files where generated) will be kept even when the testcase passes, failed testcases always keep the report dir. Does not apply to JUnit jobs which are always kept, eg.openjdk.') booleanParam('keepReleaseLogs', true, 'If true, "Release" type pipeline Jenkins logs will be marked as "Keep this build forever".') stringParam('adoptBuildNumber', '', 'Empty by default. If you ever need to re-release then bump this number. Currently this is only added to the build metadata file.')