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


132

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


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

Ответы:


211

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

command || exit 0

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

command || true


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. Он может выполнять вывод консоли, сопоставлять шаблон (ваше эхо) и отмечать сборку как нестабильную.


27

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

set +e
git commit -m "Bla."
set -e

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

8

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


похоже, это не работает для команды «выполнить 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.



6

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


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

4

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

set +e commands true

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


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

3

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

false
true

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

set +e
false
true

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

set +e
false

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


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, но тогда вы пропустите вывод своей команды.


0

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

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

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.