no falle la compilación de jenkins si falla la ejecución del shell

132

Como parte de mi proceso de compilación, estoy ejecutando un git commit como un paso de ejecución de shell. Sin embargo, si no hay cambios en el espacio de trabajo, Jenkins está fallando la compilación. Esto se debe a que git está devolviendo un código de error cuando no hay cambios para confirmar. Me gustaría abortar la compilación o simplemente marcarla como inestable si este es el caso. ¿Algunas ideas?

Ben
fuente
¿Verifica si hay algo que comprometer y solo se compromete en esos casos? stackoverflow.com/questions/5139290/…
Anders Lindahl

Respuestas:

210

Para detener la ejecución adicional cuando falla el comando :

command || exit 0

Para continuar la ejecución cuando el comando falla:

command || true

Preguntas de quolonel
fuente
12
No necesita el || exit 0en el primer caso, si commanddevuelve falso la ejecución se detendrá. Dicho esto, la segunda opción es muy útil.
Nir Alfasi
20
@alfasin No entiendes el problema. OP no quiere que la compilación Jenkins falle; ergo debemos hacerlo exit 0porque cualquier código de salida distinto de cero fallará la compilación.
Preguntas de Quolonel
1
Veo, en ese caso, cambiaría la redacción de: "Para detener la ejecución posterior cuando el comando falla:" a: "Para detener la ejecución posterior cuando el comando falla y marcar el trabajo de Jenkins como exitoso:".
Nir Alfasi
1
@alfasin Si bien estoy de acuerdo en que el comentario rápido de Quolonel Questions no fue profesional, tenía razón en lo que dijo. "salir 0" NO marcará el trabajo exitoso. Simplemente marcará el paso de compilación actual con éxito. El trabajo aún puede fallar en uno de los siguientes pasos de compilación.
noamik
1
Gracias esto funcionó! Esto es especialmente útil para la función del complemento "Ejecutar shell en host remoto usando ssh" ya que no puede usar / bin / bash + e para no fallar en caso de error. También me gusta la idea de elegir qué comandos no fallan en la compilación.
leeman24
80

Jenkins está ejecutando pasos de compilación de shell utilizando /bin/sh -xede forma predeterminada. -xsignifica imprimir cada comando ejecutado. -esignifica salir con falla si alguno de los comandos en el script falla.

Entonces, creo que lo que sucedió en su caso es que su comando git sale con 1, y debido al -eparámetro predeterminado , el shell recoge el código de salida que no es 0, ignora el resto del script y marca el paso como un error. Podemos confirmar esto si puede publicar su script de paso de compilación aquí.

Si ese es el caso, puede intentar ponerlo #!/bin/shpara que el script se ejecute sin opción; o hacer set +ealgo similar al paso de compilación para anular este comportamiento.


Editado: Otra cosa a tener en cuenta es que, si el último comando en su script de shell devuelve código que no es 0 , todo el paso de compilación seguirá marcado como fallido, incluso con esta configuración. En este caso, simplemente puede poner un echocomando al final para evitar eso.

Otra pregunta relacionada

Xiawei Zhang
fuente
41

Si no hay nada que empujar, git devuelve el estado de salida 1. Ejecutar el paso de compilación de shell se marca como fallido respectivamente. Puede usar la instrucción OR || (doble tubo).

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

Eso significa, ejecute el segundo argumento si primero falla (estado de salida devuelto> 0). El segundo comando siempre devuelve 0. Cuando no hay nada que empujar (estado de salida 1 -> ejecutar el segundo comando) echo devolverá 0 y el paso de compilación continúa.

Para marcar la compilación como inestable, puede utilizar el paso posterior a la compilación Jenkins Text Finder. Puede pasar por la salida de la consola, hacer coincidir el patrón (su eco) y marcar la construcción como inestable.

ecervena
fuente
27

Hay otra manera fácil de decirle a Jenkins que no falle. Puede aislar su confirmación en un paso de compilación y configurar el shell para que no falle:

set +e
git commit -m "Bla."
set -e
joecks
fuente
2
Asegúrese de agregar set -edespués del comando que desea ejecutar independientemente del código de salida. De lo contrario, puede terminar ejecutando comandos que no desea. Quería manejar el error yo mismo, así que hice algo como: `set + e commit -m" bla "EXIT_CODE =" $ {?} "Set -e # maneja la lógica del código de
salida`
8

Jenkins determina el éxito / fracaso de un paso por el valor de retorno del paso. Para el caso de un shell, debería ser el retorno del último valor. Tanto para los shells CMD de Windows como para Bash (POSIX), debe poder establecer el valor de retorno manualmente mediante exit 0el último comando.

jwernerny
fuente
Esto no parece funcionar para un 'ejecutar Windows Bat' que tiene 2 líneas: git commit -m "mensaje" salida 0
Ben
@Ben uso exit 0con "ejecutar el comando por lotes de Windows" en varias compilaciones en mi instalación de Windows Jenkins, y funciona como se esperaba. Algo más debe estar sucediendo. ¿Podría publicar la parte relevante del registro de la consola?
jwernerny
¿Lo estás usando con git commit -m "blah" en tu primer paso? Intenté crear un script bat en la máquina manualmente, y puse un eco y una salida 0 después del comando git. Ninguno de los otros comandos se ejecuta cuando no hay nada que comprometer ...
Ben
Ver respuesta de @xiawei. El comportamiento predeterminado de Jenkins es ejecutar un shell con el #!/bin/sh -xvque se detiene el script si se encuentra algún error.
Steven el fácilmente divertido
8

Pude hacer que esto funcione usando la respuesta que se encuentra aquí:

¿Cómo git cometer nada sin un error?

git diff --quiet --exit-code --cached || git commit -m 'bla'
Ben
fuente
1
Lo que hace lo anterior es: "Hacer git diffcomando, y si eso falla, hacer git commitcomando. Básicamente, solo hace la confirmación, si git diffencuentra algo para confirmar. Sin embargo, la respuesta de @jwernerny fue correcta que debería poder agregar exit 0como la última declaración a cualquier script para que Jenkins lo trate como un éxito. Puedo pensar en un escenario en el que esto fallaría si estuvieras haciendo un paso de shell de Linux, pero en Batch esto siempre debería funcionar.
Slav
@Ben Jenkins está ejecutando pasos de compilación de shell utilizando /bin/sh -xede forma predeterminada como se menciona aquí (en el medio). Por lo tanto, puede intentar colocar #!/bin/basho hacer una set +eparte superior del paso de compilación para anular este comportamiento, que continuará el resto del paso, incluso un comando dentro de la salida con un código que no sea 0
Xiawei Zhang,
8

En la pregunta (más general) en el título: para evitar que Jenkins falle, puede evitar que vea el código de salida 1. Ejemplo para ping:

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

Y ahora puede, por ejemplo, obtener salida de ping:

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

Por supuesto, en lugar de ping ...Puede usar cualquier comando, incluidos git commit.

Nux
fuente
6

Puede usar el complemento Buscador de texto . Le permitirá verificar la consola de salida para una expresión de su elección y luego marcar la compilación como Unstable.

jphuynh
fuente
esto parecía prometedor, pero por alguna razón seguía fallando la compilación.
Ben
4

Para múltiples comandos de shell, ignoro las fallas agregando:

set +e commands true

ingrese la descripción de la imagen aquí

Megha
fuente
Desanimo inquietante -e en general. Si desea ignorar el valor de retorno de algún comando específico, puede agregar "|| verdadero" o algo más significativo que devuelva verdadero, como: stop-service.sh || echo El servicio ya estaba inactivo
Raúl Salinas-Monteagudo
3

Si coloca estos comandos en el bloque de shell:

false
true

su compilación se marcará como fallida (al menos 1 código de salida distinto de cero), por lo que puede agregar (establecer + e) ​​para ignorarla:

set +e
false
true

No fallará. Sin embargo, esto fallará incluso con (set + e) ​​en su lugar:

set +e
false

porque el último comando de shell debe salir con 0.

chenchuk
fuente
2

Lo siguiente funciona para mercurial al comprometerse solo si hay cambios. Por lo tanto, la compilación solo falla si falla la confirmación.

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

Otra respuesta con algunos consejos, puede ser útil para alguien:

recuerde separar sus comandos con la siguiente regla :

command1 && command2: significa que ese comando2 se ejecutará, solo si el comando1 es correcto

comando1 ; comando2: significa que el comando 2 se ejecutará a pesar del resultado del comando1

por ejemplo:

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

se ejecutará con éxito con set -ey echo 0comandos si gmake testfalla (sus pruebas fallaron), mientras que el siguiente código recortado:

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

un poco mal y los comandos set -ey echo 0en && gmake test && set -e && echo 0se omitirán, con la println run_testsdeclaración, porque falló gmake testabortará la compilación de jenkins. Como solución alternativa puede cambiar returnStatus:true, pero perderá el resultado de su comando.

Sysanin
fuente
0

Esta respuesta es correcta, pero no especifica || exit 0o || trueva dentro del comando de shell . Aquí hay un ejemplo más completo:

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

Lo anterior funcionará, pero lo siguiente fallará:

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

Tal vez sea obvio para los demás, pero perdí mucho tiempo antes de darme cuenta de esto.

Big McLargeHuge
fuente