Jenkins在Jenkins中的不同节点上并行运行测试,没有这样的DSL方法';代理人';在台阶间找到的

Jenkins在Jenkins中的不同节点上并行运行测试,没有这样的DSL方法';代理人';在台阶间找到的,jenkins,jenkins-pipeline,Jenkins,Jenkins Pipeline,我让以下脚本在一个Jenkins上正常运行: def serenityBatches = [:] pipeline { agent any parameters { string(defaultValue: '6', description: 'Number of test batches that should runindividually, either parallel or batch after batch', name: 'batchCo

我让以下脚本在一个Jenkins上正常运行:

    def serenityBatches = [:]

pipeline {
    agent any

    parameters {
        string(defaultValue: '6', description: 'Number of test batches that should runindividually, either parallel or batch after batch', name: 'batchCount')
        string(defaultValue: '1', description: 'Number of tests/browsers that can run simultaniously on one node', name: 'forkCount')
    }

    options {
        buildDiscarder(logRotator(numToKeepStr: '10'))
        disableConcurrentBuilds()
    }

    stages {
        stage('Clean workspace') {

            steps {
                withMaven(){ sh "mvn clean" }
            }
        }
        stage('Create batches') {
            steps {
                script {
                    def batchCount = params.batchCount.toInteger()
                    def forkCount = params.forkCount.toInteger()

                    setJobDescription( batchCount, forkCount )

                    for (int i = 1; i <= batchCount; i++) {
                        def batchNumber = i
                        def batchName = "batch${batchNumber}"
                        serenityBatches[batchName] = {
                            node {
                                stage("batch${batchNumber} checkout") {
                                    cleanWs()
                                    checkoutFromSvn()
                                }
                                stage("batch${batchNumber} testing") {
                                    runTests(batchNumber, batchCount, forkCount)
                                }
                            }
                        }
                    }
                }
            }
        }
        stage('Execute tests') {
            steps {
                script {
                    parallel serenityBatches
                }
            }
        }
        stage('Generate Report') {
            steps {
                collectReportsFromAllBatches()
                aggregateReports()
                publishReport()
                zulipNotification stream: 'xxy', topic: 'AutoTests'
            }
        }
    }
    post {
        changed {
            script {
                // report back to normal after failure
               if(hudson.model.Result.FAILURE.equals(currentBuild.getPreviousBuild().result)) {
                  zulipNotification stream: 'xxy', topic: 'AutoTests'
                }
            }
        }
    }
}

void checkoutFromSvn() {
    checkout changelog: false, 
        scm: [ $class: 'SubversionSCM', 
            locations: [[   cancelProcessOnExternalsFail: true, 
            credentialsId: 'someID', 
            depthOption: 'infinity', 
            ignoreExternalsOption: true, 
            local: '.', 
            remote: 'https://whatever',
            clearWorkspace: true
            ]], 
        quietOperation: true, 
        workspaceUpdater: [$class: 'UpdateUpdater']
        ]
}

void runTests(batchNumber, batchCount, forkCount) {
    try {
        withMaven(){
            sh "mvn clean"
            sh "rm -rf target/site/serenity"
            sh "mvn -U verify -Dparallel.tests=${forkCount} -Dserenity.batch.count=${batchCount} -Dserenity.batch.number=${batchNumber}"
        }
    } catch (Throwable e) {
        throw e
    } finally {
        stash name: getStashId(batchNumber), excludes: "**", allowEmpty: true
        stash name: getStashId(batchNumber), includes: "target/site/serenity/**/*", allowEmpty: true
    }
}

String getStashId(int batchNumber) {
    return "$JOB_NAME".replace('/','_')+"-$BUILD_NUMBER-batch-${batchNumber}"
}

/** unstash each of the batches **/
void collectReportsFromAllBatches() {
    script {
        def batchCount = params.batchCount.toInteger()
        for (int batchNumber = 1; batchNumber <= batchCount; batchNumber++) {
            def stashName = getStashId(batchNumber)
            unstash stashName
        }
    }
}

void aggregateReports() {
    withMaven(){ sh "mvn serenity:aggregate" }
}

/** publish the Serenity report **/
void publishReport() {
    publishHTML(target: [
            reportName : 'Serenity Report',
            reportDir:   'target/site/serenity',
            reportFiles: 'index.html',
            keepAll:     true,
            alwaysLinkToLastBuild: true,
            allowMissing: false
    ])
}

void setJobDescription(int batchCount, int forkCount) {
    currentBuild.description = "batches:$batchCount forks:$forkCount"
}
def serenityBatches=[:]
管道{
任何代理人
参数{
字符串(defaultValue:'6',description:'应单独运行的测试批数,并行或批后运行',name:'batchCount')
字符串(defaultValue:'1',description:'可以在一个节点上同时运行的测试/浏览器的数量',name:'forkCount')
}
选择权{
构建丢弃器(logRotator(numtokepstr:'10'))
disableConcurrentBuilds()
}
舞台{
阶段(“清洁工作区”){
台阶{
withMaven(){sh“mvn clean”}
}
}
阶段('创建批'){
台阶{
剧本{
def batchCount=params.batchCount.toInteger()
def forkCount=params.forkCount.toInteger()
setJobDescription(batchCount、forkCount)

对于(inti=1;i尝试使用包含阶段的块的节点(标签){…}块定义代理

例如:

serenityBatches[batchName] = {
    node('chrome') {
        stage("batch${batchNumber} checkout") {
            steps {
                cleanWs()
                checkoutFromSvn()
                runTests(batchNumber, batchCount, forkCount)
            }
        }
    }
}

似乎您在
脚本
中嵌套了
阶段
,这意味着
代理
嵌套在
脚本
块中。这在语法上是不明确的,可能是不允许的,这可能是您看到该错误的原因。请尝试在
阶段
之前关闭
脚本
块d以后打开一个新的。我不确定你打算在哪里这样做。我需要脚本块来向集合中添加批。如果你能提供一个示例作为答案,我将试一试。好的,我刚想到你可能使用的是脚本管道,而不是声明性的。我被使用
代理
而抛弃了您使用的是脚本语法而不是声明性的,对吗?我理解这是声明性的。虽然我经常对什么是什么感到困惑…实际上我不介意哪一个…它应该可以工作。:)好球。我已经试过了。这就是为什么在那个位置上有空行。;-)但给我同样的错误:
java.lang.NoSuchMethodError:在步骤中找不到这样的DSL方法“agent”
您得到了一条空行,并且在步骤{}中定义了一个agent{label'chrome'}block。确保在没有代理{label'chrome}的情况下测试我的解决方案。你应该知道这一点。现在我得到了一个
java.lang.NoSuchMethodError:在步骤中找不到这样的DSL方法“步骤”
。谢谢。从这里开始尝试。``serentitybatches[batchName]={node('chrome'){stage(“batch${batchNumber}checkout”){steps{cleanWs()checkoutFromSvn()runTests(batchNumber,batchCount,forkCount)}}}}}``所以现在这是一个“脚本化管道”对吗?因为对于声明性管道,示例清楚地说明了“代理”而不是“节点”
serenityBatches[batchName] = {
    node('chrome') {
        stage("batch${batchNumber} checkout") {
            steps {
                cleanWs()
                checkoutFromSvn()
                runTests(batchNumber, batchCount, forkCount)
            }
        }
    }
}