【问题标题】:In jenkins declarative pipeline, how can I set environment variable based on method?在 jenkins 声明式管道中,如何根据方法设置环境变量?
【发布时间】:2020-09-04 19:47:17
【问题描述】:

在 jenkins 声明式管道中,如何根据自定义 groovy/powershell 方法设置环境变量的值?例如,如果我有一个如下的 delcarative 管道,我可以使用共享库方法来设置这个值吗? 本质上,我正在尝试使用具有部署阶段的多分支声明性管道 jenkins 作业,但我需要确保开发分支部署到 DEV,发布分支部署到 STG,但使用相同的管道。我的想法是创建一个基于自定义方法设置的环境变量(可能在共享库中的 Groovy 中),并且该方法将简单地查看 env.BRANCH 的当前值,并且只需有一点逻辑来设置值目标部署环境。这是我设想的一个例子

pipeline {
environment {
    DEPLOY_ENV = mapBranchToDeployEnvironment(${BRANCH})
}

然后在我的部署阶段,我会在两个 powershell 调用中使用这个值

bat "powershell .\\Deploy-Service -Environment ${DEPLOY_ENV}"

bat "powershell .\\Deploy-ServiceProxy -Environment ${DEPLOY_ENV}"

否则,人们目前如何解决使用相同管道部署到不同环境的问题,同时在许多其他函数调用中使用变量? Jenkins 推荐的将触发构建的分支名称映射到应该部署到的环境(如果有)的方法是什么? 根据我的理解,声明式管道允许管道成为“多分支”,如果作业也部署,它需要映射到部署环境。当所有全局 jenkins 管道环境变量对于每个作业/分支执行都具有相同的值时,管道如何使用多分支部署到多个环境?

在上述场景中,管道变量“DEPLOY_ENV”派生自作业设置的其他环境变量,通常在阶段级别可用,但在这里我们希望全局设置值以便我们可以使用跨阶段

更新:我的问题是我没有意识到它有多么简单,而是认为我必须将一个阶段或脚本对象传递给一个 groovy 共享库函数,而实际上它就像创建一个共享库一样简单,然后直接引用方法中的环境变量。简单的。谢谢你。

【问题讨论】:

  • 你最终解决了这个问题吗?如何根据任意条件更改 environment 块中的变量值?

标签: jenkins groovy continuous-integration jenkins-pipeline continuous-deployment


【解决方案1】:

我遇到了完全相同的问题,确实可以使用共享库方法。但是还有另一种解决方案,如果您还没有设置共享库,则更简单,它包括在 Pipeline 语句之前定义一个 groovy 方法,然后在您的管道中使用它,如下所示:

def getEnvFromBranch(branch) {
  if (branch == 'master') {
    return 'production'
  } else {
    return 'staging'
 }
}

pipeline {
  agent any
  environment {
    targetedEnv = getEnvFromBranch(env.BRANCH_NAME)
  }
  stages {
    stage('Build') {
        steps {
            echo "Building in ${env.targetedEnv}"
        }
    }
 }
}

【讨论】:

  • 这对我不起作用...当我尝试在 shell 命令中使用它时,targetedEnv 只是空/未定义。
【解决方案2】:

你完全可以按照你的建议去做。您应该使用 var(一种新的 DSL 方法)创建一个 jenkins shared library。可以调用这些来分配给管道范围的环境变量。你说的基本正确。这是分配给环境变量的 Jenkinsfile 片段:

environment {
  DEPLOY_ENV = mapBranchToDeployEnvironment()
}

您不需要将分支传递给 mapBranchToDeployEnvironment DSL 方法,因为您可以在该方法中访问分支。共享库中vars/mapBranchToDeployEnvironment.groovy 的示例内容如下所示:

def call() {
  echo "branch is: ${env.BRANCH_NAME}"
  if (env.BRANCH_NAME == 'master') {
    return 'prod'
  } else {
    return 'staging'
  }
}

你可能不应该期望这是一个五分钟的任务,但你会得到它。祝你好运!

【讨论】:

  • 我已经尝试过了,但是,DSL 方法需要将“this”作为参数传递,并且参数的传递很可能发生在您上面提到的那一行。您能否提供一个示例,说明您上面描述的 DSL 方法如何传递必要的参数? “如果库需要访问全局变量,例如 env,则应将它们显式传递给库类或方法”jenkins.io/doc/book/pipeline/shared-libraries
  • 如果 jenkins 说的是真话,那就意味着需要在你上面提供的 sn-p 中传递参数,对吗?
  • 如果您只使用 var (jenkins.io/doc/book/pipeline/shared-libraries/…),则无需传递 this。我发现 vars 可以访问 Jenkinsfile 中可用的所有内容。如果您希望您的 var 调用您在 src/com/blah/blah.groovy 中定义的类或方法,那么您需要将 this 从 var 传递给该类。但除非你有更复杂的东西,否则不要这样做;只需使用一个var。 :)
  • 好的,您能否提供一个非常简单的 var 示例,它在其逻辑中引用了 env ?网上什么都没有
  • 非常感谢。我的错误:认为我必须传入某个对象,然后该方法将从该对象中找到并使用其属性。相反,它实际上就像创建方法一样简单,并直接从方法体内部使用 env 变量,类似于我们在 jenkisnfile 中使用的方式。再次感谢您。
【解决方案3】:
stage('Prepare env variables') {
    steps {
        script {
            if (env.BRANCH_NAME == 'master') {
                echo 'Copying project-stg.env file...';
                sh 'cp /opt/project-stg.env .env';
            } else {
                echo 'Copying project-dev.env file...';
                sh 'cp /opt/project-dev.env .env';
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2018-01-26
    • 1970-01-01
    • 2019-08-05
    • 2021-05-24
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 1970-01-01
    • 2017-08-09
    相关资源
    最近更新 更多