nie zawieść kompilacji jenkinsa, jeśli powłoka wykonania zawiedzie

132

W ramach procesu kompilacji uruchamiam polecenie git commit jako krok wykonywania powłoki. Jeśli jednak nie ma zmian w obszarze roboczym, Jenkins kończy się niepowodzeniem kompilacji. Dzieje się tak, ponieważ git zwraca kod błędu, gdy nie ma żadnych zmian do zatwierdzenia. Chciałbym albo przerwać kompilację, albo po prostu oznaczyć ją jako niestabilną, jeśli tak jest. Jakieś pomysły?

Ben
źródło
Sprawdź, czy jest coś do popełnienia i tylko w takich przypadkach? stackoverflow.com/questions/5139290/…
Anders Lindahl

Odpowiedzi:

210

Aby zatrzymać dalsze wykonywanie w przypadku niepowodzenia polecenia :

command || exit 0

Aby kontynuować wykonywanie, gdy polecenie nie powiedzie się:

command || true

Pytania Quolonel
źródło
12
Nie potrzebujesz || exit 0w pierwszym przypadku, jeśli commandzwróci false, wykonanie zostanie zatrzymane. To powiedziawszy, druga opcja jest bardzo pomocna!
Nir Alfasi
20
@alfasin Nie rozumiesz problemu. OP nie chce, aby kompilacja Jenkinsa zakończyła się niepowodzeniem; ergo musimy, exit 0ponieważ każdy niezerowy kod zakończenia zakończy się niepowodzeniem podczas kompilacji.
Pytania dotyczące Quolonel
1
Widzę, w takim przypadku zmieniłbym sformułowanie z: „Aby zatrzymać dalsze wykonywanie, gdy polecenie się nie powiedzie:” na: „Aby zatrzymać dalsze wykonywanie, gdy polecenie się nie powiedzie i oznaczyć zadanie Jenkinsa jako udane:”.
Nir Alfasi
1
@alfasin Chociaż zgadzam się, że zgryźliwa uwaga Quolonela Pytania była nieprofesjonalna, miał rację w tym, co powiedział. „exit 0” NIE oznacza zadania jako pomyślnego. Po prostu oznaczy bieżący krok jako pomyślny. Zadanie może nadal zakończyć się niepowodzeniem na jednym z następnych kroków kompilacji.
noamik
1
Dzięki, że zadziałało! Jest to szczególnie przydatne dla funkcji wtyczki "Wykonaj powłokę na zdalnym hoście używając ssh", ponieważ nie możesz użyć / bin / bash + e, aby nie zawieść w przypadku błędu. Podoba mi się również pomysł, że mogę wybrać, które polecenia nie zawiodą kompilacji.
leeman24,
80

Jenkins /bin/sh -xedomyślnie wykonuje kroki budowania powłoki przy użyciu . -xoznacza wydrukowanie każdego wykonanego polecenia. -eoznacza wyjście z niepowodzeniem, jeśli któraś z komend w skrypcie nie powiodła się.

Więc myślę, że to, co wydarzyło się w twoim przypadku, to wyjście polecenia git z 1, a z powodu domyślnego -eparametru powłoka pobiera kod wyjścia inny niż 0, ignoruje resztę skryptu i oznacza krok jako niepowodzenie. Możemy to potwierdzić, jeśli możesz opublikować tutaj skrypt kroku kompilacji.

W takim przypadku możesz spróbować ustawić #!/bin/shtak, aby skrypt był wykonywany bez opcji; lub wykonaj set +elub cokolwiek podobnego w górnej części etapu kompilacji, aby zastąpić to zachowanie.


Edytowano: Inną rzeczą, na którą należy zwrócić uwagę, jest to, że ostatnie polecenie w skrypcie powłoki zwraca kod inny niż 0 , cały krok kompilacji nadal będzie oznaczony jako niepowodzenie nawet przy tej konfiguracji. W takim przypadku możesz po prostu umieścić echopolecenie na końcu, aby tego uniknąć.

Kolejne powiązane pytanie

Xiawei Zhang
źródło
41

Jeśli nie ma nic do przekazania, git zwraca kod zakończenia 1. Wykonaj krok budowania powłoki jest odpowiednio oznaczany jako nieudany. Możesz użyć instrukcji OR || (podwójna rura).

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

Oznacza to, że wykonuje drugi argument, jeśli pierwszy się nie powiódł (zwrócony kod zakończenia> 0). Druga komenda zawsze zwraca 0. Gdy nie ma nic do wciśnięcia (status wyjścia 1 -> wykonanie drugiej komendy) echo zwróci 0 i krok budowy będzie kontynuowany.

Aby oznaczyć kompilację jako niestabilną, możesz użyć kroku po kompilacji Jenkins Text Finder. Może przejść przez wyjście konsoli, dopasować wzorzec (twoje echo) i oznaczyć kompilację jako niestabilną.

ecervena
źródło
27

Istnieje inny płynny sposób, aby powiedzieć Jenkinsowi, aby nie zawiódł. Możesz odizolować swoje zatwierdzenie w kroku budowania i ustawić powłokę tak, aby nie zawodziła:

set +e
git commit -m "Bla."
set -e
joecks
źródło
2
Pamiętaj, aby dodać set -epo poleceniu, które chcesz uruchomić niezależnie od kodu zakończenia. W przeciwnym razie możesz zakończyć wykonywanie poleceń, których nie zamierzasz. Chciałem sam obsłużyć ten błąd, więc zrobiłem coś takiego: `set + e commit -m" bla "EXIT_CODE =" $ {?} "Set -e # obsługa logiki kodu
wyjścia`
8

Jenkins określa powodzenie / niepowodzenie kroku na podstawie wartości zwracanej kroku. W przypadku powłoki powinien to być zwrot ostatniej wartości. Zarówno w przypadku powłok Windows CMD, jak i (POSIX) Bash powinno być możliwe ustawienie wartości zwracanej ręcznie, używając exit 0jako ostatniego polecenia.

jwernerny
źródło
wydaje się, że to nie działa dla 'execute windows bat', który ma 2 linie: git commit -m "message" exit 0
Ben
@Ben używam exit 0z "wykonaj polecenie wsadowe systemu Windows" w wielu kompilacjach na mojej instalacji Windows Jenkins i działa zgodnie z oczekiwaniami. Coś innego musi się dziać. Czy możesz opublikować odpowiednią część dziennika konsoli?
jwernerny
czy używasz go z git commit -m "blah" w swoim pierwszym kroku? Próbowałem ręcznie utworzyć skrypt nietoperza na komputerze i wstawiłem echo i wyjście 0 po poleceniu git. Żadne z pozostałych poleceń nie jest uruchamiane, gdy nie ma nic do popełnienia ...
Ben
Zobacz odpowiedź od @xiawei. Domyślne zachowanie Jenkinsa #!/bin/sh -xvpolega na wykonaniu powłoki, która powoduje zatrzymanie skryptu w przypadku napotkania jakiegokolwiek błędu.
Steven the Easily Amused
8

Udało mi się to uruchomić, korzystając z odpowiedzi znalezionej tutaj:

Jak nic nie popełnić bez błędu?

git diff --quiet --exit-code --cached || git commit -m 'bla'
Ben
źródło
1
To, co robi powyżej, to: "Wykonaj git diffpolecenie, a jeśli to się nie powiedzie, wykonaj git commitpolecenie. Zasadniczo wykonuje zatwierdzenie tylko wtedy, gdy git diffznaleziono coś do zatwierdzenia. Jednak @jwernerny odpowiedź była poprawna, że ​​powinieneś być w stanie dodać exit 0jako ostatnią instrukcję do dowolnego skryptu, aby Jenkins potraktował to jako sukces. Przychodzi mi do głowy jeden scenariusz, w którym to by się nie udało, gdybyś wykonywał krok powłoki Linuksa, ale w Batch to powinno zawsze działać.
Slav
@Ben Jenkins domyślnie wykonuje kroki kompilacji powłoki, /bin/sh -xejak wspomniano tutaj (w środku). Możesz więc spróbować umieścić #!/bin/bashlub wykonać set +ekrok kompilacji, aby nadpisać to zachowanie, które będzie kontynuowało resztę kroku, nawet jedno polecenie wewnątrz wyjścia z kodem innym niż 0
Xiawei Zhang
8

Na (bardziej ogólne) pytanie w tytule - aby zapobiec niepowodzeniu Jenkinsa, możesz zapobiec wyświetlaniu kodu zakończenia 1. Przykład dla polecenia ping:

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

A teraz możesz np. Uzyskać wynik polecenia ping:

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

Oczywiście zamiast ping ...Możesz użyć dowolnego polecenia (w tym git commit.

Nux
źródło
6

Możesz użyć wtyczki Text-Finder . Pozwoli ci to sprawdzić konsolę wyjściową pod kątem wybranego wyrażenia, a następnie oznaczyć kompilację jako Unstable.

jphuynh
źródło
wyglądało to obiecująco, ale z jakiegoś powodu wciąż zawodziło w budowie.
Ben
4

W przypadku wielu poleceń powłoki ignoruję błędy, dodając:

set +e commands true

wprowadź opis obrazu tutaj

Megha
źródło
Generalnie odradzam rozbrajanie -e. Jeśli chcesz zignorować wartość zwracaną przez określone polecenie, możesz dodać „|| true” lub coś bardziej znaczącego zwracającego true, na przykład: stop-service.sh || echo Serwis już nie działał
Raúl Salinas-Monteagudo
3

Jeśli umieścisz te polecenia w bloku powłoki:

false
true

Twoja kompilacja zostanie oznaczona jako niepowodzenie (co najmniej 1 niezerowy kod zakończenia), więc możesz dodać (set + e), aby ją zignorować:

set +e
false
true

nie zawiedzie. Jednak to się nie powiedzie nawet z (set + e) ​​na miejscu:

set +e
false

ponieważ ostatnie polecenie powłoki musi zakończyć się z wartością 0.

chenchuk
źródło
2

Poniższe działa dla Mercurial tylko wtedy, gdy są zmiany. Tak więc kompilacja kończy się niepowodzeniem tylko wtedy, gdy zatwierdzanie nie powiedzie się.

hg id | grep "+" || exit 0
hg commit -m "scheduled commit"
Shaun Lebron
źródło
0

Kolejna odpowiedź z kilkoma wskazówkami może być pomocna dla kogoś:

pamiętaj, aby oddzielić polecenia następującą regułą :

polecenie1 && polecenie2 - oznacza, że ​​polecenie2 zostanie wykonane tylko w przypadku powodzenia polecenia1

polecenie1 ; polecenie2 - oznacza, że ​​polecenie 2 zostanie wykonane pomimo wyniku polecenia 1

na przykład:

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

zostanie pomyślnie wykonany z poleceniami set -ei echo 0, jeśli się gmake testnie powiodły (testy nie powiodły się), podczas gdy następujący kod zostanie wycięty:

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

trochę źle, a polecenia set -ei echo 0in && gmake test && set -e && echo 0zostaną pominięte wraz z println run_testsinstrukcją, ponieważ failed gmake testspowoduje przerwanie kompilacji Jenkinsa. Aby obejść ten problem, możesz przełączyć się returnStatus:true, ale wtedy przegapisz dane wyjściowe polecenia.

Sysanin
źródło
0

Ta odpowiedź jest poprawna, ale nie określa || exit 0lub nie || truejest umieszczana w poleceniu powłoki . Oto bardziej kompletny przykład:

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

Powyższe zadziała, ale poniższe zawiodą:

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

Być może dla innych jest to oczywiste, ale zmarnowałem dużo czasu, zanim zdałem sobie z tego sprawę.

Big McLargeHuge
źródło