web-dev-qa-db-fra.com

Comment marquer une construction instable dans Jenkins lors de l'exécution de scripts Shell

Dans un projet sur lequel je travaille, nous utilisons des scripts Shell pour exécuter différentes tâches. Certains scripts sont SH/Bash qui exécute Rsync et certains sont des scripts PHP. L'un des scripts PHP exécute des tests d'intégration générés au format JUnit XML, des rapports de couverture de code, etc.

Jenkins peut marquer les travaux comme ayant réussi/échoué quitter le statut. Dans PHP, le script se ferme avec 1 s'il a détecté que des tests ont échoué au cours de l'exécution. Les autres scripts du shell exécutent des commandes et utilisent les codes de sortie de ceux-ci pour marquer une construction comme ayant échoué.

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

Dans la terminologie Jenkins , une construction instable est définie comme

Une construction est instable si elle a été générée avec succès et qu'un ou plusieurs éditeurs la signalent comme instable. Par exemple, si l'éditeur JUnit est configuré et qu'un test échoue, la construction sera marquée comme étant instable.

Comment puis-je faire en sorte que Jenkins marque une compilation comme instable au lieu de succès/échec lors de l'exécution de scripts Shell?

67
HNygard

Utilisez le Text-Finder plugin.

Au lieu de quitter avec le statut 1 (ce qui échouerait la construction), faites:

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

Que dans les actions post-construction, activez le Text Finder, définissez l’expression régulière avec le message que vous avez imprimé (TESTS FAILED!) et cochez la case "Unstable s’il est trouvé" sous cette entrée.

51
Jan Hudec

Cela peut être fait sans imprimer de chaînes magiques et sans utiliser TextFinder. Voici quelques informations à ce sujet.

Fondamentalement, vous avez besoin d’un fichier .jar à partir de http: // yourserver.com/cli disponible dans les scripts Shell, vous pouvez utiliser la commande suivante pour marquer une construction instable:

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

Pour marquer la construction instable en cas d'erreur, vous pouvez utiliser:

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

Le problème est que jenkins-cli.jar doit être disponible à partir d'un script shell. Vous pouvez le mettre dans un chemin d'accès facile ou le télécharger via le script Shell du travail:

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

Les versions modernes de Jenkins (depuis la version 2.26, octobre 2016) ont résolu ce problème: il ne s'agit que d'une option avancée pour l'étape de compilation Execute Shell!

 exit code for build

Vous pouvez simplement choisir et définir une valeur de sortie arbitraire; si cela correspond, la construction sera instable. Choisissez simplement une valeur qui ne sera probablement pas lancée par un processus réel dans votre construction.

22
Alan Franzoni

Vous devez utiliser Jenkinsfile pour envelopper votre script de génération et marquer simplement la version actuelle comme UNSTABLE en utilisant currentBuild.result = "UNSTABLE".

 étape {
 status =/* votre commande de construction va ici */
 if (status === "MARK-AS-UNSTABLE") {
 currentBuild.result = "UNSTABLE" 
 } 
 } 
9
poussma

vous devriez aussi pouvoir utiliser groovy et faire ce que textfinder a fait

marquer une construction comme étant instable avec un plugin groovy post-build

if(manager.logContains("Could not login to FTP server")) {
    manager.addWarningBadge("FTP Login Failure")
    manager.createSummary("warning.gif").appendText("<h1>Failed to login to remote FTP Server!</h1>", false, false, false, "red")
    manager.buildUnstable()
}

Voir aussi Groovy Postbuild Plugin

8
Kalpesh Soni

Dans mon script de travail, j'ai les déclarations suivantes (ce travail ne s'exécute que sur le maître 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

Vous pouvez voir ceci et beaucoup plus d'informations sur la définition des statuts de construction sur le wiki Jenkins: https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+CLI

6
Steve HHH
  1. Configurez PHP pour générer un rapport XML Junit

    <phpunit bootstrap="tests/bootstrap.php" colors="true" >
       <logging>
           <log type="junit" target="build/junit.xml" 
               logIncompleteSkipped="false" title="Test Results"/>
       </logging>
    
       ....
    
     </phpunit>
    
  2. Terminer le script de construction avec le statut 0

    ...
    exit 0;
    
  3. Ajouter une action post-construction Publier le résultat du test JUnit pour les rapports XML du rapport de test. Ce plugin changera la construction Stable en Unstable lorsque le test échouera. 

    **/build/junit.xml
    
  4. Ajouter Jenkins Text Finder plugin avec analyse de la sortie console et options non cochées. Ce plugin échoue dans son intégralité en cas d'erreur fatale.

    PHP Fatal error:
    
4
MariuszS

Je trouve que le moyen le plus flexible de le faire est de lire un fichier dans le plugin groovy post build .  enter image description here

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

Si le contenu du fichier est 'true', la construction sera définie sur unstable. Cela fonctionnera sur le maître local et sur tous les esclaves sur lesquels vous exécutez le travail, ainsi que pour tout type de scripts pouvant écrire sur le disque.

3
jeremyjjbrown

TextFinder est valide uniquement si le statut du travail n'a pas été modifié de SUCCESS à FAILED ou ABORTED . Dans ce cas, utilisez un script groovy à l'étape 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
    }
 }

Voir plus de détails dans un article que j'ai écrit à ce sujet: http://www.tikalk.com/devops/JenkinsJobStatusChange/

1
yorammi

Comme alternative plus légère aux réponses existantes, vous pouvez définir le résultat de la construction avec un simple HTTP POST pour accéder à l'API REST de la console de script 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

Avantages:

  • pas besoin de télécharger et d'exécuter un énorme fichier jar
  • pas de problème pour définir et lire un état global (texte de la console, fichiers dans l'espace de travail)
  • aucun plugin requis (à part Groovy)
  • pas besoin de configurer une étape de construction supplémentaire qui est superflue dans les cas PASSED ou FAILURE.

Pour cette solution, votre environnement doit répondre à ces conditions:

  • L'API Jenkins REST est accessible depuis l'esclave
  • Slave doit avoir accès aux informations d'identification permettant d'accéder à l'API Jenkins Groovy Script REST.
1
Alex O

Je pensais que je posterais une autre réponse pour les personnes qui pourraient être à la recherche de quelque chose de similaire.

Dans notre travail de création, nous avons des cas dans lesquels nous souhaiterions que la construction se poursuive, mais être marquée comme instable. Pour nous, cela concerne les numéros de version.

Donc, je voulais définir une condition sur la construction et la définir sur instable si cette condition est remplie.

J'ai utilisé l'option Conditional step (single) comme étape de construction.

Ensuite, j'ai utilisé Execute System Groovy Script comme étape de construction à exécuter lorsque cette condition est remplie.

J'ai utilisé la commande Groovy et ai défini le script comme suit

import hudson.model.*

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

return

Cela semble fonctionner assez bien.

Je suis tombé sur la solution ici

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

1
adprocas

Si Shell se termine avec une commande en échec que tout est OK (la construction a échoué:) En cas d'échec de la commande dans le script Shell, effectuez la vérification suivante:

 if [ "$?" -ne 0 ]; then
    exit 1
 fi 

Correction de @zrajm: il pourrait être simplifié à

... || exit 1
0
GKislin

Dupliquer ma réponse de ici parce que j'ai passé quelque temps à chercher ceci:

Ceci est maintenant possible dans les nouvelles versions de Jenkins, vous pouvez faire quelque chose comme ceci:

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

Le générateur de syntaxe de pipeline vous montre cela dans l'onglet Avancé:

 Pipeline Syntax Example

0
gib