Jak oznaczyć kompilację jako niestabilną w Jenkinsie podczas uruchamiania skryptów powłoki


93

W projekcie, nad którym pracuję, używamy skryptów powłoki do wykonywania różnych zadań. Niektóre z nich to skrypty sh / bash, które uruchamiają rsync, a inne to skrypty PHP. Jeden ze skryptów PHP uruchamia testy integracji, które generują dane w formacie XML JUnit, raporty pokrycia kodu i tym podobne.

Jenkins jest w stanie oznaczyć zadania jako zakończone sukcesem / niepowodzeniem na podstawie statusu wyjścia . W PHP skrypt kończy pracę z wartością 1, jeśli wykryje, że testy zakończyły się niepowodzeniem podczas wykonywania. Pozostałe skrypty powłoki uruchamiają polecenia i używają kodów zakończenia z nich, aby oznaczyć kompilację jako nieudaną.

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

W terminologii Jenkinsa niestabilna kompilacja jest definiowana jako:

Kompilacja jest niestabilna, jeśli została pomyślnie utworzona, a co najmniej jeden wydawca zgłasza, że ​​jest niestabilna. Na przykład, jeśli wydawca JUnit jest skonfigurowany i test zakończy się niepowodzeniem, kompilacja zostanie oznaczona jako niestabilna.

Jak mogę sprawić, by Jenkins oznaczał kompilację jako niestabilną, a nie tylko sukces / niepowodzenie, podczas uruchamiania skryptów powłoki?


Odpowiedzi:


58

Użyj wtyczki Text-Finder .

Zamiast wychodzić ze statusem 1 (co spowodowałoby niepowodzenie kompilacji), wykonaj:

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

Następnie w czynnościach post-kompilacyjnych włącz wyszukiwarkę tekstu, ustaw wyrażenie regularne tak, aby pasowało do wydrukowanej wiadomości ( TESTS FAILED!) i zaznacz pole wyboru „Niestabilne, jeśli znaleziono” pod tym wpisem.


2
Zobacz odpowiedź poniżej dla opcji bez instalowania wtyczki, od wersji
jenkins

63

Nowoczesne wersje Jenkinsa (od 2.26, październik 2016) rozwiązały ten problem: to tylko zaawansowana opcja dla kroku budowania powłoki Wykonaj!

kod zakończenia kompilacji

Możesz po prostu wybrać i ustawić dowolną wartość wyjścia; jeśli pasuje, kompilacja będzie niestabilna. Po prostu wybierz wartość, która prawdopodobnie nie zostanie uruchomiona przez prawdziwy proces w twojej kompilacji.


Podoba mi się ta opcja, ponieważ nie wymaga instalowania żadnych dodatkowych wtyczek
mattherman

2
Ponieważ jest to zaimplementowane w najnowszym
Jenkinsie

3
„Nowoczesne wersje Jenkins” oznaczają Jenkins 2.26 lub nowszy. Zobacz issue.jenkins-ci.org/browse/JENKINS-23786 .
Blue

5
Czy można to określić za pomocą kodu podczas używania shpolecenia step w pliku Jenkinsfile? Gdzie znajduje się ustawienie w GUI? Nie mogę tego znaleźć.
bluenote10

1
Musiałem kliknąć przycisk „Zaawansowane ...” w kroku kompilacji, aby to ujawnić. Ukrywanie pojedynczej (i niezbyt zaawansowanej) opcji za zwijaczem typu „kliknij tutaj, aby coś zrobić” nie jest zbyt przydatne, ale tak właśnie jest.
tripleee

57

Można to zrobić bez drukowania magicznych ciągów i używania TextFindera. Oto kilka informacji na ten temat.

Zasadniczo potrzebujesz pliku .jar z http: // yourserver.com / cli dostępnego w skryptach powłoki, a następnie możesz użyć następującego polecenia, aby oznaczyć kompilację jako niestabilną:

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

Aby oznaczyć kompilację jako niestabilną po błędzie, możesz użyć:

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

Problem polega na tym, że plik jenkins-cli.jar musi być dostępny ze skryptu powłoki. Możesz umieścić go w łatwo dostępnej ścieżce lub pobrać za pomocą skryptu powłoki zadania:

wget ${JENKINS_URL}jnlpJars/jenkins-cli.jar

2
Naprawdę podoba mi się to rozwiązanie, zaimplementowałem w tym celu klasę ruby, aby ułatwić ponowne użycie w moich plikach rakefile. :)
Shire

3
+1 - jest to lepsze rozwiązanie niż zaakceptowana odpowiedź, ponieważ wyszukiwarka tekstu może wyszukiwać tylko jeden ciąg na zadanie, więc możesz ustawić stan kompilacji tylko na jedną z dwóch wartości.
gareth_bowles

4
Ciekawe rozwiązanie. Ale jeśli Twój Jenkins wymaga uwierzytelnienia, musisz skonfigurować uwierzytelnianie klucza publicznego w jego konfiguracji, w przeciwnym razie dowolne polecenie jenkins-cli zakończy się niepowodzeniem z wyjątkiem AccessDeniedException.
Tom De Leu,

2
To nie zadziała, jeśli używasz urządzenia podrzędnego, które nie ma dostępu internetowego do urządzenia głównego. Na przykład, jeśli serwer podrzędny Jenkins nie może utworzyć połączenia HTTP lub HTTPS z powrotem do serwera.
Steve HHH,

3
Chciałem użyć tego rozwiązania, ale set-build-resultzostało ono wycofane w jenkins-cli.
DrLime2k10

28

Powinieneś użyć Jenkinsfile, aby opakować skrypt kompilacji i po prostu oznaczyć bieżącą kompilację jako NIESTABILNĄ przy użyciu currentBuild.result = "UNSTABLE".

   etap {
      status = / * twoje polecenie kompilacji jest tutaj * /
      if (status === "OZNACZ-JAKO NIESTABILNE") {
        currentBuild.result = "NIESTABILNE"
      }
   }

3
Dlaczego ta odpowiedź nie ma więcej głosów? Czy jest z nim coś nie tak (z wyjątkiem użycia „magicznego” ciągu UNSTABLE)? Wydaje się to prostsze niż inne odpowiedzi.
Kevin

2
Pytanie dotyczyło zawodów freestyle, podczas gdy ta odpowiedź dotyczy prac na rurociągach. Odpowiedź Pipeline nie dotyczy zawodów freestyle
Mark Waite

Jak to w ogóle działa? Expected one of "steps", "stages", or "parallel" for stagePojawia się błąd: kiedy próbuję ustawić currentBuild.result bezpośrednio na scenie.
dokaspar


6

W moim skrypcie pracy mam następujące oświadczenia (to zadanie działa tylko na serwerze głównym 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

Możesz zobaczyć to i wiele więcej informacji na temat ustawiania statusu kompilacji na wiki Jenkins: https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+CLI


4
  1. Skonfiguruj kompilację PHP do tworzenia raportu 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. Zakończ kompilację skryptu ze statusem 0

    ...
    exit 0;
    
  3. Dodaj akcję po kompilacji Opublikuj raport wyników testu JUnit dla plików XML raportu z testu. Ta wtyczka zmieni kompilację stabilną na niestabilną, gdy test zakończy się niepowodzeniem.

    **/build/junit.xml
    
  4. Dodaj wtyczkę Jenkins Text Finder ze skanowaniem wyników konsoli i niezaznaczonymi opcjami. Ta wtyczka nie działa w całej kompilacji z powodu błędu krytycznego.

    PHP Fatal error:
    

3

Uważam, że najbardziej elastycznym sposobem na to jest odczytanie pliku we wtyczce groovy post build. wprowadź opis obrazu tutaj

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

Jeśli zawartość pliku ma wartość „prawda”, kompilacja zostanie ustawiona na niestabilną. Będzie to działać na lokalnym urządzeniu głównym i na wszystkich urządzeniach podrzędnych, na których uruchamiasz zadanie, oraz na wszelkiego rodzaju skryptach, które mogą zapisywać na dysku.


Zakładam, że to naprawdę mówi, że „jeśli w obszarze roboczym znajduje się plik o nazwie build.properties”, oznacz jako niestabilny. czy to prawda? Jestem nowy w Groovy, czy mógłbyś nieco bardziej podzielić to wyjaśnienie?
uchuugaka

@uchuugaka tak, jeśli istnieje plik i ma taką zawartość. Nazwa i zawartość pliku są dowolne. Użyj tego, co pasuje do twojego przypadku.
jeremyjjbrown

Dzięki! bardzo pomocny. Groovy Postbuild jest dość pośredni, a Groovy zasysa ogromną ilość rzeczy z Javy i dodaje więcej ... to dla mnie nowa sztuczka.
uchuugaka

@uchuugaka Nie sądzę, żeby to był problem z groovy :)
jeremyjjbrown

Nie ma problemu. To tylko wyzwanie!
uchuugaka

2

TextFinder jest dobry tylko wtedy, gdy status zadania nie został zmieniony z SUCCESS na FAILED lub ABORTED. W takich przypadkach użyj groovy skryptu w kroku 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
    }
 }

Zobacz więcej szczegółów w poście, który o tym napisałem: http://www.tikalk.com/devops/JenkinsJobStatusChange/


2

Powielam moją odpowiedź tutaj, ponieważ spędziłem trochę czasu na szukaniu tego:

Jest to teraz możliwe w nowszych wersjach Jenkinsa, możesz zrobić coś takiego:

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

Generator składni potoku pokazuje to na karcie Zaawansowane:

Przykład składni potoku


2

Pomyślałem, że opublikuję kolejną odpowiedź dla osób, które mogą szukać czegoś podobnego.

W naszej pracy kompilacji mamy przypadki, w których chcielibyśmy, aby kompilacja była kontynuowana, ale została oznaczona jako niestabilna. W naszym przypadku dotyczy to numerów wersji.

Tak więc chciałem ustawić warunek dla kompilacji i ustawić kompilację jako niestabilną, jeśli ten warunek zostanie spełniony.

Użyłem opcji Krok warunkowy (pojedynczy) jako krok kompilacji.

Następnie użyłem skryptu Execute system Groovy jako kroku kompilacji, który zostanie uruchomiony, gdy ten warunek zostanie spełniony.

Użyłem Groovy Command i ustawiłem następujący skrypt

import hudson.model.*

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

return

Wydaje się, że działa całkiem nieźle.

Natknąłem się tutaj na rozwiązanie

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


1

Jako lżejszą alternatywę dla istniejących odpowiedzi, możesz ustawić wynik kompilacji za pomocą prostego HTTP POST, aby uzyskać dostęp do interfejsu API REST konsoli skryptów 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

Zalety:

  • nie ma potrzeby pobierania i uruchamiania ogromnego pliku jar
  • brak możliwości ustawiania i czytania niektórych stanów globalnych (tekst konsoli, pliki w obszarze roboczym)
  • nie są wymagane żadne wtyczki (poza Groovym)
  • nie ma potrzeby konfigurowania dodatkowego kroku kompilacji, który jest zbędny w przypadkach PASSED lub FAILURE.

W przypadku tego rozwiązania środowisko musi spełniać następujące warunki:

  • Dostęp do interfejsu API Jenkins REST można uzyskać z poziomu slave
  • Slave musi mieć dostęp do poświadczeń, które umożliwiają dostęp do interfejsu API REST skryptów Jenkins Groovy.

0

Jednym z łatwych sposobów ustawienia kompilacji jako niestabilnej jest użycie bloku „execute shell”, uruchomienie exit 13


-3

Możesz po prostu wywołać „exit 1”, a kompilacja zakończy się niepowodzeniem w tym momencie i nie będzie kontynuowana. Skończyło się na utworzeniu funkcji przejściowej, która obsługuje to za mnie, i wzywam safemake zamiast tworzyć:

function safemake {
  make "$@"
  if [ "$?" -ne 0 ]; then
    echo "ERROR: BUILD FAILED"
    exit 1
  else
    echo "BUILD SUCCEEDED"
  fi
}

11
wyjście 1, o ile wiem, tylko zakończy się niepowodzeniem. Nie chcę, aby kompilacja zakończyła się niepowodzeniem, chcę, aby została oznaczona jako niestabilna.
HNygard

1
Zobacz także stackoverflow.com/questions/36313216/… - proste rozwiązanie jest po prostuif make "$@"; then echo "BUILD SUCCEEDED"; else rc=$?; echo "BUILD FAILED"; exit $rc; fi
tripleee
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.