Como marcar uma construção como instável no Jenkins ao executar scripts de shell

93

Em um projeto no qual estou trabalhando, estamos usando scripts de shell para executar tarefas diferentes. Alguns são scripts sh / bash que executam rsync e alguns são scripts PHP. Um dos scripts PHP está executando alguns testes de integração que geram saída para JUnit XML, relatórios de cobertura de código e similares.

Jenkins é capaz de marcar as tarefas como bem-sucedidas / com falha com base no status de saída . No PHP, o script sai com 1 se detectar que os testes falharam durante a execução. Os outros scripts de shell executam comandos e usam os códigos de saída deles para marcar uma construção como falha.

// :: End of PHP script:
// If any tests have failed, fail the build
if ($build_error) exit(1);

Na terminologia do Jenkins , uma construção instável é definida como:

Uma construção é instável se foi construída com sucesso e um ou mais editores relatam que é instável. Por exemplo, se o editor JUnit estiver configurado e um teste falhar, a construção será marcada como instável.

Como posso fazer com que o Jenkins marque uma construção como instável em vez de apenas sucesso / falha ao executar scripts de shell?

HNygard
fonte
Consegui executando diferentes etapas de trabalho e usando os plug-ins jenkins stackoverflow.com/questions/25442343/…
fantastory

Respostas:

58

Use o localizador de texto plugin .

Em vez de sair com o status 1 (o que causaria uma falha na compilação), faça:

if ($build_error) print("TESTS FAILED!");

Em seguida, nas ações pós-construção, habilite o Text Finder, defina a expressão regular para corresponder à mensagem que você imprimiu ( TESTS FAILED!) e marque a caixa de seleção "Instável se encontrada" sob essa entrada.

Jan Hudec
fonte
2
Veja a resposta abaixo para uma opção sem instalar um plugin, desde jenkins versão 2.26: stackoverflow.com/a/49676269/1347649
JSoet
61

As versões modernas do Jenkins (desde 2.26, outubro de 2016) resolveram isso: é apenas uma opção avançada para a etapa de compilação Executar shell!

código de saída para construção

Você pode apenas escolher e definir um valor de saída arbitrário; se corresponder, a construção ficará instável. Basta escolher um valor que provavelmente não será iniciado por um processo real em sua construção.

Alan Franzoni
fonte
Eu gosto dessa opção, pois não requer a instalação de nenhum plug
in
2
Como isso foi implementado no último Jenkins - essa deve ser uma resposta aceita
smoke_lp
3
"Versões modernas do Jenkins" significa Jenkins 2.26 ou mais recente. Consulte issues.jenkins-ci.org/browse/JENKINS-23786 .
Azul
5
É possível especificar isso via código ao usar o shcomando step em a Jenkinsfile? Onde a configuração está localizada na GUI? Eu não encontro.
bluenote10
1
Tive que clicar para abrir o botão "Avançado ..." na etapa de construção para expor isso. Não é muito útil ocultar uma única opção (e não particularmente avançada) atrás de um colapsador "clique aqui para fazer as coisas", mas é assim que as coisas são.
tripleee 01 de
57

Isso pode ser feito sem imprimir strings mágicas e usando TextFinder. Aqui estão algumas informações sobre isso.

Basicamente, você precisa de um arquivo .jar de http: // yourserver.com / cli disponível em scripts de shell, então você pode usar o seguinte comando para marcar uma compilação como instável:

java -jar jenkins-cli.jar set-build-result unstable

Para marcar a construção como instável em caso de erro, você pode usar:

failing_cmd cmd_args || java -jar jenkins-cli.jar set-build-result unstable

O problema é que jenkins-cli.jar precisa estar disponível no shell script. Você pode colocá-lo em um caminho de fácil acesso ou fazer o download via script de shell do job:

wget ${JENKINS_URL}jnlpJars/jenkins-cli.jar
binaryLV
fonte
2
Eu realmente gosto dessa solução, implementei uma classe de ruby ​​para isso para fácil reutilização em meus rakefiles. :)
Shire
3
+1 - esta é uma solução melhor do que a resposta aceita porque o Text Finder pode pesquisar apenas uma string por trabalho, então você só pode definir o status de construção para um de dois valores.
gareth_bowles de
4
Solução interessante. Mas se seu Jenkins requer autenticação, você precisará configurar a autenticação de chave pública em sua configuração ou qualquer comando jenkins-cli falhará com uma AccessDeniedException.
Tom De Leu
2
Isso não funcionará se você estiver usando um escravo que não tenha acesso à web para o mestre. Por exemplo, se o escravo Jenkins não puder criar uma conexão HTTP ou HTTPS de volta ao servidor.
Steve HHH
3
Eu queria usar essa solução, mas set-build-resultfoi descontinuada no jenkins-cli.
DrLime2k10
27

Você deve usar Jenkinsfile para embrulhar seu script de compilação e simplesmente marcar a compilação atual como INSTÁVEL usando currentBuild.result = "UNSTABLE" .

   palco {
      status = / * seu comando de compilação vai aqui * /
      if (status === "MARK-AS-UNSTABLE") {
        currentBuild.result = "UNSTABLE"
      }
   }
poussma
fonte
3
Por que essa resposta não tem mais votos positivos? Há algo de errado com isso (exceto o uso da string "mágica" UNSTABLE)? Parece mais direto do que as outras respostas.
Kevin
2
A pergunta era sobre trabalhos de freestyle, enquanto esta resposta é sobre trabalhos de Pipeline. A resposta do Pipeline não se aplica a trabalhos de estilo livre
Mark Waite
Como isso funciona? Recebo um erro: Expected one of "steps", "stages", or "parallel" for stagequando tento definir currentBuild.result diretamente dentro de um estágio.
dokaspar
6

No meu script de trabalho, tenho as seguintes declarações (este trabalho só é executado no mestre Jenkins):

# This is the condition test I use to set the build status as UNSTABLE
if [ ${PERCENTAGE} -gt 80 -a ${PERCENTAGE} -lt 90 ]; then
  echo WARNING: disc usage percentage above 80%

  # Download the Jenkins CLI JAR:
  curl -o jenkins-cli.jar ${JENKINS_URL}/jnlpJars/jenkins-cli.jar

  # Set build status to unstable
  java -jar jenkins-cli.jar -s ${JENKINS_URL}/ set-build-result unstable

fi

Você pode ver isso e muito mais informações sobre a configuração de status de compilação no wiki Jenkins: https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+CLI

Steve HHH
fonte
4
  1. Configure a construção do PHP para produzir relatório junit xml

    <phpunit bootstrap="tests/bootstrap.php" colors="true" >
       <logging>
           <log type="junit" target="build/junit.xml" 
               logIncompleteSkipped="false" title="Test Results"/>
       </logging>
    
       ....
    
     </phpunit>
  2. Concluir o script de construção com status 0

    ...
    exit 0;
  3. Adicionar ação pós-construção Publicar relatório de resultado de teste JUnit para XMLs de relatório de teste. Este plug-in irá alterar a construção Stable para Unstable quando o teste estiver falhando.

    **/build/junit.xml
  4. Adicione o plugin Jenkins Text Finder com verificação de saída do console e opções desmarcadas. Este plug-in falha totalmente na criação de um erro fatal.

    PHP Fatal error:
MariuszS
fonte
3

Acho que a maneira mais flexível de fazer isso é lendo um arquivo no plugin do Groovy Post Build. insira a descrição da imagem aqui

import hudson.FilePath
import java.io.InputStream

def build = Thread.currentThread().executable

String unstable = null
if(build.workspace.isRemote()) {
    channel = build.workspace.channel;
    fp = new FilePath(channel, build.workspace.toString() + "/build.properties")
    InputStream is = fp.read()
    unstable = is.text.trim()
} else {
    fp = new FilePath(new File(build.workspace.toString() + "/build.properties"))
    InputStream is = fp.read()
    unstable = is.text.trim()
}

manager.listener.logger.println("Build status file: " + unstable)
if (unstable.equalsIgnoreCase('true')) {
    manager.listener.logger.println('setting build to unstable')
    manager.buildUnstable()
}

Se o conteúdo do arquivo for 'verdadeiro', a construção será definida como instável. Isso funcionará no mestre local e em quaisquer escravos nos quais você execute o trabalho e para qualquer tipo de script que possa gravar no disco.

jeremyjjbrown
fonte
Estou assumindo que isso realmente diz "se houver um arquivo no espaço de trabalho denominado build.properties", marque como instável. Isso está certo? Eu sou novo no Groovy. Você se importaria de quebrar essa explicação um pouco mais?
uchuugaka
@uchuugaka sim, se houver um arquivo e tiver esse conteúdo. O nome e o conteúdo do arquivo são arbitrários. Use o que for adequado ao seu caso.
jeremyjjbrown
Obrigado! muito útil. Groovy Postbuild é bastante indireto, e Groovy suga uma grande quantidade de coisas do Java e adiciona mais ... é um novo truque para mim.
uchuugaka 01 de
@uchuugaka Eu não acho que isso seja um problema com groovy :)
jeremyjjbrown 01 de
Não um problema de todos. Apenas um desafio para se apoiar!
uchuugaka 01 de
2

O TextFinder é bom apenas se o status do trabalho não foi alterado de SUCCESS para FAILED ou ABORTED. Para esses casos, use um script bacana na etapa PostBuild:

errpattern = ~/TEXT-TO-LOOK-FOR-IN-JENKINS-BUILD-OUTPUT.*/;
manager.build.logFile.eachLine{ line ->
    errmatcher=errpattern.matcher(line)
    if (errmatcher.find()) {
        manager.build.@result = hudson.model.Result.NEW-STATUS-TO-SET
    }
 }

Veja mais detalhes em uma postagem que escrevi sobre isso: http://www.tikalk.com/devops/JenkinsJobStatusChange/

yorammi
fonte
2

Duplicando minha resposta a partir daqui porque passei algum tempo procurando por isso:

Isso agora é possível em versões mais recentes do Jenkins, você pode fazer algo assim:

#!/usr/bin/env groovy

properties([
  parameters([string(name: 'foo', defaultValue: 'bar', description: 'Fails job if not bar (unstable if bar)')]),
])


stage('Stage 1') {
  node('parent'){
    def ret = sh(
      returnStatus: true, // This is the key bit!
      script: '''if [ "$foo" = bar ]; then exit 2; else exit 1; fi'''
    )
    // ret can be any number/range, does not have to be 2.
    if (ret == 2) {
      currentBuild.result = 'UNSTABLE'
    } else if (ret != 0) {
      currentBuild.result = 'FAILURE'
      // If you do not manually error the status will be set to "failed", but the
      // pipeline will still run the next stage.
      error("Stage 1 failed with exit code ${ret}")
    }
  }
}

O gerador de sintaxe de pipeline mostra isso na guia avançada:

Exemplo de sintaxe de pipeline

chacota
fonte
2

Pensei em postar outra resposta para pessoas que podem estar procurando por algo semelhante.

Em nosso trabalho de construção, temos casos em que gostaríamos que a construção continuasse, mas fosse marcada como instável. Para o nosso está relacionado aos números de versão.

Então, eu queria definir uma condição na construção e definir a construção como instável se essa condição for atendida.

Usei a opção Etapa condicional (única) como uma etapa de construção.

Em seguida, usei Execute system Groovy script como a etapa de compilação que seria executada quando essa condição fosse atendida.

Usei o comando Groovy e configurei o script a seguir

import hudson.model.*

def build = Thread.currentThread().executable
build.@result = hudson.model.Result.UNSTABLE

return

Isso parece funcionar muito bem.

Eu tropecei na solução aqui

http://tech.akom.net/archives/112-Marking-Jenkins-build-UNSTABLE-from-environment-inject-groovy-script.html

adprocas
fonte
1

Como uma alternativa mais leve às respostas existentes, você pode definir o resultado da compilação com um HTTP POST simples para acessar a API REST do console de script do Groovy :

    curl -X POST \
     --silent \
     --user "$YOUR_CREDENTIALS" \
     --data-urlencode "script=Jenkins.instance.getItemByFullName( '$JOB_NAME' ).getBuildByNumber( $BUILD_NUMBER ).setResult( hudson.model.Result.UNSTABLE )" $JENKINS_URL/scriptText

Vantagens:

  • não há necessidade de baixar e executar um arquivo jar enorme
  • sem kludges para definir e ler algum estado global (texto do console, arquivos na área de trabalho)
  • nenhum plug-in necessário (além do Groovy)
  • não há necessidade de configurar uma etapa de compilação extra que é supérflua nos casos PASSED ou FAILURE.

Para esta solução, seu ambiente deve atender a estas condições:

  • A API REST do Jenkins pode ser acessada do escravo
  • O escravo deve ter acesso às credenciais que permitem acessar a API REST do script Jenkins Groovy.
Alex O
fonte
0

Uma maneira fácil de definir uma construção como instável é em seu bloco "executar shell", executar exit 13

user1415664
fonte
-3

Você pode apenas chamar "exit 1", e a compilação falhará nesse ponto e não continuará. Acabei criando uma função make de passagem para lidar com isso para mim e chamei safemake em vez de make para construir:

function safemake {
  make "$@"
  if [ "$?" -ne 0 ]; then
    echo "ERROR: BUILD FAILED"
    exit 1
  else
    echo "BUILD SUCCEEDED"
  fi
}
Jessebs
fonte
11
saída 1, até onde eu sei, apenas fará a compilação falhar. Não quero que a construção falhe, quero que seja marcada como instável.
HNygard
1
Consulte também stackoverflow.com/questions/36313216/… - a solução simples éif make "$@"; then echo "BUILD SUCCEEDED"; else rc=$?; echo "BUILD FAILED"; exit $rc; fi
tripleee