我正在使用Jenkins自动执行并行的JMeter测试。这被设置为两个单独的Jenkins管道作业,即父作业和子作业。
子作业需要一系列参数,并针对目标服务执行JMeter测试。这可以正常工作,并且在每个版本上都存档四个CSV和一个XML文件。
父作业在不同节点上并行执行多次子作业。目前,它在测试中执行两次,但最终最终一次生成10或20个子作业。并行执行有效,子作业每次执行父项时都会记录两次构建,并且它们的工件已存档。
问题是如何配置“复制工件”插件以从子作业中检索工件,以便可以将其存储在父作业中。
ParentBuildTag
中创建了一个参数,类型为Build selector for Copy Artifact
。选中Permission to Copy Artifact
复选框,并将Projects to allow copy artifacts
字段设置为*
。post {
always {
script {
print "buildParameter('${BUILD_TAG}') == " + buildParameter("${BUILD_TAG}")
copyArtifacts optional: false, projectName: 'CC_DGN_Test', selector: buildParameter("${BUILD_TAG}")
archiveArtifacts "*.xml"
}
cleanWs()
}
}
将build参数填充到子作业中,如下所示:
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)
什么都不会复制到父级。构建标记已正确打印到控制台日志(从post {}中的打印语句)。
08:18:52 buildParameter('jenkins-CC_DGN_TrickleTest-45') == @buildParameter(<anonymous>=jenkins-CC_DGN_TrickleTest-45)
这种方法看起来很有希望,但是我认为存在语法问题...我想我应该告诉copyArtifacts插件使用ParentBuildTag参数,其值为'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,但是当前父作业没有任何存档。 copyArtifact语法在哪里出问题?
答案 0 :(得分:1)
您的观点2。方法是正确的方法。您只需要将node2.number
转换为字符串:
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应该是唯一的,以便每个报表在归档到父作业时都具有唯一的路径。