Как сравнить строковые переменные в условии Jenkins `when`

Я определяю декларативный конвейер Jenkins и с трудом настраиваю шаг, чтобы он не выполнялся, если две строки равны.

Я пробовал несколько вещей, но сравнение строк не работает.

Вот мое текущее состояние:

stages {
    stage('Check if image has changed') {
        steps {
            script {
                OLD_DIGEST = sh(returnStdout: true, script: "podman manifest inspect registry/myimage:11 2>/dev/null | jq .config.digest").trim()
                NEW_DIGEST = sh(returnStdout: true, script: "podman inspect --format='sha256:{{.Id}}' myimage:11-tmp").trim()
            }
            sh "echo previous digest:${OLD_DIGEST}, new digest:${NEW_DIGEST}"
        }
    }
    stage('Release') {
        when {
            allOf {
                expression { env.RELEASE != null && env.RELEASE == "true" }
                expression { env.OLD_DIGEST != env.NEW_DIGEST }
            }
        }
        steps {
            sh "echo Releasing image..."
            sh "podman image push myimage:11-tmp registry/myimage:11.${DATE_TIME}"
            sh "podman image push myimage:11-tmp registry/myimage:11"
        }
    }
}

В частности, проблемы заключаются в when:

allOf {
    expression { env.RELEASE != null && env.RELEASE == "true" }
    expression { env.OLD_DIGEST != env.NEW_DIGEST }
}

Первое выражение работает нормально, но я не могу заставить второе работать: даже если OLD_DIGEST и NEW_DIGEST разные, шаг пропускается.

Пример вывода:

previous digest:sha256:736fd651afdffad2ee48a55a3fbab8de85552f183602d5bfedf0e74f90690e32, new digest:sha256:9003077f080f905d9b1a960b7cf933f04756df9560663196b65425beaf21203d
...
Stage "Release" skipped due to when conditional

Я также пробовал expression { OLD_DIGEST != NEW_DIGEST } (удаление env.), но теперь результат противоположный: даже если обе строки равны, шаг НЕ пропускается.

Выход в этом случае:

previous digest:sha256:8d966d43262b818073ea23127dedb61a43963a7fafc5cffdca85141bb4aada57, new digest:sha256:8d966d43262b818073ea23127dedb61a43963a7fafc5cffdca85141bb4aada57
...
Releasing image...

Мне интересно, заключается ли проблема в expression или allOf в какой-то момент.

expression { OLD_DIGEST != NEW_DIGEST } — правильный подход, префикс .env актуален, если вы также использовали его для определения: env. OLD_DIGEST = sh(.... Вы уверены, что ваше второе условие на RELEASE работает должным образом? поскольку оба они должны быть оценены как true, чтобы этап запустился.
Noam Helmer 17.02.2023 16:48

@NoamHelmer да, почти уверен, что первое условие работает нормально, как и в случае с expression { OLD_DIGEST != NEW_DIGEST } Я всегда вхожу в шаг. Даже если OLD_DIGEST равно NEW_DIGEST в этом случае не должно.

Gaël J 17.02.2023 17:02

Я обновил пост с выходом в случае expression { OLD_DIGEST != NEW_DIGEST }

Gaël J 17.02.2023 18:45

@NoamHelmer имеет правильное решение в комментарии, поскольку ни одна из них не является переменной среды конвейера и, следовательно, не назначается членам в объекте env. Что касается другой проблемы: это похоже на синтаксис Groovy в expression и, следовательно, синтаксически требуется явное return: jenkins.io/doc/book/pipeline/syntax/#when.

Matt Schuchard 17.02.2023 19:35
"DevOps: Jenkins & AWS Series, часть 5: Установка Gradle на Ubuntu 22.04
"DevOps: Jenkins & AWS Series, часть 5: Установка Gradle на Ubuntu 22.04
В этой статье блога мы проведем вас через процесс установки Gradle на Ubuntu 22.04, интеграции его с Jenkins и создания задания Gradle. Мы...
0
4
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Согласно моим тестам в последней версии 2023 года переменные env инициализируются на любом этапе, поэтому предыдущие значения переопределяются.

Примечание. Внутри when переменные env имеют значения по умолчанию, игнорируя ожидаемые значения, заданные на предыдущем этапе. После этого на шагах есть ожидаемые значения (обновленные на предыдущем этапе)

Если вы используете глобальные переменные вместо переменных env, это работает. Я имитирую ваш вывод podman с помощью эха.

def OLD_DIGEST
def NEW_DIGEST

pipeline {
    agent any
    environment {
      RELEASE = "true"
    } 
    stages {
        stage('Check if image has changed') {
            steps {
                script {
                    OLD_DIGEST = sh(returnStdout: true, script: "echo '1'").trim()
                    NEW_DIGEST = sh(returnStdout: true, script: "echo '1'").trim()
                }
                sh "echo previous digest:${OLD_DIGEST}, new digest:${NEW_DIGEST}"
            }
        }
        stage('Release') {
            when {
                allOf {
                    expression { env.RELEASE != null && env.RELEASE == "true" }
                    expression { OLD_DIGEST != NEW_DIGEST }
                }
            }
            steps {
                sh "echo Releasing image..."
            }
        }
    }
}

когда OLD_DIGEST = 1 && NEW_DIGEST = 1 этап пропускается

если есть разные, этап выполняется

Итак, ваш ответ работает в вашем случае, но как только я использую свои команды оболочки, он больше не работает. Я предполагаю, что где-то в моих строках есть специальный символ. Буду устранять неполадки еще.

Gaël J 20.02.2023 10:32

Глупая ошибка с моей стороны, одна из строк на самом деле была "xxx", когда другая была xxx (без кавычек). Каким-то образом вывод Дженкинса не отображает кавычки.

Gaël J 20.02.2023 11:24

Это работает и без def.

Gaël J 20.02.2023 11:25
Ответ принят как подходящий

Основной причиной моей проблемы был вывод двух моих строк для сравнения, которые действительно отличались: одна была "xxx", а другая была xxx, но вывод Дженкинса не показывает двойные кавычки.


Правильное сравнение Дженкинса, как указано в комментариях, это expression { OLD_DIGEST != NEW_DIGEST } (без env.).

Другие вопросы по теме