So markieren Sie einen Build in Jenkins als instabil, wenn Shell-Skripte ausgeführt werden

92

In einem Projekt, an dem ich arbeite, verwenden wir Shell-Skripte, um verschiedene Aufgaben auszuführen. Einige sind sh / bash-Skripte, die rsync ausführen, andere sind PHP-Skripte. Eines der PHP-Skripte führt einige Integrationstests aus, die in JUnit XML, Code Coverage-Berichten und ähnlichem ausgegeben werden.

Jenkins kann die Jobs basierend auf dem Exit-Status als erfolgreich / fehlgeschlagen markieren . In PHP wird das Skript mit 1 beendet, wenn festgestellt wurde, dass die Tests während des Laufs fehlgeschlagen sind. Die anderen Shell-Skripte führen Befehle aus und verwenden die Exit-Codes von diesen, um einen Build als fehlgeschlagen zu markieren.

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

In der Jenkins-Terminologie wird ein instabiler Build wie folgt definiert:

Ein Build ist instabil, wenn er erfolgreich erstellt wurde und ein oder mehrere Publisher ihn als instabil melden. Wenn beispielsweise der JUnit-Publisher konfiguriert ist und ein Test fehlschlägt, wird der Build als instabil markiert.

Wie kann ich Jenkins dazu bringen, einen Build als instabil zu markieren, anstatt nur Erfolg / Misserfolg beim Ausführen von Shell-Skripten?

HNygard
quelle
Ich habe es erreicht, verschiedene Jobschritte auszuführen und Jenkins Plugins zu verwenden stackoverflow.com/questions/25442343/…
fantastisch

Antworten:

57

Verwenden Sie das Text-Finder- Plugin.

Anstatt mit Status 1 zu beenden (was den Build fehlschlagen würde), gehen Sie wie folgt vor:

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

Aktivieren Sie dann in den Post-Build-Aktionen den Text Finder, stellen Sie den regulären Ausdruck so ein, dass er mit der von Ihnen gedruckten Nachricht übereinstimmt ( TESTS FAILED!), und aktivieren Sie das Kontrollkästchen "Instabil, wenn gefunden" unter diesem Eintrag.

Jan Hudec
quelle
2
In der Antwort unten finden Sie eine Option ohne Installation eines Plugins, da Jenkins Version 2.26
JSoet
60

Moderne Jenkins-Versionen (seit 2.26, Oktober 2016) haben dieses Problem gelöst: Es ist nur eine erweiterte Option für den Schritt zum Ausführen der Shell-Erstellung!

Exit-Code für Build

Sie können einfach einen beliebigen Exit-Wert auswählen und festlegen. Wenn es übereinstimmt, ist der Build instabil. Wählen Sie einfach einen Wert aus, der wahrscheinlich nicht durch einen realen Prozess in Ihrem Build ausgelöst wird.

Alan Franzoni
quelle
Ich mag diese Option, da Sie keine zusätzlichen Plugins installieren müssen
Mattherman
2
Da dies in den neuesten Jenkins implementiert ist - dies sollte eine akzeptierte Antwort sein
rauchen_lp
3
"Moderne Jenkins-Versionen" bedeutet Jenkins 2.26 oder neuer. Siehe Issues.jenkins-ci.org/browse/JENKINS-23786 .
Blau
5
Ist es möglich, dies per Code anzugeben, wenn der shBefehl step in a verwendet wird Jenkinsfile? Wo befindet sich die Einstellung in der GUI? Ich kann es nicht finden.
bluenote10
1
Ich musste auf die Schaltfläche "Erweitert ..." unter dem Erstellungsschritt klicken, um dies anzuzeigen. Es ist nicht sehr nützlich, eine einzelne (und nicht besonders erweiterte) Option hinter einem Reduzierer "Klicken Sie hier, um Dinge zu tun" auszublenden, aber so ist es nun mal.
Tripleee
57

Dies kann ohne Drucken von magischen Zeichenfolgen und mit TextFinder erfolgen. Hier sind einige Informationen dazu.

Grundsätzlich benötigen Sie eine .jar-Datei von http: // yourserver.com / cli, die in Shell-Skripten verfügbar ist. Dann können Sie den folgenden Befehl verwenden, um einen Build als instabil zu markieren:

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

Um Build bei Fehler als instabil zu markieren, können Sie Folgendes verwenden:

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

Das Problem ist, dass jenkins-cli.jar über das Shell-Skript verfügbar sein muss. Sie können es entweder in einen leicht zugänglichen Pfad einfügen oder über das Shell-Skript des Jobs herunterladen:

wget ${JENKINS_URL}jnlpJars/jenkins-cli.jar
binaryLV
quelle
2
Diese Lösung gefällt mir sehr gut. Ich habe dafür eine Ruby-Klasse implementiert, die in meinen Rake-Dateien einfach wiederverwendet werden kann. :)
Shire
3
+1 - Dies ist eine bessere Lösung als die akzeptierte Antwort, da der Text Finder nur nach einer Zeichenfolge pro Job suchen kann, sodass Sie den Erstellungsstatus nur auf einen von zwei Werten setzen können.
gareth_bowles
4
Interessante Lösung. Wenn Ihr Jenkins jedoch eine Authentifizierung erfordert, müssen Sie die Authentifizierung mit öffentlichem Schlüssel in seiner Konfiguration einrichten. Andernfalls schlägt ein Befehl von jenkins-cli mit einer AccessDeniedException fehl.
Tom De Leu
2
Dies funktioniert nicht, wenn Sie einen Slave verwenden, der keinen Webzugriff auf den Master hat. Zum Beispiel, wenn der Jenkins-Slave keine HTTP- oder HTTPS-Verbindung zum Server herstellen kann.
Steve HHH
3
Ich wollte diese Lösung verwenden, wurde aber set-build-resultin der jenkins-cli.
DrLime2k10
27

Sie sollten Jenkinsfile verwenden, um Ihr Build-Skript zu verpacken, und den aktuellen Build einfach mit UNSTABLE markieren currentBuild.result = "UNSTABLE".

   Bühne {
      status = / * Ihr Build-Befehl geht hierher * /
      if (status === "MARK-AS-UNSTABLE") {
        currentBuild.result = "UNSTABLE"
      }}
   }}
Poussma
quelle
3
Warum hat diese Antwort nicht mehr positive Stimmen? Stimmt etwas nicht (außer der Verwendung der "magischen" Zeichenfolge UNSTABLE)? Es scheint einfacher als die anderen Antworten.
Kevin
2
Die Frage bezog sich auf Freestyle-Jobs, während sich diese Antwort auf Pipeline-Jobs bezieht. Die Pipeline-Antwort gilt nicht für Freestyle-Jobs
Mark Waite
Wie funktioniert das überhaupt? Ich erhalte eine Fehlermeldung: Expected one of "steps", "stages", or "parallel" for stageWenn ich versuche, currentBuild.result direkt in einer Phase festzulegen.
Dokaspar
6

In meinem Jobskript habe ich die folgenden Anweisungen (dieser Job wird nur auf dem Jenkins-Master ausgeführt):

# 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

Sie können dies und viele weitere Informationen zum Festlegen des Build-Status im Jenkins-Wiki sehen: https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+CLI

Steve HHH
quelle
4
  1. Konfigurieren Sie den PHP-Build so, dass ein XML-Junit-Bericht erstellt wird

    <phpunit bootstrap="tests/bootstrap.php" colors="true" >
       <logging>
           <log type="junit" target="build/junit.xml" 
               logIncompleteSkipped="false" title="Test Results"/>
       </logging>
    
       ....
    
     </phpunit>
    
  2. Beenden Sie das Build-Skript mit dem Status 0

    ...
    exit 0;
    
  3. Aktion nach dem Erstellen hinzufügen JUnit-Testergebnisbericht für XML-Testberichte veröffentlichen. Dieses Plugin ändert Stable Build in Unstable, wenn der Test fehlschlägt.

    **/build/junit.xml
  4. Fügen Sie das Jenkins Text Finder- Plugin mit dem Scannen der Konsolenausgabe und deaktivierten Optionen hinzu. Dieses Plugin schlägt aufgrund eines schwerwiegenden Fehlers fehl.

    PHP Fatal error:
MariuszS
quelle
3

Ich finde den flexibelsten Weg, dies zu tun, indem ich eine Datei im groovigen Post-Build-Plugin lese. Geben Sie hier die Bildbeschreibung ein

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()
}

Wenn der Dateiinhalt 'true' ist, wird der Build auf instabil gesetzt. Dies funktioniert auf dem lokalen Master und auf allen Slaves, auf denen Sie den Job ausführen, sowie auf allen Arten von Skripten, die auf die Festplatte schreiben können.

jeremyjjbrown
quelle
Ich gehe davon aus, dass hier wirklich "Wenn sich im Arbeitsbereich eine Datei mit dem Namen build.properties befindet" als instabil markiert wird. ist das richtig? Ich bin neu bei Groovy. Würde es Ihnen etwas ausmachen, diese Erklärung ein bisschen mehr aufzuschlüsseln?
Uchuugaka
@uchuugaka ja, wenn es eine Datei gibt und sie diesen Inhalt hat. Der Dateiname und der Inhalt sind beliebig. Verwenden Sie alles, was zu Ihrem Fall passt.
Jeremyjjbrown
Vielen Dank! sehr hilfreich. Groovy Postbuild ist ziemlich indirekt, und Groovy saugt so viel Material aus Java ein und fügt mehr hinzu ... es ist ein neuer Trick für mich.
Uchuugaka
@uchuugaka Ich glaube nicht, dass das ein Problem mit groovy ist :)
jeremyjjbrown
Absolut kein Problem. Nur eine Herausforderung zum Anlehnen!
Uchuugaka
2

Der TextFinder ist nur dann gut, wenn der Auftragsstatus nicht von SUCCESS in FAILED oder ABORTED geändert wurde. Verwenden Sie in solchen Fällen ein grooviges Skript im PostBuild-Schritt:

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
    }
 }

Weitere Details finden Sie in einem Beitrag, den ich darüber geschrieben habe: http://www.tikalk.com/devops/JenkinsJobStatusChange/

Yorammi
quelle
2

Ich habe meine Antwort von hier aus dupliziert , weil ich einige Zeit damit verbracht habe, danach zu suchen:

Dies ist jetzt in neueren Versionen von Jenkins möglich. Sie können Folgendes tun:

#!/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}")
    }
  }
}

Der Pipeline-Syntaxgenerator zeigt Ihnen dies auf der Registerkarte "Erweitert":

Beispiel für eine Pipeline-Syntax

gib
quelle
2

Ich dachte, ich würde eine andere Antwort für Leute posten, die nach etwas Ähnlichem suchen könnten.

In unserem Build-Job haben wir Fälle, in denen wir möchten, dass der Build fortgesetzt wird, aber als instabil markiert werden. Bei uns handelt es sich um Versionsnummern.

Daher wollte ich eine Bedingung für den Build festlegen und den Build auf instabil setzen, wenn diese Bedingung erfüllt ist.

Ich habe die Option Bedingter Schritt (einzeln) als Erstellungsschritt verwendet.

Dann habe ich Execute System Groovy Script als Build-Schritt verwendet, der ausgeführt wird, wenn diese Bedingung erfüllt ist.

Ich habe Groovy Command verwendet und das Skript wie folgt eingestellt

import hudson.model.*

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

return

Das scheint ganz gut zu funktionieren.

Ich bin hier auf die Lösung gestoßen

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

Adprocas
quelle
1

Als leichtere Alternative zu den vorhandenen Antworten können Sie das Build-Ergebnis mit einem einfachen HTTP-POST festlegen, um auf die REST-API der Groovy-Skriptkonsole zuzugreifen :

    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

Vorteile:

  • Sie müssen keine große JAR-Datei herunterladen und ausführen
  • Keine Probleme beim Festlegen und Lesen eines globalen Status (Konsolentext, Dateien im Arbeitsbereich)
  • Keine Plugins erforderlich (außer Groovy)
  • Es ist nicht erforderlich, einen zusätzlichen Erstellungsschritt zu konfigurieren, der in den Fällen PASSED oder FAILURE überflüssig ist.

Für diese Lösung muss Ihre Umgebung die folgenden Bedingungen erfüllen:

  • Auf die Jenkins REST-API kann vom Slave aus zugegriffen werden
  • Der Slave muss Zugriff auf Anmeldeinformationen haben, mit denen er auf die REST-API des Jenkins Groovy-Skripts zugreifen kann.
Alex O.
quelle
0

Eine einfache Möglichkeit, einen Build als instabil festzulegen, besteht darin, in Ihrem Block "Shell ausführen" auszuführen exit 13

user1415664
quelle
-3

Sie können einfach "exit 1" aufrufen, und der Build schlägt an diesem Punkt fehl und wird nicht fortgesetzt. Ich habe eine Passthrough-Make-Funktion erstellt, um sie für mich zu erledigen, und Safemake aufgerufen, anstatt Make für das Bauen:

function safemake {
  make "$@"
  if [ "$?" -ne 0 ]; then
    echo "ERROR: BUILD FAILED"
    exit 1
  else
    echo "BUILD SUCCEEDED"
  fi
}
Jessebs
quelle
11
Exit 1 wird, soweit ich weiß, nur dazu führen, dass der Build fehlschlägt. Ich möchte nicht, dass der Build fehlschlägt, ich möchte, dass er als instabil markiert wird.
HNygard
1
Siehe auch stackoverflow.com/questions/36313216/… - die einfache Lösung ist nurif make "$@"; then echo "BUILD SUCCEEDED"; else rc=$?; echo "BUILD FAILED"; exit $rc; fi
Tripleee