не сбой сборки jenkins, если выполнить оболочку не удается

132

В процессе сборки я запускаю коммит git как шаг оболочки выполнения. Однако, если в рабочей области нет изменений, Jenkins не выполняет сборку. Это потому, что git возвращает код ошибки, когда нет изменений для фиксации. Я бы хотел либо прервать сборку, либо просто отметить ее как нестабильную, если это так. Любые идеи?

Бен
источник
Проверить, есть ли что-нибудь для фиксации, и делать коммит только в этих случаях? stackoverflow.com/questions/5139290/…
Андерс Линдал

Ответы:

211

Чтобы остановить дальнейшее выполнение при сбое команды :

command || exit 0

Чтобы продолжить выполнение при сбое команды :

command || true

Quolonel вопросы
источник
12
В || exit 0первом случае вам не нужно , если commandвернет false, выполнение остановится. Тем не менее, второй вариант очень полезен!
Нир Альфаси
20
@alfasin Вы не понимаете проблемы. OP не хочет, чтобы сборка Jenkins завершилась неудачей; следовательно, мы должны это сделать, exit 0потому что любой ненулевой код выхода приведет к сбою сборки.
Quolonel Questions
1
Понятно, в этом случае я бы изменил формулировку с: «Чтобы остановить дальнейшее выполнение при сбое команды:» на: «Чтобы остановить дальнейшее выполнение при сбое команды и пометить задание Дженкинса как успешное:».
Нир Альфаси
1
@alfasin Хотя я согласен с тем, что резкое замечание Quolonel Questions было непрофессиональным, он был прав в том, что сказал. «exit 0» НЕ пометит задание как успешное. Он просто пометит текущий этап сборки как успешный. Задание все равно может завершиться ошибкой на одном из следующих шагов сборки.
Ноамик
1
Спасибо, это сработало! Это особенно полезно для функции плагина «Выполнить оболочку на удаленном хосте с использованием ssh», поскольку вы не можете использовать / bin / bash + e, чтобы не сбой при ошибке. Мне также нравится идея, что я могу выбирать, какие команды не приводят к сбою сборки.
leeman24
80

Jenkins выполняет шаги сборки оболочки, используя /bin/sh -xeпо умолчанию. -xозначает вывод каждой выполненной команды. -eозначает выход с ошибкой, если какая-либо из команд в сценарии не удалась.

Итак, я думаю, что в вашем случае произошло то, что вы вышли из команды git с 1, и из-за параметра по умолчанию -eоболочка выбирает код выхода, отличный от 0, игнорирует остальную часть скрипта и отмечает шаг как сбой. Мы можем подтвердить это, если вы разместите здесь свой скрипт этапа сборки.

Если это так, вы можете попробовать поставить #!/bin/shтак, чтобы сценарий выполнялся без опции; или выполните set +eили что-нибудь подобное поверх этапа сборки, чтобы переопределить это поведение.


Отредактировано: еще одна вещь, на которую следует обратить внимание, заключается в том, что если последняя команда в вашем сценарии оболочки возвращает код , отличный от 0 , весь этап сборки по-прежнему будет отмечен как сбой даже при этой настройке. В этом случае вы можете просто поставить echoкоманду в конце, чтобы этого избежать.

Другой связанный вопрос

Сявэй Чжан
источник
41

Если нечего нажимать, git возвращает статус выхода 1. Выполнить шаг сборки оболочки, соответственно, помечается как неудачный. Вы можете использовать оператор OR || (двойная труба).

git commit -m 'some messasge' || echo 'Commit failed. There is probably nothing to commit.'

Это означает, что выполнить второй аргумент, если первый не удалось (возвращенный статус выхода> 0). Вторая команда всегда возвращает 0. Когда нечего нажимать (статус выхода 1 -> выполнить вторую команду), echo вернет 0, и этап сборки продолжится.

Чтобы пометить сборку как нестабильную, вы можете использовать шаг после сборки Jenkins Text Finder. Он может выполнять вывод консоли, сопоставлять шаблон (ваше эхо) и отмечать сборку как нестабильную.

ecervena
источник
27

Есть еще один простой способ сказать Дженкинсу не терпеть неудач. Вы можете изолировать свой коммит на этапе сборки и настроить оболочку, чтобы она не выходила из строя:

set +e
git commit -m "Bla."
set -e
joecks
источник
2
Обязательно добавьте set -eпосле команды, которую вы хотите запустить, независимо от кода выхода. В противном случае вы можете выполнить команды, которые не собирались выполнять. Я хотел обработать ошибку сам, поэтому сделал что-то вроде: `set + e commit -m" bla "EXIT_CODE =" $ {?} "Set -e # handle exit code
logic`
8

Дженкинс определяет успех / неудачу шага по возвращаемому значению шага. В случае оболочки это должно быть возвращение последнего значения. Для оболочек Windows CMD и (POSIX) Bash вы должны иметь возможность установить возвращаемое значение вручную, используя exit 0последнюю команду.

jwernerny
источник
похоже, это не работает для команды «выполнить windows bat», в которой есть 2 строки: git commit -m "message" exit 0
Бен
@Ben Я использую exit 0команду «выполнить пакетную команду Windows» в нескольких сборках в моей установке Windows Jenkins, и она работает должным образом. Что-то еще должно происходить. Не могли бы вы опубликовать соответствующую часть журнала консоли?
jwernerny
вы используете его с git commit -m "blah" на первом этапе? Я попытался создать сценарий bat на машине вручную и поставил эхо и выход 0 после команды git. Ни одна из других команд не запускается, когда нечего фиксировать ...
Бен
См. Ответ от @xiawei. По умолчанию Jenkins запускает оболочку, в #!/bin/sh -xvрезультате которой сценарий останавливается при обнаружении какой-либо ошибки.
Стивен Легко Развлекающийся
8

Я смог заставить это работать, используя ответ, найденный здесь:

Как git ничего не зафиксировать без ошибки?

git diff --quiet --exit-code --cached || git commit -m 'bla'
Бен
источник
1
Что делает приведенное выше: «Выполните git diffкоманду, а если она не удалась, выполните git commitкоманду. В основном, она выполняет фиксацию только в том случае, если git diffнайдено что-то для фиксации. Однако ответ @jwernerny был правильным, и вы можете добавить его exit 0в качестве последнего оператора. к любому сценарию, чтобы Дженкинс считал это успехом. Я могу придумать один сценарий, в котором это не удалось бы, если бы вы выполняли этап оболочки Linux, но в пакетном режиме это всегда должно работать.
Slav
@Ben Jenkins выполняет шаги сборки оболочки, используя /bin/sh -xeпо умолчанию, как указано здесь (посередине). Таким образом, вы можете попытаться поставить #!/bin/bashили выполнить set +eповерх этапа сборки, чтобы переопределить это поведение, которое продолжит оставшуюся часть шага, даже если одна команда внутри выхода с кодом,
отличным от
8

По (более общему) вопросу в заголовке - чтобы предотвратить сбой Jenkins, вы можете запретить ему видеть код выхода 1. Пример для ping:

bash -c "ping 1.2.3.9999 -c 1; exit 0"

И теперь вы можете, например, получить вывод ping:

output=`bash -c "ping 1.2.3.9999 -c 1; exit 0"`

Конечно, вместо ping ...Вы можете использовать любую команду (ы), в том числе git commit.

Nux
источник
6

Вы можете использовать плагин Text-finder . Это позволит вам проверить консоль вывода на наличие выражения по вашему выбору, а затем пометить сборку как Unstable.

jphuynh
источник
это выглядело многообещающе, но по какой-то причине сборка продолжалась неудачно.
Бен
4

Для нескольких команд оболочки я игнорирую сбои, добавляя:

set +e commands true

введите описание изображения здесь

Megha
источник
Я вообще не рекомендую расстраивать -e. Если вы хотите игнорировать возвращаемое значение какой-либо конкретной команды, вы можете добавить «|| true» или что-то более значимое, возвращающее истину, например: stop-service.sh || Служба эхо уже не работает
Рауль Салинас-Монтеагудо
3

Если вы поместите эти команды в блок оболочки:

false
true

ваша сборка будет отмечена как неудачная (по крайней мере, 1 ненулевой код выхода), поэтому вы можете добавить (set + e), чтобы игнорировать ее:

set +e
false
true

не подведет. Однако это не удастся даже с (set + e) ​​на месте:

set +e
false

потому что последняя команда оболочки должна завершиться с 0.

chenchuk
источник
2

Следующее работает для mercurial, фиксируя только при наличии изменений. Таким образом, сборка терпит неудачу только при неудачной фиксации.

hg id | grep "+" || exit 0
hg commit -m "scheduled commit"
Шон Леброн
источник
0

Еще один ответ с некоторыми советами, может быть кому-то полезен:

не забудьте разделить свои команды следующим правилом :

command1 && command2 - означает, что command2 будет выполнена, только если command1 успешно

command1 ; command2 - означает, что команда 2 будет выполнена несмотря на результат command1

например:

String run_tests = sh(script: "set +e && cd ~/development/tests/ && gmake test ;set -e;echo 0 ", returnStdout: true).trim()
println run_tests 

будет успешно выполнена с set -eи echo 0команды , если gmake testне удалось (тесты не удалось), а следующий код отрезала:

String run_tests = sh(script: "set +e && cd ~/development/tests/ && gmake test && set -e && echo 0 ", returnStdout: true).trim()
println run_tests 

немного неверно, и команды set -eи echo 0in && gmake test && set -e && echo 0будут пропущены вместе с println run_testsоператором, потому что failed gmake testпрервет сборку jenkins. В качестве обходного пути вы можете переключиться на returnStatus:true, но тогда вы пропустите вывод своей команды.

Sysanin
источник
0

Это правильный ответ , но он не указывает || exit 0или || trueвходит в команду оболочки . Вот более полный пример:

sh "adb uninstall com.example.app || true"

Вышеуказанное будет работать, но следующее не удастся:

sh "adb uninstall com.example.app" || true

Возможно, это очевидно для других, но я потратил много времени, прежде чем понял это.

Большой МакЛарджОгромный
источник