Как продолжить прошлый этап неудачи в синтаксисе декларации Jenkins
Я хочу определить несколько этапов в синтаксисе декларативного конвейера Jenkins, который может провалиться после любого из них. Я не могу найти какие-либо существующие вопросы, которые являются истинными дубликатами, потому что все они предполагают или разрешают скриптовый синтаксис.
pipeline {
agent any
stages {
stage('stage 1') {
steps {
echo "I need to run every time"
}
}
stage('stage 2') {
steps {
echo "I need to run every time, even if stage 1 fails"
}
}
stage('stage 3') {
steps {
echo "Bonus points if the solution is robust enough to allow me to continue *or* be halted based on previous stage status"
}
}
}
}
Чтобы уточнить, я не ищу, как это сделать в сценарии синтаксиса. Я пытаюсь понять, действительно ли этот вид управления потоком поддерживается и формализован в декларативном синтаксисе. С этой целью я постараюсь точно определить, что я ищу:
Обязательно
- Нет попытки/улова. Я не хочу выходить в сценарий или "обматывать" свой декларативный конвейер в другой разделяемой библиотеке или сценарии.
- Нет
post step
shenanigans. Я хочу истинные несколько этапов, а не один этап с шагом post always
, который содержит всю мою другую логику.
Дополнительно
- Неудачная стадия должна быть признана неудачной; Я не хочу, чтобы неудачный этап отображался как зеленый, потому что он был "пропущен" или "продолжен".
- Строка с любой неудачной стадией должна быть отмечена как красный (или желтый, или ничего, что не зеленое).
Связанный, но не достаточный
Ответы
Ответ 1
Возможно, мне что-то не хватает, но идея декларативного, упрямого конвейера должна обеспечить покрытие самых простых случаев использования.
В тот момент, когда вам нужно что-то, о чем не относится, вам нужно прибегнуть к сценарию, связанного с сценарием, это относится только к "требованию" "декларативного конвейера": теперь это не произойдет.
Что касается ваших других "требований", они имеют мало смысла, поскольку вся идея заключается в том, чтобы обернуть уродство низкого уровня в разделяемые библиотеки, предоставляя пользователям такие конструкции, как:
mylib.failable_stages({
stages {
stage('stage 1') {
steps {
echo "I need to run every time"
}
}
stage('stage 2') {
steps {
echo "I need to run every time, even if stage 1 fails"
}
}
stage('stage 3') {
steps {
echo "Bonus points if the solution is robust enough to allow me to continue *or* be halted based on previous stage status"
}
}
}
})
Естественно, вам нужно было бы найти или реализовать такой класс mylib
, а failable_stages
получит замыкание и обернет его в различные фрагменты сантехники/шаблона.
Надеюсь, что это будет полезно.
Ответ 2
Я думаю, это зависит от того, насколько рабочие места зависят друг от друга. Исходя из вашего примера, я бы предположил, что
- Этап 1 не зависит от всех других этапов, потому что это первый
- Этап 2 не зависит от всех других этапов, поскольку этап 1 может сразу же завершиться неудачей, а этап 2 все равно потребуется для запуска
- этап 3 зависит от результата этапа 1 и этапа 2
Таким образом, соответствующий конвейер может быть
pipeline {
stages {
stage('Independent tasks') {
parallel {
stage('stage 1') {
steps {
sh 'exit 1' // failure
}
}
stage('stage 2') {
steps {
echo 'Happens even so stage 1 fails'
sh 'exit 0' // success
}
}
}
post { // 'stage 3'
failure {
echo "... at least one failed"
}
success {
echo "Success!"
}
}
}
stage ('stage 4') {
steps {
echo 'Happens only if all previous succeed'
}
}
}
}
Этап 1 и этап 2 всегда выполняются, этап 3 реагирует на их совокупный успех/неудачу.
Дополнительная мысль: эта концепция работает только "в конце" вашего конвейера. Если вам это нужно где-то посередине, и сборка должна продолжаться, вы можете переместить ее в собственное задание и использовать плагин build job
.
pipeline {
stages {
stage('Start own job for stage 1, 2, 3') {
steps {
build job: 'stageOneTwoThree', propagate: false, wait: true
}
}
stage ('stage 4') {
steps {
echo 'Happens always, because "propagate: false"'
}
}
}
Ответ 3
Теперь это возможно:
pipeline {
agent any
stages {
stage('1') {
steps {
sh 'exit 0'
}
}
stage('2') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh "exit 1"
}
}
}
stage('3') {
steps {
sh 'exit 0'
}
}
}
}
В приведенном выше примере все этапы будут выполнены, конвейер будет успешным, но этап 2 будет показан как неудачный:
![Pipeline Example]()
Как вы уже догадались, вы можете свободно выбирать buildResult
и stageResult
, если вы хотите, чтобы он был нестабильным или что-то еще. Вы даже можете потерпеть неудачу при сборке и продолжить выполнение конвейера.
Просто убедитесь, что ваш Jenkins обновлен, так как это довольно новая функция.
Ответ 4
Теперь это возможно:
pipeline {
agent any
stages {
stage('1') {
steps {
sh 'exit 0'
}
}
stage('2') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh "exit 1"
}
}
}
stage('3') {
steps {
sh 'exit 0'
}
}
}
}
В приведенном выше примере все этапы будут выполнены, конвейер будет успешным, но этап 2 будет показан как неудачный:
![Pipeline Example]()
Как вы уже догадались, вы можете свободно выбирать buildResult
и stageResult
, если вы хотите, чтобы он был нестабильным или что-то еще. Вы даже можете потерпеть неудачу при сборке и продолжить выполнение конвейера.
Просто убедитесь, что ваш Jenkins обновлен, так как это довольно новая функция.
РЕДАКТИРОВАТЬ: Это вопрос, для которого этот ответ был изначально написан. Это также правильный ответ на несколько других вопросов, поэтому я также разместил этот ответ там. Это правильное решение для множества похожих проблем. Я разработал другие мои ответы на их конкретные вопросы, чтобы прояснить это. Я только скопировал ответ, чтобы сэкономить время. Это не значит, что это не очень правильный ответ.