Jenkins流水线测试失败后无法归档工件问题求助
Jenkins流水线并行测试归档问题修复
问题描述
我有一个Jenkins流水线,配置了5个并行运行的测试任务,原本期望所有测试完成后将所有工件归档到同一文件夹。但现在遇到的问题是:只要其中一个测试失败,其余测试会继续执行,但流水线最终会被标记为失败,且无法完成工件归档。
我试过用catchError将buildResult和stageResult设为SUCCESS,也在post块里用always步骤执行归档,但问题依然存在。
现有代码
stage("Test") { steps { parallel ( test1: { catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') { script { def sql_run_tag = "${params.sql_run_tag}" if (params.sql_run_tag == 'skip') { sql_run_tag = "Sanity-${env.BUILD_NUMBER}" } else { sql_run_tag = "${params.sql_run_tag}" } def build_test1 = build ( job: 'test1', wait: true, parameters: [ string(name: 'xx', value: params.xx), string(name: 'yy', value: params.yy), string(name: 'zz', value: params.zz), string(name: 'aa', value: params.aa), string(name: 'sql_run_tag', value: "${sql_run_tag}"), string(name: 'test_template', value: params.test_template), string(name: 'run_category', value: params.run_category), string(name: 'upstream_build_number', value: get_build_number) ] ) get_build_test1 = build_test1.getNumber().toString() copyArtifacts( projectName: 'test1', selector: specific("${build_test1.getNumber().toString()}"), filter: 'output_files/**/*', target: 'results/test1' ) post { always { archiveArtifacts artifacts: '**/Runs/xx/results/**/*' , fingerprint: true } } } } } // 其他4个测试分支类似 ) } }
控制台输出
[Pipeline] // script [Pipeline] } [Pipeline] // catchError [Pipeline] } Build test1 #1118 completed: SUCCESS [Pipeline] copyArtifacts Copied 18 artifacts from "test1" build number 1118 [Pipeline] archiveArtifacts Archiving artifacts [Pipeline] } [Pipeline] // script [Pipeline] } [Pipeline] // catchError [Pipeline] } [Pipeline] // parallel [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // withEnv [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: FAILURE
问题根源及修复方案
1. post块位置错误
你把post块放在了script内部,这不符合Jenkins Pipeline的语法规范。post块只能属于stage或者整个pipeline,不能嵌套在script或catchError里面。
2. 归档时机错误
应该在所有并行测试分支执行完成后,统一执行归档操作,而不是在单个分支里单独归档。
修改后的代码示例
stage("Test") { steps { parallel ( test1: { catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { // stageResult设为FAILURE可直观看到哪个分支失败 script { def sql_run_tag = params.sql_run_tag == 'skip' ? "Sanity-${env.BUILD_NUMBER}" : params.sql_run_tag def build_test1 = build ( job: 'test1', wait: true, parameters: [ string(name: 'xx', value: params.xx), string(name: 'yy', value: params.yy), string(name: 'zz', value: params.zz), string(name: 'aa', value: params.aa), string(name: 'sql_run_tag', value: sql_run_tag), string(name: 'test_template', value: params.test_template), string(name: 'run_category', value: params.run_category), string(name: 'upstream_build_number', value: get_build_number) ] ) get_build_test1 = build_test1.getNumber().toString() copyArtifacts( projectName: 'test1', selector: specific(get_build_test1), filter: 'output_files/**/*', target: 'results/test1' ) } } }, test2: { // 其他测试分支逻辑,结构同test1 }, // 补充test3、test4、test5分支 ) } // 将post块移到stage级别,确保所有并行分支完成后执行 post { always { // 归档所有测试结果目录下的工件 archiveArtifacts artifacts: 'results/**/*', fingerprint: true // 如果需要归档原路径的文件,保留原规则 archiveArtifacts artifacts: '**/Runs/xx/results/**/*', fingerprint: true } } }
关键说明
catchError参数调整:将stageResult设为FAILURE,可以在Jenkins UI上直观看到哪个测试分支失败,同时buildResult设为SUCCESS保证流水线整体不标记为失败。- 统一归档:把
post块放在Teststage的末尾,用always确保不管并行分支成功或失败,都会执行归档操作。 - 代码简化:用三元运算符简化了
sql_run_tag的判断逻辑,让代码更简洁。
内容的提问来源于stack exchange,提问作者Mati
相关产品推荐
相关产品推荐

