Импорт переменной карты на этапе среды Jenkinsfile - PullRequest
3 голосов
/ 04 ноября 2019

В моем проекте есть много общих переменных для многих других проектов, поэтому я использую Jenkins Shared Library и создал файл vars/my_vars.groovy, в котором я определил свои переменные и вернул карту их:

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

        return varMap
    }
}

Я загружаюОбщая библиотека в моем Jenkinsfile и вызов функции в маркере environment , так как я хочу, чтобы эти переменные были переменными среды.

Jenkinsfile:

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
...

Ответы [ 2 ]

2 голосов
/ 04 ноября 2019

Переменные окружения конвейера хранят только строковые значения. Вот почему, когда вы присваиваете карту переменным 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 для хранения некоторой глобальной карты конфигурации (она может быть частью общей библиотеки, здесь для простоты она является частьюДженкинсфайл). Мы используем INITIALIZE_ENV_VARIABLES_FROM_MAP присваивание переменной окружения для вызова MyVars.initializeEnvironmentVariables(this) метода, который может получить доступ к env из параметра script. Вызов этого метода изнутри 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.var1 и env.var2 из карты, инкапсулированной в классе MyVars. Обе переменные могут быть доступны внутри шага конвейера, блока скрипта или даже внутри переменных среды оболочки.

1 голос
/ 04 ноября 2019

Насколько я знаю, нет простого способа сделать это в декларативном конвейере (например, в директиве environment. Вместо этого вы можете настроить окружение вне декларативного определения, например так:

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}"
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...