Как реализовать стадию Post-Build с использованием подключаемого модуля Jenkins Pipeline?

После прочтения Jenkins учебника, объясняющего Pipeline плагин, кажется, что плагин должен позволяют выполнить Пост-Построить. Однако документация довольно ограничена в отношении конкретных инструкций.

Например, мне интересно, как реализовать:

  • Запуск только в том случае, если сборка выполнена успешно
  • Запуск только в том случае, если сборка выполнена успешно или нестабильна.
  • Запуск независимо от результата сборки
  • Выполнить, только если сборка выполнена успешно

    stage 'build'
    ... build
    ... tests
    stage 'post-build'
    ...
    

    (Или добавьте -Dmaven.test.failure.ignore=false в MAVEN_OPTS)

  • Выполнить, только если сборка выполнена успешно или нестабильно

    stage 'build'
    ... build
    try {
        ... tests
    } catch {
        ...
    }
    stage 'post-build'
    ...
    

    (Или добавьте -Dmaven.test.failure.ignore=true в MAVEN_OPTS)

  • Выполнить независимо от результата сборки - можно ли это сделать с помощью try / catch / finally?

    try {
        stage 'build'
        ...
    } catch {
        ...
    } finally {
        stage 'post-build'
        ...
    }
    

(Я заметил, что окончательный статус сборки задан как SUCCESS, хотя некоторые этапы, т.е. "сборка", потерпели неудачу, поскольку они были установлены на основе последнего этапа. Означает ли это окончательный статус сборки нужно явно установить, т.е. currentBuild.result = 'UNSTABLE'?)

Ответ 1

Лучший способ - использовать post build action в конвейере script.

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

Jenkinsfile (декларативный трубопровод)

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                sh 'make check'
            }
        }
    }
    post {
        always {
            junit '**/target/*.xml'
        }
        failure {
            mail to: [email protected], subject: 'The Pipeline failed :('
        }
    }
}

Документация ниже https://jenkins.io/doc/book/pipeline/syntax/#post

Ответ 2

Если вы используете try/catch и хотите, чтобы сборка была помечена как нестабильная или неудачная, вы должны использовать currentBuild.result = 'UNSTABLE' и т.д. Я считаю, что некоторые плагины, такие как плагин JUnit Report, установят это для вас, если он находит неудачные тесты в результатах junit. Но в большинстве случаев вам нужно настроить себя, если вы ломаете ошибки.

Второй вариант, если вы не хотите продолжать, - это повторная ошибка.

stage 'build'
... build
try {
    ... tests
} catch(err) {
    //do something then re-throw error if needed.
    throw(err)
}
stage 'post-build'
...

Ответ 3

try-catch блоки могут быть настроены для обработки ошибок, как в реальном коде приложения.

Например:

try {
    node {
        sh 'sleep 20' // <<- can abort here
    }
} catch (Exception e) {
    println 'catch'
} finally {
    println 'finally'
}

node {
    println 'second'
}

try {
    node {
        sh 'sleep 20' // <<- can abort here again
    }
} catch (Exception e) {
    println 'catch'
} finally {
    println 'finally'
}

И вот пример вывода с двумя прерываниями.

Started by user me
Replayed #3
[Pipeline] node
Running on my-node in /var/lib/jenkins-slave/workspace/my-job
[Pipeline] {
[Pipeline] sh
[my-job] Running shell script
+ sleep 20

Aborted by me

Sending interrupt signal to process

/var/lib/jenkins-slave/workspace/[email protected]/durable-9e1a15e6/script.sh: line 2: 10411 Terminated              sleep 20
[Pipeline] }
[Pipeline] // node
[Pipeline] echo
catch
[Pipeline] echo
finally
[Pipeline] node
Running on my-node in /var/lib/jenkins-slave/workspace/my-job
[Pipeline] {
[Pipeline] echo
second
[Pipeline] }
[Pipeline] // node
[Pipeline] node
Running on my-node in /var/lib/jenkins-slave/workspace/my-job
[Pipeline] {
[Pipeline] sh
[my-job] Running shell script
+ sleep 20

Aborted by me

Sending interrupt signal to process
/var/lib/jenkins-slave/workspace/[email protected]/durable-d711100c/script.sh: line 2: 10416 Terminated              sleep 20
[Pipeline] }
[Pipeline] // node
[Pipeline] echo
catch
[Pipeline] echo
finally
[Pipeline] End of Pipeline
Finished: ABORTED

Конечно, это работает для любых исключений, происходящих во время выполнения.

Ответ 4

FWIW, если вы используете скриптовые конвейеры, а не декларативные, вы должны использовать блок try/catch/finally как предложено в других ответах. В блоке finally, если вы хотите имитировать то, что делает декларативный конвейер, вы можете либо поместить следующее непосредственно в блок, либо сделать его функцией и вызвать эту функцию из вашего блока finally:

def currResult = currentBuild.result ?: 'SUCCESS'
def prevResult = currentBuild.previousBuild?.result ?: 'NOT_BUILT'

// Identify current result
boolean isAborted = (currResult == 'ABORTED')
boolean isFailure = (currResult == 'FAILURE')
boolean isSuccess = (currResult == 'SUCCESS')
boolean isUnstable = (currResult == 'UNSTABLE')

boolean isChanged = (currResult != prevResult)
boolean isFixed = isChanged && isSuccess && (prevResult != 'ABORTED') && (prevResult != 'NOT_BUILT')
boolean isRegression = isChanged && currentBuild.resultIsWorseOrEqualTo(prevResult)

onAlways()
if (isChanged) {
    onChanged()
    if (isFixed) {
        onFixed()
    } else if (isRegression) {
        onRegression()
    }
}
if (isSuccess) {
    onSuccess()
} else {
    if (isAborted) {
        onAborted()
    }
    onUnsuccessful()
    if (isFailure) {
        onFailure()
    }
    if (isUnstable) {
        onUnstable()
    }
}
onCleanup()

Различные onXYZ() вызовы функции, которые вы определили бы, чтобы справиться с этим особым условием вместо того, чтобы использовать более хороший синтаксис декларативных post блоков.