ne pas échouer la construction de jenkins si l'exécution du shell échoue

132

Dans le cadre de mon processus de construction, j'exécute un commit git en tant qu'étape d'exécution du shell. Cependant, s'il n'y a aucune modification dans l'espace de travail, Jenkins échoue la construction. C'est parce que git renvoie un code d'erreur lorsqu'il n'y a pas de modifications à valider. Je voudrais soit abandonner la construction, soit simplement la marquer comme instable si tel est le cas. Des idées?

Ben
la source
Vérifier s'il y a quelque chose à valider, et ne valider que dans ces cas? stackoverflow.com/questions/5139290/…
Anders Lindahl

Réponses:

210

Pour arrêter la poursuite de l'exécution lorsque la commande échoue:

command || exit 0

Pour continuer l'exécution lorsque la commande échoue:

command || true

Questions sur Quolonel
la source
12
Vous n'avez pas besoin du || exit 0dans le premier cas, si commandretourne false, l'exécution s'arrêtera. Cela dit, la deuxième option est très utile!
Nir Alfasi
20
@alfasin Vous ne comprenez pas le problème. OP ne veut pas que la construction de Jenkins échoue; ergo, nous le devons exit 0car tout code de sortie non nul échouera la construction.
Questions Quolonel
1
Je vois, dans ce cas, je changerais le libellé de: "Pour arrêter la poursuite de l'exécution lorsque la commande échoue:" à: "Pour arrêter la poursuite de l'exécution lorsque la commande échoue et marquer le travail Jenkins comme réussi:".
Nir Alfasi
1
@alfasin Bien que je convienne que la remarque vive de Quolonel Questions n'était pas professionnelle, il avait raison dans ce qu'il a dit. "exit 0" ne marquera PAS le travail comme réussi. Cela marquera simplement la réussite de l'étape de construction actuelle. Le travail peut toujours échouer lors de l'une des étapes de génération suivantes.
noamik
1
Merci cela a fonctionné! Ceci est particulièrement utile pour la fonction du plugin "Exécuter le shell sur un hôte distant en utilisant ssh" puisque vous ne pouvez pas utiliser / bin / bash + e pour ne pas échouer en cas d'erreur. J'aime aussi l'idée que j'ai de choisir les commandes qui n'échouent pas à la construction.
leeman24
80

Jenkins exécute les étapes de construction du shell en utilisant /bin/sh -xepar défaut. -xsignifie imprimer chaque commande exécutée.-esignifie quitter avec un échec si l'une des commandes du script a échoué.

Donc, je pense que ce qui s'est passé dans votre cas est votre sortie de commande git avec 1, et à cause du -eparamètre par défaut , le shell récupère le code de sortie non-0, ignore le reste du script et marque l'étape comme un échec. Nous pouvons le confirmer si vous pouvez publier votre script d'étape de construction ici.

Si c'est le cas, vous pouvez essayer de mettre de #!/bin/shsorte que le script soit exécuté sans option; ou faites une set +eou quelque chose de similaire en plus de l'étape de génération pour remplacer ce comportement.


Modifié: Une autre chose à noter est que, si la dernière commande de votre script shell renvoie du code non-0 , toute l'étape de construction sera toujours marquée comme échec même avec cette configuration. Dans ce cas, vous pouvez simplement mettre une echocommande à la fin pour éviter cela.

Une autre question connexe

Xiawei Zhang
la source
41

S'il n'y a rien à pousser, git renvoie l'état de sortie 1. L'étape d'exécution de la construction du shell est marquée comme ayant échoué respectivement. Vous pouvez utiliser l'instruction OR || (double tuyau).

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

Cela signifie, exécutez le deuxième argument en cas d'échec du premier (état de sortie renvoyé> 0). La deuxième commande renvoie toujours 0. Lorsqu'il n'y a rien à pousser (état de sortie 1 -> exécution de la deuxième commande), l'écho renverra 0 et l'étape de construction continue.

Pour marquer la construction comme instable, vous pouvez utiliser l'étape de post-construction Jenkins Text Finder. Il peut passer par la sortie de la console, faire correspondre le modèle (votre écho) et marquer la construction comme instable.

ecervena
la source
27

Il existe un autre moyen simple de dire à Jenkins de ne pas échouer. Vous pouvez isoler votre validation dans une étape de construction et définir le shell pour ne pas échouer:

set +e
git commit -m "Bla."
set -e
joecks
la source
2
Assurez-vous d'ajouter set -eaprès la commande que vous souhaitez exécuter quel que soit le code de sortie. Sinon, vous risquez d'exécuter des commandes que vous n'avez pas l'intention de faire. Je voulais gérer l'erreur moi-même, alors j'ai fait quelque chose comme: `set + e commit -m" bla "EXIT_CODE =" $ {?} "Set -e # gérer la logique du code de
sortie`
8

Jenkins détermine le succès / l'échec d'une étape par la valeur de retour de l'étape. Dans le cas d'un shell, ce devrait être le retour de la dernière valeur. Pour les shells Windows CMD et (POSIX) Bash, vous devez pouvoir définir la valeur de retour manuellement en utilisant exit 0comme dernière commande.

jwernerny
la source
cela ne semble pas fonctionner pour un 'exécuter windows bat' qui a 2 lignes: git commit -m "message" exit 0
Ben
@Ben J'utilise exit 0avec "exécuter la commande batch windows" dans plusieurs versions sur mon installation Windows Jenkins, et cela fonctionne comme prévu. Quelque chose d'autre doit se passer. Pourriez-vous publier la partie pertinente du journal de la console?
jwernerny
l'utilisez-vous avec git commit -m "blah" dans votre première étape? J'ai essayé de créer manuellement un script bat sur la machine et de mettre un écho et une sortie 0 après la commande git. Aucune des autres commandes n'est exécutée lorsqu'il n'y a rien à valider ...
Ben
Voir la réponse de @xiawei. Le comportement par défaut de Jenkins #!/bin/sh -xvconsiste à exécuter un shell qui entraîne l'arrêt du script si une erreur est rencontrée.
Steven the Easily Amused
8

J'ai pu faire fonctionner cela en utilisant la réponse trouvée ici:

Comment git ne rien commettre sans erreur?

git diff --quiet --exit-code --cached || git commit -m 'bla'
Ben
la source
1
Ce que fait ce qui précède est: " git diffExécutez la commande, et si cela échoue, exécutez la git commitcommande. Fondamentalement, il ne fait la validation que si git diffquelque chose à valider a été trouvé. Cependant, la réponse @jwernerny était correcte que vous devriez pouvoir ajouter exit 0comme dernière instruction à n'importe quel script pour que Jenkins le considère comme un succès. Je peux penser à un scénario où cela échouerait si vous faisiez une étape de shell Linux, mais dans Batch cela devrait toujours fonctionner.
Slav
@Ben Jenkins exécute les étapes de construction du shell en utilisant /bin/sh -xepar défaut comme mentionné ici (au milieu). Ainsi, vous pouvez essayer de mettre #!/bin/bashou de faire un set +eau-dessus de l'étape de construction pour remplacer ce comportement, ce qui continuera le reste de l'étape même une commande à l'intérieur de la sortie avec un code non-0
Xiawei Zhang
8

Sur la question (plus générale) du titre - pour éviter l'échec de Jenkins, vous pouvez l'empêcher de voir le code de sortie 1. Exemple pour ping:

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

Et maintenant, vous pouvez par exemple obtenir la sortie du ping:

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

Bien sûr, au lieu de ping ...Vous pouvez utiliser n'importe quelle commande, y compris git commit.

Nux
la source
6

Vous pouvez utiliser le plugin Text-finder . Cela vous permettra de vérifier la console de sortie pour une expression de votre choix puis de marquer la construction comme Unstable.

jphuynh
la source
cela semblait prometteur, mais pour une raison quelconque, la construction échouait.
Ben
4

Pour plusieurs commandes shell, j'ignore les échecs en ajoutant:

set +e commands true

entrez la description de l'image ici

Megha
la source
Je déconseille de désarmer -e en général. Si vous voulez ignorer la valeur de retour d'une commande spécifique, vous pouvez ajouter "|| true" ou quelque chose de plus significatif retournant true, tel que: stop-service.sh || echo Le service était déjà en panne
Raúl Salinas-Monteagudo
3

Si vous mettez ces commandes dans le bloc shell:

false
true

votre build sera marqué comme échec (au moins 1 code de sortie différent de zéro), vous pouvez donc ajouter (set + e) ​​pour l'ignorer:

set +e
false
true

n'échouera pas. Cependant, cela échouera même avec (set + e) ​​en place:

set +e
false

car la dernière commande shell doit quitter avec 0.

chenchuk
la source
2

Ce qui suit fonctionne pour mercurial en ne validant que s'il y a des changements. Ainsi, la construction échoue uniquement si la validation échoue.

hg id | grep "+" || exit 0
hg commit -m "scheduled commit"
Shaun Lebron
la source
0

Une autre réponse avec quelques conseils peut être utile pour quelqu'un:

n'oubliez pas de séparer vos commandes avec la règle suivante :

commande1 && command2 - signifie que la commande2 sera exécutée, uniquement si la commande1 réussit

command1 ;command2 - signifie que la commande 2 sera exécutée malgré le résultat de la commande1

par exemple:

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

sera exécuté avec succès avec les commandes set -eet en echo 0cas d' gmake testéchec (vos tests ont échoué), tandis que le code suivant est extrait:

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

un peu faux et les commandes set -eet echo 0in && gmake test && set -e && echo 0seront ignorées, avec l' println run_testsinstruction, car échoué gmake testentraînera l'annulation de la construction de jenkins. Pour contourner le problème, vous pouvez basculer vers returnStatus:true, mais vous manquerez la sortie de votre commande.

Sysanin
la source
0

Cette réponse est correcte, mais elle ne spécifie pas la commande || exit 0ou || trueentre dans la commande shell . Voici un exemple plus complet:

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

Ce qui précède fonctionnera, mais ce qui suit échouera:

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

C'est peut-être évident pour les autres, mais j'ai perdu beaucoup de temps avant de m'en rendre compte.

Grand McLargeÉnorme
la source