não falhe a construção de jenkins se a execução do shell falhar

132

Como parte do meu processo de construção, estou executando um commit do git como uma etapa de execução do shell. No entanto, se não houver alterações no espaço de trabalho, o Jenkins falhará na compilação. Isso ocorre porque o git está retornando um código de erro quando não há alterações a serem confirmadas. Gostaria de abortar a compilação ou marcá-la como instável, se esse for o caso. Alguma ideia?

Ben
fonte
Verifique se há algo para confirmar, e somente confirme nesses casos? stackoverflow.com/questions/5139290/…
Anders Lindahl

Respostas:

210

Para parar a execução adicional quando o comando falhar:

command || exit 0

Para continuar a execução quando o comando falhar:

command || true

Quolonel Questions
fonte
12
Você não precisa || exit 0no primeiro caso, se commandretornar false, a execução será interrompida. Dito isto, a segunda opção é muito útil!
Nir Alfasi
20
@ alfasin Você não entende o problema. O OP não quer que a construção Jenkins falhe; portanto, precisamos, exit 0porque qualquer código de saída diferente de zero falhará na compilação.
Perguntas Quolonel
1
Entendo, nesse caso, eu mudaria a redação de: "Para interromper a execução quando o comando falhar:" para: "Para interromper a execução quando o comando falhar e marcar o trabalho de Jenkins como bem-sucedido:".
Nir Alfasi
1
@alfasin Embora eu concorde que o comentário rápido do Quolonel Questions não seja profissional, ele estava certo no que disse. "exit 0" NÃO marcará o trabalho com sucesso. Apenas marcará a etapa de compilação atual com êxito. O trabalho ainda pode falhar em uma das próximas etapas de compilação.
noamik
1
Graças a isso funcionou! Isso é especialmente útil para o recurso de plug-in "Executar shell no host remoto usando ssh", pois você não pode usar / bin / bash + e para não falhar por erro. Também gosto da ideia de escolher quais comandos não falham na compilação.
leeman24
80

Jenkins está executando as etapas de construção do shell usando /bin/sh -xepor padrão. -xsignifica imprimir todos os comandos executados. -esignifica sair com falha se algum dos comandos no script falhar.

Então, acho que o que aconteceu no seu caso é o comando git exit com 1 e, devido ao -eparâmetro padrão , o shell pega o código de saída diferente de 0, ignora o restante do script e marca a etapa como uma falha. Podemos confirmar isso se você puder postar seu script da etapa de construção aqui.

Se for esse o caso, você pode tentar colocar #!/bin/shpara que o script seja executado sem opção; ou faça uma set +ecoisa semelhante na etapa de compilação para substituir esse comportamento.


Editado: Outra coisa a ser observada é que, se o último comando no seu script de shell retornar código diferente de 0 , toda a etapa de compilação ainda será marcada como falha, mesmo com esta configuração. Nesse caso, você pode simplesmente colocar um echocomando no final para evitar isso.

Outra questão relacionada

Xiawei Zhang
fonte
41

Se não houver nada a ser enviado, o git retorna o status de saída 1. A etapa de execução da construção do shell é marcada como falha, respectivamente. Você pode usar a instrução OR || (tubo duplo).

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

Isto significa, execute o segundo argumento se falhar primeiro (status de saída retornado> 0). O segundo comando sempre retorna 0. Quando não há nada para pressionar (status de saída 1 -> execute o segundo comando), echo retornará 0 e a etapa de construção continuará.

Para marcar a compilação como instável, você pode usar a etapa de pós-compilação Jenkins Text Finder. Ele pode passar pela saída do console, corresponder ao padrão (seu eco) e marcar a construção como instável.

ecervena
fonte
27

Há outra maneira fácil de dizer a Jenkins para não falhar. Você pode isolar seu commit em uma etapa de construção e configurar o shell para não falhar:

set +e
git commit -m "Bla."
set -e
joecks
fonte
2
Certifique-se de adicionar set -eapós o comando que deseja executar, independentemente do código de saída. Caso contrário, você pode acabar executando comandos que não pretende. Eu queria resolver o erro sozinho, então fiz algo como: `set + e commit -m" bla "EXIT_CODE =" $ {?} "Set -e # manipula a lógica do código de
saída`
8

Jenkins determina o sucesso / falha de uma etapa pelo valor de retorno da etapa. Para o caso de um shell, deve ser o retorno do último valor. Para os shells do Windows CMD e (POSIX) Bash, você deve poder definir o valor de retorno manualmente usando exit 0como o último comando.

jwernerny
fonte
isso parece não funcionar para um 'execute windows bat' que possui 2 linhas: git commit -m "message" exit 0
Ben
@ Ben Eu uso exit 0com o comando "execute windows batch command" em várias versões da minha instalação do Windows Jenkins, e funciona conforme o esperado. Algo mais deve estar acontecendo. Você poderia postar a parte relevante do log do console?
jwernerny
você o está usando com git commit -m "blah" em sua primeira etapa? Tentei criar um script bat na máquina manualmente e coloquei um eco e uma saída 0 após o comando git. Nenhum dos outros comandos são executados quando não há nada para cometer ...
Ben
Veja a resposta de @xiawei. O comportamento padrão do Jenkins é executar um shell com o #!/bin/sh -xvqual resulta na interrupção do script se algum erro for encontrado.
Steven the facilmente divertido
8

Consegui fazer isso funcionar usando a resposta encontrada aqui:

Como git cometer nada sem um erro?

git diff --quiet --exit-code --cached || git commit -m 'bla'
Ben
fonte
1
O que o acima faz é: "Faça o git diffcomando, e se isso falhar, faça o git commitcomando. Basicamente, ele apenas faz o commit, se git diffencontrou algo a ser confirmado. No entanto, a resposta @jwernerny estava correta e você deveria poder adicionar exit 0a última declaração para qualquer script para fazer Jenkins tratá-lo como sucesso que eu posso pensar de um cenário em que este seria um fracasso se você estivesse fazendo Linux shell passo, mas em Batch esta deve sempre trabalhar..
Slav
Ben Jenkins está executando etapas de construção do shell usando /bin/sh -xepor padrão, como mencionado aqui (no meio). Então você pode tentar colocar #!/bin/bashou fazer uma set +eem cima da etapa de compilação para substituir esse comportamento, que vai continuar o resto da etapa mesmo um comando dentro de saída com código não-0
Xiawei Zhang
8

Na pergunta (mais geral) do título - para impedir que Jenkins falhe, você pode impedir que ele veja o código de saída 1. Exemplo para ping:

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

E agora você pode, por exemplo, obter a saída do ping:

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

Claro que em vez de ping ...Você pode usar qualquer comando (s) - inclusive git commit.

Nux
fonte
6

Você pode usar o plug-in Localizador de texto . Isso permitirá que você verifique se há uma expressão de sua escolha no console de saída e marque a compilação como Unstable.

jphuynh
fonte
isso parecia promissor, mas por algum motivo continuava falhando na construção.
Ben
4

Para vários comandos do shell, eu ignoro as falhas adicionando:

set +e commands true

insira a descrição da imagem aqui

Megha
fonte
Eu desencorajo desestabilizar -e em geral. Se você deseja ignorar o valor de retorno de algum comando específico, é possível adicionar "|| true" ou algo mais significativo retornando true, como: stop-service.sh || eco O serviço já estava inoperante
Raúl Salinas-Monteagudo
3

Se você colocar esses comandos no bloco de shell:

false
true

sua compilação será marcada como falha (pelo menos 1 código de saída diferente de zero), para que você possa adicionar (defina + e) ​​para ignorá-la:

set +e
false
true

não falhará. No entanto, isso falhará mesmo com o (conjunto + e) ​​instalado:

set +e
false

porque o último comando do shell deve sair com 0.

chenchuk
fonte
2

O seguinte funciona para mercurial apenas confirmando se houver alterações. Portanto, a construção falha apenas se a confirmação falhar.

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

Outra resposta, com algumas dicas, pode ser útil para alguém:

lembre-se de separar seus comandos com a seguinte regra :

command1 && command2 - meios, que command2 será executado, somente se o sucesso command1

command1 ;command2 - significa que o comando 2 será executado apesar do resultado do comando1

por exemplo:

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

será executado com êxito set -ee com os echo 0comandos se gmake testfalharem (seus testes falharam), enquanto o seguinte código cortou:

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

um pouco errado e comandos set -ee echo 0in && gmake test && set -e && echo 0serão ignorados, com a println run_testsdeclaração, porque falha gmake testabortará a construção de jenkins. Como solução alternativa, você pode alternar para returnStatus:true, mas perderá a saída do seu comando.

Sysanin
fonte
0

Esta resposta está correta, mas não especifica o || exit 0ou || trueentra no comando do shell . Aqui está um exemplo mais completo:

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

O acima funcionará, mas o seguinte falhará:

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

Talvez seja óbvio para os outros, mas perdi muito tempo antes de perceber isso.

Big McLargeHuge
fonte