You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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块放在Test stage的末尾,用always确保不管并行分支成功或失败,都会执行归档操作。
  • 代码简化:用三元运算符简化了sql_run_tag的判断逻辑,让代码更简洁。

内容的提问来源于stack exchange,提问作者Mati

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 16:27:47