将参数从Jenkinsfile传递到共享库

时间:2019-01-10 08:55:37

标签: jenkins jenkins-pipeline

我有几个组件(具有自己的Bitbucket存储库的代码项目),每个组件都有一个Jenkinsfile,如下所示:

licence.customers

需要使用“包装程序”管道,例如wrapperPipeline.groovy:

properties([parameters([string(defaultValue: "", description: "List of components", name: 'componentsToUpdate'),
                        string(defaultValue: "refs%2Fheads%2Fproject%2Fintegration", description: "BuildInfo CommitID", name: 'commitId'),
                        string(defaultValue: "", description: "Tag to release, e.g. 1.1.0-integration", name: 'releaseTag'),
                        string(defaultValue: "", description: "Forked buildInfo repo. Be aware right commit ID!!!", name: 'fork')]),
                        [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '7', numToKeepStr: '5']],
                        disableConcurrentBuilds()])

@Library('jenkins-shared-stages')

import mergePipeline
import releasePipeline
import ripplePipeline
import componentPipeline


def branchName = env.BRANCH_NAME
def rewriteDependencies = ""
def returnValue = null
def forkedRepo = params.fork
def buildInfoCommitId = params.commitId
def tagToRelease = params.releaseTag
println "buildInfoCommitId: " + buildInfoCommitId
if(params.componentsToUpdate) {
    rewriteDependencies = params.componentsToUpdate
}

if (branchName == "project/integration") {
    mergePipeline {
    }
} else if (branchName == 'master') {
    releasePipeline {
        releaseTag = tagToRelease
    }
} else {
    returnValue = componentPipeline {
        componentsToUpdate = rewriteDependencies
        commitId = buildInfoCommitId
        runOnForkedRepo = forkedRepo
    }

    rewriteDependencies = rewriteDependencies.isEmpty() ? returnValue : rewriteDependencies + "," + returnValue
    println "WHAT is rewriteDependencies? " + rewriteDependencies
    println "The return value: " + returnValue
    ripplePipeline {
        commitId = buildInfoCommitId
        componentName = returnValue
        runOnForkedRepo = forkedRepo
        componentsToUpdate = rewriteDependencies
    }
}

修改后的Jenkins文件:

import mergePipeline
import releasePipeline
import ripplePipeline
import componentPipeline
import org.slf4j.Logger
import org.slf4j.LoggerFactory

def call(body) {

    final Logger logger = LoggerFactory.getLogger(wrapperPipeline)

    def config = [:]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config
    body()

    // Assuming we have multibranch pipeline job or defined branch name in the env
    def branchName = env.BRANCH_NAME
    // There is a bug in the Jenkins it will pass a string "null" as a gradle build parameter instead of NULL object if there is
    // empty parameter has been passed!!!
    def rewriteDependencies = ""
    def returnValue = null
    def forkedRepo = config.runOnForkedRepo
    def buildInfoCommitId = config.commitId
    def tagToRelease = config.releaseTag

    def globalVars = new se.GlobalVars()
    def notifyHandler = new se.NotifyHandler()

    node(globalVars.getAgent('buildAgent')) {
        def PIPELINE_NAME = "wrapperPipeline"

        try {
            logger.info("The buildInfoCommitId is {}", buildInfoCommitId)
            logger.info("Branch name: {}", branchName)

            println "buildInfoCommitId:  "+buildInfoCommitId
            println"Branch name: "+branchName

            if (config.componentsToUpdate) {
                rewriteDependencies = config.componentsToUpdate
            }

    // keep the same integration pipeline for the master branch for now
            if (branchName == "project/integration") {
                logger.info("Invoking mergePipeline")
                println "Invoking mergePipeline"
                mergePipeline {
                }
            } else if (branchName == 'master') {
                logger.info("Invoking releasePipeline")
                println "Invoking releasePipeline"
                releasePipeline {
                    releaseTag = tagToRelease
                }
            } else {
                logger.info("Invoking componentPipeline")
                println "Invoking componentPipeline"

                returnValue = componentPipeline {
                    componentsToUpdate = rewriteDependencies
                    commitId = buildInfoCommitId
                    runOnForkedRepo = forkedRepo
                }
                logger.info("Component pipeline has returned {}", returnValue)
                println "Component pipeline has returned"+returnValue

                // We need to provide new version of the component to the Ripple builds
                rewriteDependencies = rewriteDependencies.isEmpty() ? returnValue : rewriteDependencies + "," + returnValue
                logger.info("rewriteDependencies: {}", rewriteDependencies)
                println "The return value: " + returnValue
                ripplePipeline {
                    commitId = buildInfoCommitId
                    componentName = returnValue
                    runOnForkedRepo = forkedRepo
                    componentsToUpdate = rewriteDependencies
                }
            }
        }
        catch (err) {
            def build_status = "Exception ${err.message} in build ${env.BUILD_ID}"
            logger.error(build_status,err)
            notifyHandler.NotifyFail(build_status, PIPELINE_NAME)

            throw err
        }

    }
}

现在,我怀疑 params 对象(Jenkinsfile中的属性)未正确填充。例如

properties([parameters([string(defaultValue: "", description: "List of components", name: 'componentsToUpdate'),
                        string(defaultValue: "refs%2Fheads%2Fproject%2Fintegration", description: "BuildInfo CommitID", name: 'commitId'),
                        string(defaultValue: "", description: "Tag to release, e.g. 1.1.0-integration", name: 'releaseTag'),
                        string(defaultValue: "", description: "Forked buildInfo repo. Be aware right commit ID!!!", name: 'fork')]),
                        [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '7', numToKeepStr: '5']],
                        disableConcurrentBuilds()])

@Library('jenkins-shared-stages@integration/CICD-959-wrapper-pipeline-for-the-jenkinsfile') _

import wrapperPipeline

wrapperPipeline{}

打印为空。

如何正确调用wrapperPipeline?

注意:我对Jenkins管道和Groovy都是陌生的:)

1 个答案:

答案 0 :(得分:1)

由于这些是詹金斯参数,因此不在配置对象中。

您将以params.commitId的身份访问commitId

如果在调用wrapperPipeline()时在闭包中包含某些内容,则这些内容将位于config对象中。例如

wrapperPipeline({
    param="value"
})

然后,config.param将导致"value"

但是,作为建议,我建议避免在调用共享库中vars /下存储的lib时避免使用闭包。有关什么是闭包,请参见http://groovy-lang.org/closures.html。症结在于,它们相当复杂,如果由于实例化闭包的时间而最终尝试传递动态变量,则会带来一些问题。 (他们有自己的位置,但是对于简单的事情,我认为避免更好)

我建议改为实现一个帮助程序功能,该功能将允许您使用地图或闭包来调用共享库。

在您的src路径下添加一个名为buildConfig的共享库:

package net.my.jenkins.workflow
import com.cloudbees.groovy.cps.NonCPS

class BuildConfig implements Serializable {
    static Map resolve(def body = [:]) {

        Map config = [:]
        config = body
        if (body in Map) {
            config = body
        } else if (body in Closure) {
            body.resolveStrategy = Closure.DELEGATE_FIRST
            body.delegate = config
            body()
        } else {
            throw  new Exception(sprintf("Unsupported build config type:%s", [config.getClass()]))
        }
        return config
    }
}

然后在vars /下的共享库中,以

开始
import net.my.jenkins.workflow.BuildConfig

def call(def body = [:]) {
    // evaluate the body block, and collect configuration into the object
    config = BuildConfig.resolve(body)

然后,您可以使用Maps来消除复杂性,因此可以(例如,不这样做,因为您只使用params.commitId)可以重新分配它。

wrapperPipeline ([
    "commitId": params.commitId,
])

这又意味着config.commitId现在的值为params.commitId

如果您需要更多详细信息,请告诉我。

TL; DR-您应该使用params对象,因为已经定义了参数。 如果确实通过共享的lib调用开始传递参数,那么我将在闭包上使用映射。 (需要一些最小的实现)

相关问题