Используйте легкий исполнитель для декларативной стадии конвейера (агент none)

Я использую Jenkins Pipeline с декларативным синтаксисом, в настоящее время со следующими этапами:

  • Подготовка
  • Сборка (два параллельных набора шагов)
  • Тест (также два параллельных набора шагов)
  • Спросите, где/где развернуть
  • Deploy

Для шагов 1, 2, 3 и 5 мне нужно и агента (исполнителя), потому что они выполняют фактическую работу в рабочей области. Для шага 4 мне это не нужно, и я бы не хотел блокировать моих доступных исполнителей во время ожидания ввода пользователя. Это, по-видимому, упоминается как "облегченный" или "легкий" исполнитель для классического синтаксиса сценария, но я не могу найти никакой информации о том, как добиться этого с помощью декларативного синтаксиса.

До сих пор я пробовал:

  • Настройка агента непосредственно в параметрах конвейера, а затем установка agent none на сцене. Это не влияет, и конвейер работает как normalt, блокируя исполнитель во время ожидания ввода. В документации также упоминается, что это не будет иметь никакого эффекта, но я думал, что все равно сделаю это.
  • Настройка agent none в параметрах конвейера, а затем установка агента для каждого этапа, кроме # 4. К сожалению, но, как ожидается, это выделяет новое рабочее пространство для каждого этапа, что, в свою очередь, требует, чтобы я запихнул и разблокировал. Это бесполезно и дает дополнительные проблемы на параллельных этапах (2 и 3), потому что я не могу иметь код вне конструкции parallel. Я предполагаю, что параллельные шаги выполняются в одном и том же рабочем пространстве, поэтому удержание/нерест в обоих случаях приведет к неудачным результатам.

Вот контур моего файла Jenkins:

pipeline {
    agent {
        label 'build-slave'
    }
    stages {
        stage("Prepare build") {
            steps {
                // ...
            }
        }
        stage("Build") {
            steps {
                parallel(
                    frontend: {
                        // ...
                    },
                    backend: {
                        // ...
                    }
                )
            }
        }
        stage("Test") {
            steps {
                parallel(
                    jslint: {
                        // ...
                    },
                    phpcs: {
                        // ...
                    },
                )
            }
            post {
                // ...
            }
        }
        stage("Select deploy target") {
            steps {
                script {
                    // ... code that determines choiceParameterDefinition based on branch name ...
                    try {
                        timeout(time: 5, unit: 'MINUTES') {
                            deployEnvironment = input message: 'Deploy target', parameters: [choiceParameterDefinition]
                        }
                    } catch(ex) {
                        deployEnvironment = null
                    }
                }
            }
        }
        stage("Deploy") {
            when {
                expression {
                    return binding.variables.get("deployEnvironment")
                }
            }
            steps {
                // ...
            }
        }
    }
    post {
        // ...
    }
}

Мне что-то не хватает, или это просто невозможно в текущей версии?

Ответ 1

Настройка agent none на верхнем уровне, затем agent { label 'foo' } на каждом этапе, с agent none снова на этапе input, похоже, будет работать как ожидалось для меня.

то есть. Каждый этап, выполняющий некоторую работу, работает на одном и том же агенте, а этап input не использует исполнителя для любого агента.

pipeline {
    agent none
    stages {
        stage("Prepare build") {
            agent { label 'some-agent' }
            steps {
                echo "prepare: ${pwd()}"
            }
        }
        stage("Build") {
            agent { label 'some-agent' }
            steps {
                parallel(
                    frontend: {
                        echo "frontend: ${pwd()}"
                    },
                    backend: {
                        echo "backend: ${pwd()}"
                    }
                )
            }
        }
        stage("Test") {
            agent { label 'some-agent' }
            steps {
                parallel(
                    jslint: {
                        echo "jslint: ${pwd()}"
                    },
                    phpcs: {
                        echo "phpcs: ${pwd()}"
                    },
                )
            }
        }
        stage("Select deploy target") {
            agent none
            steps {
                input message: 'Deploy?'
            }
        }
        stage("Deploy") {
            agent { label 'some-agent' }
            steps {
                echo "deploy: ${pwd()}"
            }
        }
    }
}

Однако нет никакой гарантии, что использование одной и той же метки агента внутри Pipeline всегда будет работать в том же рабочем пространстве, например. как другая сборка той же работы, в то время как первая сборка ожидает на input.

Вам нужно будет использовать stash после шагов сборки. Как вы заметили, в настоящий момент это невозможно сделать с помощью parallel, поэтому вам придется дополнительно использовать блок script, чтобы написать фрагмент сценария для сценария для блокировки/блокировки после/перед параллелью шаги.

Ответ 2

Существует обходной путь для использования того же ведомого билда на других этапах. Вы можете установить переменную с именем узла и использовать ее в других.

то есть:

pipeline {
    agent none
    stages {
        stage('First Stage Gets Agent Dynamically') {
            agent {
                node {
                    label "some-agent"
                }
            }
            steps {
                echo "first stage running on ${NODE_NAME}"
                script {
                  BUILD_AGENT = NODE_NAME
                }
            }
        }
        stage('Second Stage Setting Node by Name') {
            agent {
                node {
                    label "${BUILD_AGENT}"
                }
            }
            steps {
                echo "Second stage using ${NODE_NAME}"
            }
        }
    }
}