当前位置: 首页 > 知识库问答 >
问题:

如何从并行子作业复制工件

习宸
2023-03-14

我在用詹金斯自动化并行JMeter测试。这被设置为两个独立的Jenkins管道作业,父作业和子作业。

子作业接受一系列参数,并对目标服务执行JMeter测试。这是工作和档案四个CSV的和一个XML文件在每个版本。

父作业在不同节点上并行执行子作业多次。目前它在测试中执行了两次,但最终打算一次生成10或20个子作业。并行执行有效,每次执行父作业时,子作业都会记录两次构建,并存档它们的工件。

问题是如何配置复制工件插件,以便从子作业中检索工件,从而将其归档到父作业中。

  1. 我尝试了buildParameter选项(CC_DGN_Test是子作业的名称)。我在子作业中创建了一个名为ParentBuildTag的参数,类型为Build selector for Copy Artifact。选中复制工件的权限复选框,将允许复制工件的项目字段设置为*
post {
    always {
        script {
            print "buildParameter('${BUILD_TAG}') == " + buildParameter("${BUILD_TAG}")
            copyArtifacts optional: false, projectName: 'CC_DGN_Test', selector: buildParameter("${BUILD_TAG}")
            archiveArtifacts "*.xml"
        }
        cleanWs()
    }
}

生成参数正在填充到子作业中,如下所示:

stage('Node 2') {
    agent { node { label 'PIPELINE' } }
    steps {
        script {
            node2 = build job: 'CC_DGN_Test',
                parameters: [
                    string(name: 'dummy', value: "2"),
                    string(name: 'ParentBuildTag', value: "${BUILD_TAG}"),
                    string(name: 'Labels', value: "JMETER"),
                    ...additional parameters snipped...
                ]
        }
    }
}

控制台日志显示一个错误:

Error when executing always post condition:
hudson.AbortException: Unable to find a build for artifact copy from: CC_DGN_Test
    at hudson.plugins.copyartifact.CopyArtifact.perform(CopyArtifact.java:412)
    at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:80)
    at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:67)
    at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

不会将任何内容复制到父级。build标记被正确地打印到控制台日志中(来自post{}中的print语句)。

08:18:52 buildParameter('jenkins-CC_DGN_TrickleTest-45') == @buildParameter(<anonymous>=jenkins-CC_DGN_TrickleTest-45)

这种方法看起来很有希望,但我认为有一个语法问题......我认为我应该告诉复制工件插件使用值为“jenkins-CC_DGN_TrickleTest-45”的父母构建标签参数,但我还没有找到描述语法的示例。

stage('Node 2') {
    agent { node { label 'PIPELINE' } }
    steps {
        script {
            node2 = build job: 'CC_DGN_Test',
                parameters: [
                    string(name: 'dummy', value: "2"),
                    string(name: 'ParentBuildTag', value: "${BUILD_TAG}"),
                    string(name: 'Labels', value: "JMETER"),
                    ...additional parameters snipped...
                ]
            print "Build number (node 2) = " + node2.number //prints build number to console e.g. "Build number (node 2) = 102"
            copyArtifacts optional: false, filter: '*.xml, *.csv', fingerprintArtifacts: true, projectName: 'CC_DGN_Test', selector: specific(node2.number)
        }
    }
}

内部版本号正确打印到控制台日志中,但不会记录任何错误,也不会复制任何内容。

properties([parameters([
    [$class: 'BuildSelectorParameter',
    defaultSelector: upstream(fallbackToLastSuccessful: true),
    description: '',
    name: 'ParentBuildTag']])
])
copyArtifacts(
    projectName: 'CC_DGN_Test',
    selector: [
        class: 'ParameterizedBuildSelector', 
        parameterName: 'ParentBuildTag'
    ]
);

再一次,我的怀疑是,我需要告诉它ParentBuildTag使用什么值,但我从中借用的语法示例没有说明如何做到这一点。“上游……”部分只是我从示例中复制的东西,不是我认为我需要的东西,但在我的测试中包含它似乎是无害的。

stash includes: '*.xml', name: 'node1xml'
unstash 'node1xml'

以下是当前的父作业配置,为简洁起见,在某些地方进行了裁剪:

pipeline {
    agent { node { label 'PIPELINE' } }
    options {
        timeout(time: 1, unit: 'HOURS')
        buildDiscarder(logRotator(numToKeepStr: '100'))
        timestamps()
    }
    environment {
        node1 = ""
        node2 = ""
    }

    stages {
        stage('Clean Up') {
            steps {
                cleanWs()
            }
        }

        stage('Test') {
            parallel {
                stage('Node 1') {
                    agent { node { label 'PIPELINE' } }
                    steps {
                        script {
                            node1 = build job: 'CC_DGN_Test',
                                parameters: [
                                    string(name: 'dummy', value: "1"),
                                    string(name: 'ParentBuildTag', value: "${BUILD_TAG}"),
                                    string(name: 'Labels', value: "JMETER"),
                                    ...additional parameters snipped...
                                ]
                        }
                    }
                }

                stage('Node 2') {
                    agent { node { label 'PIPELINE' } }
                    steps {
                        script {
                            node2 = build job: 'CC_DGN_Test',
                                parameters: [
                                    string(name: 'dummy', value: "2"),
                                    string(name: 'ParentBuildTag', value: "${BUILD_TAG}"),
                                    string(name: 'Labels', value: "JMETER"),
                                    ...additional parameters snipped...
                                ]
                        }
                    }
                }
            }
        }
    }

    post {
        always {
            script {
                copyArtifacts optional: false, projectName: 'CC_DGN_Test', selector: buildParameter("${BUILD_TAG}")
                archiveArtifacts "*.xml"
            }
            cleanWs()
        }
    }
}

我的目标是在作业完成后,根据当前配置,父作业总共包含八个CSV和两个XML,但当前父作业中没有任何存档。我的复制工件语法哪里出错了?

共有1个答案

孟昆
2023-03-14

你的观点2。方法是正确的。你只需要转换node2。数字到字符串:

selector: specific("${node2.number}")

您还可以在方法中调用子作业。这是一个示例脚本:

#! groovy
pipeline {
    environment {
        childJobName = "Testing/MyChildJob"
    }
    stages {
        stage('Child Jobs') {
            parallel {
                stage('ChildJob1') {
                    steps {
                        runJob(childJobName, '@tag1 @tag2', 'job1')
                    }
                }
                stage('ChildJob2') {
                    steps {
                        runJob(childJobName, '@tag3 @tag4', 'job2')
                    }
                }
            }
        }
    }
    post {
        cleanup{
            cleanWs()
        }
    }
}

def runJob(String jobName, String tags, String rootReportDir) {

    def childJob = build job: jobName, propagate: false, wait: true, parameters: [string(name: 'TAGS', value: tags)]
    copyArtifacts filter: "report.html", projectName: jobName, selector: specific("${childJob.number}"), target: rootReportDir
    archiveArtifacts artifacts: "${rootReportDir}/report.html"

    if (childJob.result == "FAILURE") {
        bat "exit 1"
    }
}

在本例中,子作业都是相同的詹金斯作业。父作业会向每个作业传递不同的参数。

子作业生成的报告文件将复制到父作业中的rootReportDir中。rootReportDir对于每个子作业都应该是唯一的,这样每个报告在存档到父作业时都有一个唯一的路径。

 类似资料:
  • 问题内容: 是否可以通过多个上游作业的Join插件复制工件触发Jenkins作业? 我正在尝试使用“钻石”作业来设置Jenkins配置:my-trigger运行并产生两个作业,my-fork1和my- fork2,它们可以同时运行并且花费不同的时间,并且Join一旦两个分支完成,插件就会启动作业my-join。 my-trigger,my-fork1和my-fork2中的每一个都创建并指纹工件(例

  • 是否可能有一个Jenkins作业被来自多个上游作业的连接插件复制工件触发? 我试图设置一个带有“钻石”作业的詹金斯配置:我的触发器运行并产生两个作业,我的叉子1和我的叉子2,它们可以同时运行并花费不同的时间,而加入插件会同时启动我的加入作业叉子已完成。 my-触发器、my-fork1和my-fork2中的每一个都创建和指纹工件(例如,文本文件)。 我想使用“从另一个项目复制工件”工具,将“哪个构建

  • 一个spark有一个oracle查询。所以我必须并行运行多个作业,以便所有查询都将同时激发。 如何并行运行多个作业?

  • 我正试图将所有工作表(7张)从workbook1(wb1)复制到WB2。wb1包含命令按钮,但我不希望它们出现在我的新工作簿中。我正在使用循环将单个工作表从一个工作簿复制到另一个工作簿。但是复制到第二张时出错了。我使用的代码如下:- 循环第一次成功运行,但对于i=2,代码给出错误

  • 我有一个作业流,我希望以以下方式运行它: 作业流将从Job1开始。在Job1成功完成后,Job1将同时启动Job2和Job4。 Job2和Job4将并行运行。 在Job2成功完成后,Job2将启动Job3。 在Job4成功完成后,Job4将启动Job5。 下面是job1.xml和job1的作业启动器类的代码片段: job1.xml uijobLauncher.java “job2,Job3”对和“

  • 问题内容: 我有BuildFlow做了一个工作,这个工作接收参数一样,, 。 在我的DSL我单独一个参数的值,所以现在我有一个数组:。 现在,我想让DSL用X构建并行运行一个子作业,其中X是数组的大小,并迭代将数组的每个位置作为参数传递给子作业的构建。 问题答案: 在您的dsl中尝试以下操作: 此代码段使用此处记录的并行作业执行语法。 默认情况下,Groovy会正确处理“并行” -DSL 的列表,