简体   繁体   English

Jenkins 声明式管道中的条件环境变量

[英]Conditional environment variables in Jenkins Declarative Pipeline

I'm trying to get a declarative pipeline that looks like this:我正在尝试获得如下所示的声明性管道:

pipeline {
    environment {
        ENV1 = 'default'
        ENV2 = 'default also'
    }
}

The catch is, I'd like to be able to override the values of ENV1 or ENV2 based on an arbitrary condition.问题是,我希望能够根据任意条件覆盖ENV1ENV2的值。 My current need is just to base it off the branch but I could imagine more complicated conditions.我目前的需要只是基于分支,但我可以想象更复杂的条件。

Is there any sane way to implement this?有没有明智的方法来实现这一点? I've seen some examples online that do something like:我在网上看到了一些例子,它们的作用如下:

stages {
    stage('Set environment') {
        steps {
            script {
                ENV1 = 'new1'
            }
        }
    }
}

But I believe this isn't setting the actually environment variable, so much as it is setting a local variable which is overriding later calls to ENV1 .但我相信这并没有设置实际的环境变量,而是设置了一个局部变量,该变量覆盖了以后对ENV1的调用。 The problem is, I need these environment variables read by a nodejs script, and those need to be real machine environment variables.问题是,我需要 nodejs 脚本读取这些环境变量,并且这些环境变量需要是真机环境变量。

Is there any way to set environment variables to be dynamic in a jenkinsfile?有没有办法在 jenkinsfile 中将环境变量设置为动态的?

Maybe you can try Groovy's ternary-operator :也许你可以试试 Groovy 的三元运算符

pipeline {
    agent any
    environment {
        ENV_NAME = "${env.BRANCH_NAME == "develop" ? "staging" : "production"}"
    }
}

or extract the conditional to a function:或将条件提取到函数:

 pipeline {
        agent any
        environment {
           ENV_NAME = getEnvName(env.BRANCH_NAME)
        }
    }

// ...

def getEnvName(branchName) {
    if("int".equals(branchName)) {
        return "int";
    } else if ("production".equals(branchName)) {
        return "prod";
    } else {
        return "dev";
    }
}

But, actually, you can do whatever you want using the Groovy syntax (features that are supported by Jenkins at least)但是,实际上,您可以使用 Groovy 语法做任何您想做的事情(至少 Jenkins 支持的功能)

So the most flexible option would be to play with regex and branch names...So you can fully support Git Flow if that's the way you do it at VCS level.所以最灵活的选择是使用正则表达式和分支名称......所以如果你在 VCS 级别这样做的话,你可以完全支持 Git Flow。

use withEnv to set environment variables dynamically for use in a certain part of your pipeline (when running your node script, for example).使用withEnv动态设置环境变量以用于管道的某个部分(例如,在运行节点脚本时)。 like this (replace the contents of an sh step with your node script):像这样(用你的节点脚本替换 sh 步骤的内容):

pipeline {
    agent { label 'docker' }
    environment {
        ENV1 = 'default'
    }
    stages {
        stage('Set environment') {
            steps {
                sh "echo $ENV1" // prints default
                // override with hardcoded value
                withEnv(['ENV1=newvalue']) {
                    sh "echo $ENV1" // prints newvalue
                }
                // override with variable
                script {
                    def newEnv1 = 'new1'
                    withEnv(['ENV1=' + newEnv1]) {
                        sh "echo $ENV1" // prints new1
                    }
                }
            }
        }
    }
}

Here is the correct syntax to conditionally set a variable in the environment section.这是在环境部分有条件地设置变量的正确语法。

environment {
    MASTER_DEPLOY_ENV = "TEST" // Likely set as a pipeline parameter
    RELEASE_DEPLOY_ENV = "PROD" // Likely set as a pipeline parameter
    DEPLOY_ENV = "${env.BRANCH_NAME == 'master' ? env.MASTER_DEPLOY_ENV : env.RELEASE_DEPLOY_ENV}"
    CONFIG_ENV = "${env.BRANCH_NAME == 'master' ? 'MASTER' : 'RELEASE'}"
}

I managed to get this working by explicitly calling shell in the environment section, like so:我设法通过在环境部分显式调用 shell 来使其工作,如下所示:

UPDATE_SITE_REMOTE_SUFFIX = sh(returnStdout: true, script: "if [ \"$GIT_BRANCH\" == \"develop\" ]; then echo \"\"; else echo \"-$GIT_BRANCH\"; fi").trim()

however I know that my Jenkins is on nix, so it's probably not that portable但是我知道我的 Jenkins 在 nix 上,所以它可能不是那么便携

Here is a way to set the environment variables with high flexibility, using maps:这是一种使用映射来灵活设置环境变量的方法:

    stage("Environment_0") {
        steps {
            script {
                def MY_MAP = [ME: "ASSAFP", YOU: "YOUR_NAME", HE: "HIS_NAME"]
                env.var3 = "HE"
                env.my_env1 = env.null_var ? "not taken" : MY_MAP."${env.var3}"
                echo("env.my_env1: ${env.my_env1}")                 
           }
        }
    }

This way gives a wide variety of options, and if it is not enough, map-of-maps can be used to enlarge the span even more.这种方式提供了多种选择,如果还不够,可以使用map-of-maps来进一步扩大跨度。 Of course, the switching can be done by using input parameters, so the environment variables will be set according to the input parameters value.当然,也可以通过输入参数来进行切换,所以环境变量会根据输入参数的值来设置。

pipeline {
    agent none
    environment {
        ENV1 = 'default'
        ENV2 = 'default'
    }
    stages {
        stage('Preparation') {
            steps {
                script {
                    ENV1 = 'foo' // or variable
                    ENV2 = 'bar' // or variable
                }
                echo ENV1
                echo ENV2
            }
        }
        stage('Build') {
            steps {
                sh "echo ${ENV1} and ${ENV2}"
            }
        }
        // more stages...
    }
}

This method is more simple and looks better.这种方法更简单,看起来更好。 Overridden environment variables will be applied to all other stages also.覆盖的环境变量也将应用于所有其他阶段。

I tried to do it in a different way, but unfortunately it does not entirely work:我试图以不同的方式做到这一点,但不幸的是它并不完全有效:

pipeline {
  agent any
  environment {
    TARGET = "${changeRequest() ? CHANGE_TARGET:BRANCH_NAME}"
  }

  stages {
    stage('setup') {
        steps {
            echo "target=${TARGET}"
            echo "${BRANCH_NAME}"
        }
    }
  }
}

Strangely enough this works for my pull request builds (changeRequest() returning true and TARGET becoming my target branch name) but it does not work for my CI builds (in which case the branch name is eg release/201808 but the resulting TARGET evaluating to null)奇怪的是,这适用于我的拉取请求构建(changeRequest() 返回 true 并且 TARGET 成为我的目标分支名称)但它不适用于我的 CI 构建(在这种情况下,分支名称是例如 release/201808 但生成的 TARGET 评估为无效的)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM