non fallire la compilazione di jenkins se l'esecuzione della shell fallisce


132

Come parte del mio processo di compilazione, sto eseguendo un commit git come fase di esecuzione della shell. Tuttavia, se non ci sono cambiamenti nell'area di lavoro, Jenkins non riesce a compilare. Questo perché git sta restituendo un codice di errore quando non ci sono modifiche da confermare. Vorrei interrompere la build o contrassegnarla come instabile se questo è il caso. Qualche idea?


Controlla se c'è qualcosa da impegnare e commetti solo in questi casi? stackoverflow.com/questions/5139290/…
Anders Lindahl il

Risposte:


210

Per interrompere l'ulteriore esecuzione quando il comando non riesce:

command || exit 0

Per continuare l'esecuzione quando il comando non riesce:

command || true


12
Non è necessario || exit 0nel primo caso, se commandrestituisce false l'esecuzione verrà interrotta. Detto questo, la seconda opzione è molto utile!
Nir Alfasi,

20
@alfasin Non capisci il problema. OP non vuole che la build Jenkins fallisca; ergo dobbiamo exit 0perché qualsiasi codice di uscita diverso da zero non riuscirà la compilazione.
Domande Quolonel,

1
Vedo, in tal caso cambierei il testo da: "Per interrompere l'ulteriore esecuzione quando il comando fallisce:" a: "Per interrompere l'ulteriore esecuzione quando il comando fallisce e contrassegnare il lavoro Jenkins come riuscito:".
Nir Alfasi,

1
@alfasin Anche se concordo sul fatto che l'osservazione scattante di Quolonel Questions non era professionale, aveva ragione in quello che ha detto. "exit 0" NON contrassegnerà il lavoro con esito positivo. Contrassegnerà con successo solo l'attuale fase di costruzione. Il processo può comunque non riuscire in uno dei passaggi di compilazione successivi.
Noamik,

1
Grazie ha funzionato! Ciò è particolarmente utile per la funzionalità del plug-in "Esegui shell su host remoto usando ssh" poiché non puoi usare / bin / bash + e per non fallire in caso di errore. Mi piace anche l'idea che posso scegliere quali comandi non falliscono nella compilazione.
leeman24,

80

Jenkins sta eseguendo i passaggi di compilazione della shell usando /bin/sh -xeper impostazione predefinita. -xsignifica stampare ogni comando eseguito. -esignifica uscire con esito negativo se uno dei comandi nello script ha esito negativo.

Quindi penso che quello che è successo nel tuo caso sia il comando git exit con 1 e, a causa del -eparametro predefinito , la shell prende il codice di uscita diverso da 0, ignora il resto dello script e contrassegna il passaggio come un errore. Possiamo confermarlo se puoi pubblicare il tuo script del passo di costruzione qui.

In tal caso, puoi provare a mettere in #!/bin/shmodo che lo script venga eseguito senza opzione; oppure esegui una set +eo più operazioni simili al passaggio di generazione per ignorare questo comportamento.


Modificato: un'altra cosa da notare è che, se l' ultimo comando nello script della shell restituisce un codice diverso da 0 , l'intera fase di compilazione verrà comunque contrassegnata come non riuscita anche con questa configurazione. In questo caso, puoi semplicemente inserire un echocomando alla fine per evitarlo.

Un'altra domanda correlata


41

Se non c'è nulla da spingere git restituisce lo stato di uscita 1. Eseguire il passo di compilazione della shell è contrassegnato rispettivamente come non riuscito. È possibile utilizzare l'istruzione OR || (doppio tubo).

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

Ciò significa che esegui il secondo argomento se il primo non riesce (stato di uscita restituito> 0). Il secondo comando restituisce sempre 0. Quando non c'è nulla da premere (esci dallo stato 1 -> esegui il secondo comando) echo restituirà 0 e il passo di costruzione continua.

Per contrassegnare la build come instabile, è possibile utilizzare il passaggio di ricerca testo Jenkins post-build. Può passare attraverso l'output della console, abbinare il pattern (l'eco) e contrassegnare build come instabile.


27

C'è un altro modo semplice per dire a Jenkins di non fallire. È possibile isolare il commit in un passaggio di generazione e impostare la shell in modo che non fallisca:

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

2
Assicurati di aggiungere set -edopo il comando che desideri eseguire indipendentemente dal codice di uscita. Altrimenti, potresti finire con l'esecuzione di comandi che non intendi fare. Volevo gestire l'errore da solo, quindi ho fatto qualcosa del tipo: `set + e commit -m" bla "EXIT_CODE =" $ {?} "Set -e # gestisce la logica del codice di
uscita`

8

Jenkins determina il successo / fallimento di un passo in base al valore di ritorno del passo. Nel caso di una shell, dovrebbe essere il ritorno dell'ultimo valore. Per entrambe le shell CMD di Windows e (POSIX) Bash, dovresti essere in grado di impostare manualmente il valore di ritorno usando exit 0come ultimo comando.


questo non sembra funzionare per un 'esegui windows bat' che ha 2 righe: git commit -m "message" exit 0
Ben

@Ben Uso exit 0con " Esegui comando batch di Windows" in più build sulla mia installazione di Windows Jenkins e funziona come previsto. Qualcos'altro deve succedere. Potresti pubblicare la parte pertinente del registro della console?
jwernerny,

lo stai usando con git commit -m "blah" nel tuo primo passo? Ho provato a creare manualmente uno script bat sulla macchina e ho inserito un'eco e un'uscita 0 dopo il comando git. Nessuno degli altri comandi viene eseguito quando non c'è nulla da impegnare ...
Ben

Vedi la risposta di @xiawei. Il comportamento predefinito di Jenkins è quello di eseguire una shell con la #!/bin/sh -xvquale si ottiene l'interruzione dello script in caso di errore.
Steven the Easily Amused

8

Sono stato in grado di farlo funzionare utilizzando la risposta trovata qui:

Come git commettere nulla senza un errore?

git diff --quiet --exit-code --cached || git commit -m 'bla'

1
Ciò che fa sopra è: "Esegui git diffcomando, e se fallisce, esegui git commitcomando. Fondamentalmente, esegue solo il commit, se git difftrova qualcosa da impegnare. Comunque la risposta di @jwernerny era corretta che dovresti essere in grado di aggiungere exit 0come ultima istruzione a qualsiasi sceneggiatura per fare in modo che Jenkins lo consideri un successo. Posso pensare a uno scenario in cui questo fallirebbe se si eseguisse il passo della shell di Linux, ma in Batch dovrebbe sempre funzionare.
Slav

@Ben Jenkins sta eseguendo i passaggi di compilazione della shell usando /bin/sh -xedi default come menzionato qui (nel mezzo). Quindi puoi provare a mettere #!/bin/basho fare uno set +ein cima al passaggio di costruzione per sovrascrivere questo comportamento, che continuerà il resto del passaggio anche un comando all'interno dell'uscita con codice diverso da 0
Xiawei Zhang,

8

Sulla domanda (più generale) nel titolo - per evitare che Jenkins fallisca, puoi impedirgli di vedere il codice di uscita 1. Esempio di ping:

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

E ora puoi ad esempio ottenere l'output del ping:

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

Naturalmente al posto di ping ...È possibile utilizzare qualsiasi comando / i - incluso git commit.



6

Puoi usare il plugin Text-finder . Ti permetterà di controllare la console di output per un'espressione di tua scelta, quindi contrassegnare la build come Unstable.


questo sembrava promettente, ma per qualche motivo continuava a fallire la costruzione.
Ben

4

Per più comandi shell, ignoro gli errori aggiungendo:

set +e commands true

inserisci qui la descrizione dell'immagine


Scoraggio inquietante -e in generale. Se si desidera ignorare il valore restituito di alcuni comandi specifici, è possibile aggiungere "|| true" o qualcosa di più significativo che restituisca true, ad esempio: stop-service.sh || Il servizio echo era già inattivo
Raúl Salinas-Monteagudo

3

Se si inseriscono questi comandi nel blocco shell:

false
true

la tua build verrà contrassegnata come non riuscita (almeno 1 codice di uscita diverso da zero), quindi puoi aggiungere (set + e) ​​per ignorarlo:

set +e
false
true

non fallirà. Tuttavia, ciò fallirà anche con (set + e) ​​in posizione:

set +e
false

perché l'ultimo comando della shell deve uscire con 0.


2

Quanto segue funziona per mercurial impegnandosi solo in caso di modifiche. Quindi la compilazione fallisce solo se il commit fallisce.

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

0

Un'altra risposta con alcuni suggerimenti, può essere utile per qualcuno:

ricordati di separare i tuoi comandi con la seguente regola :

comando1 && comando2 - mezzi, sarà eseguita che command2, solo se il successo comando1

comando1 ; command2 - significa che quel comando 2 verrà eseguito nonostante il risultato di command1

per esempio:

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

verrà eseguito correttamente con set -ee echo 0comandi in caso di gmake testesito negativo (i test non sono riusciti), mentre il seguente codice viene visualizzato:

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

un po 'sbagliato e i comandi set -ee echo 0in && gmake test && set -e && echo 0verranno saltati, con la println run_testsdichiarazione, perché il fallimento gmake testinterromperà la costruzione di jenkins. Come soluzione alternativa puoi passare a returnStatus:true, ma poi perderai l'output del tuo comando.


0

Questa risposta è corretta, ma non specifica il comando|| exit 0 o || trueva all'interno del comando shell . Ecco un esempio più completo:

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

Quanto sopra funzionerà, ma non riuscirà:

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

Forse è ovvio per gli altri, ma ho perso molto tempo prima di rendermene conto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.