9

我的项目有许多其他项目的公共变量,所以我使用 Jenkins 共享库并创建了一个vars/my_vars.groovy文件,在其中定义了我的变量并返回它们的 Map:

class my_vars {
    static Map varMap = [:]
    static def loadVars (Map config) {
        varMap.var1 = "val1"
        varMap.var2 = "val2"
        // Many more variables ...

        return varMap
    }
}

我在我的 Jenkinsfile 中加载共享库,并在环境项目符号中调用该函数,因为我希望这些变量作为 environment variables 。

詹金斯文件:

pipeline {

    environment {
        // initialize common vars
        common_vars = my_vars.loadVars()
    } // environment

    stages {
        stage('Some Stage') {
            // ...
        }
    }

    post {
        always { 
            script {
                // Print environment variables
                sh "env"
            } // script
        } // always
    } // post

} // pipeline

问题是环境项目符号KEY=VALUE成对,因此我common_vars的地图像字符串值一样加载(我可以在 上看到sh "env")。

...
vars=[var1:val1, var2:val2]
...

将这些值声明为环境变量的正确方法是什么?我的目标是:

...
var1=val1
var2=val2
...
4

3 回答 3

9

Pipeline 的环境变量只存储 String 值。这就是为什么当您将映射分配给它存储等效的env.common_vars变量时。map.toString()

如果您想将映射中的键值对重写为环境变量,您可以迭代变量映射并将每个k-v对分配给类似env."$k" = v. 您可以通过在environment块内调用类方法来做到这一点 - 这样,无论您的管道从哪个阶段重新启动,您都可以确保分配环境变量。考虑以下示例:

class MyVars {
    private Map config = [
        var1: "val1",
        var2: "val2"
    ]

    String initializeEnvironmentVariables(final Script script) {
        config.each { k,v ->
            script.env."$k" = v
        }

        return "Initialization of env variables completed!"
    }
}

pipeline {
    agent any

    environment {
        INITIALIZE_ENV_VARIABLES_FROM_MAP = "${new MyVars().initializeEnvironmentVariables(this)}"
    }

    stages {
        stage("Some stage") {
            steps {
                echo "env.var1 = ${env.var1}"
            }
        }
    }

    post {
        always {
            script {
                sh 'printenv | grep "var[0-9]\\+"'
            }
        }
    }
}

在这个例子中,我们使用MyVars类来存储一些全局配置映射(它可以是共享库的一部分,这里为了简单起见,它是 Jenkinsfile 的一部分)。我们使用INITIALIZE_ENV_VARIABLES_FROM_MAP环境变量赋值来调用MyVars.initializeEnvironmentVariables(this)可以envscript参数访问的方法。从块内部调用这个方法environment有一个显着的好处——它保证环境变量将被初始化,即使你从任何阶段重新启动管道。

这是这个示例管道的输出:

Running on Jenkins in /home/wololock/.jenkins/workspace/pipeline-env-map
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Some stage)
[Pipeline] echo
env.var1 = val1
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Declarative: Post Actions)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
+ grep 'var[0-9]\+'
+ printenv
var1=val1
var2=val2
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

如您所见,我们将它设置env.var1env.var2从封装在MyVars类中的地图中。这两个变量都可以在管道步骤、脚本块甚至 shell 环境变量中访问。

于 2019-11-04T13:38:41.343 回答
3

据我所知,在声明性管道中没有简单的方法(例如在环境指令中。相反,您可以做的是在声明性定义之外设置环境,如下所示:

my_vars.loadVars().each { key, value ->
    env[key] = value
}
// Followed by your pipelines definition:
pipeline {
    stages {
        stage('Some Stage') {
            // ...
        }
    }
    // ...
} // pipeline

作为一个完整的例子:

class my_vars {
    static Map varMap = [:]
    static def loadVars (Map config) {
        varMap.var1 = "val1"
        varMap.var2 = "val2"
        // Many more variables ...

        return varMap
    }
}

my_vars.loadVars().each { key, value ->
    env[key] = value
}

pipeline {
    agent any
    stages {
        stage("Some stage") {
            steps {
                echo "env.var1 = ${env.var1}"
            }
        }
    }
}

构建时输出以下内容:

Started by user xxx
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on yyy in /zzz
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Some stage)
[Pipeline] echo
env.var1 = val1
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

编辑;如果您的课程 (my_vars) 位于共享库 (MySharedLibrary) 中:

library 'MySharedLibrary' // Will load vars/my_vars.groovy
my_vars.loadVars().each { key, value ->
    env[key] = value
}

pipeline {
    agent any
    stages {
        stage("Some stage") {
            steps {
                echo "env.var1 = ${env.var1}"
            }
        }
    }
}
于 2019-11-04T13:43:36.703 回答
0

您不必从共享库中返回环境变量的映射。您可以简单地将它们设置在共享库方法中,该方法将在与管道相同的容器中运行。

在您共享的库vars/目录中:

def setVars() {
    env.var1 = "var1"
    env.var2 = "var2"
    env.var3 = "var3"
}

在您的管道中:

pipeline {
    agent any
    stages {
        stage("Setup") {
            steps {
                script {
                    imported_shared_lib.setVars()
                }
            }
        }
    }
}

其他人提到即使您从某个阶段重新启动管道,也需要保留环境变量。在我的实验中,使用此方法保留变量,即使在environment{}块中未调用 setVars() 方法。

于 2022-02-03T11:24:44.997 回答