4
votes

Pipeline Jenkins Obtenir l'état actuel de l'étape après l'utilisation de catchError

Ceci fait suite à ma question précédente:

Définir un statut d'étape dans Jenkins Pipelines

Il s'avère que je peux garder un pipeline comme SUCCESS mais que je peux marquer une étape individuelle comme INSTABLE si je le souhaite via catchError comme ceci:

stage("1") {
    catchError(buildResult: 'SUCCESS', stageResult: 'UNSTABLE') {
        // do stuff
    }
    // perhaps more catchError() blocks
    if(currentStage.getCurrentResult() == "UNSTABLE") {
        // do something special if we're unstable
    }
}

Si je veux obtenir l'état actuel du pipeline lui-même, je peux utiliser currentBuild.getCurrentResult() mais je ne vois pas d'analogue currentStage à cela.

Je suis intéressé à essayer un modèle qui pourrait ressembler à ceci dans mes étapes:

node()
{
    stage("Stage 1")
    {
        catchError(buildResult: 'SUCCESS', stageResult: 'UNSTABLE')
        {
            sh 'exit 1'
        }
    }
}

mais cela échouerait car il n'y a pas de currentStage disponible.

Donc en gros, catchError() est sympa mais j'aimerais savoir comment je peux attraper le changement de statut de ma scène si elle est modifiée ... Est-ce que quelqu'un sait comment vous accédez au statut de l'étape actuelle dans laquelle vous vous trouvez à partir d'un pipeline?


0 commentaires

4 Réponses :


2
votes

Bien qu'il n'existe pas de méthode directe pour accéder au résultat d'une étape dans un pipeline à partir de maintenant, vous pouvez contourner ce problème. Cela considère que vous n'êtes intéressé que par les résultats de l'étape SUCCESS ou UNSTABLE selon la question et non par l' FAILURE .

La solution de contournement consiste à initialiser une carte vide en haut de votre pipeline pour stocker le résultat de chaque étape. Maintenant, au lieu de la méthode catchError() , utilisez la méthode unstable() en combinaison avec un bloc try-catch. En effet, ce dernier vous permet non seulement de définir le résultat comme instable, mais également d'effectuer d'autres opérations telles que l'ajout du résultat à la carte dans le bloc except. Ensuite, vous pouvez lire ce résultat stocké à partir de la carte dans votre instruction if .

Exemple

stageResults = [:]
...
stage("1") {
    try {
        // do stuff
        // Add to map as SUCCESS on successful execution 
        stageResults."{STAGE_NAME}" = "SUCCESS"
    } catch (Exception e) {
        // Set the result and add to map as UNSTABLE on failure
        unstable("[ERROR]: ${STAGE_NAME} failed!")
        currentBuild.result = "SUCCESS"
        stageResult."{STAGE_NAME}" = "UNSTABLE"
    }
    if(stageResults.find{ it.key == "{STAGE_NAME}" }?.value == "UNSTABLE") {
        // do something special if we're unstable
    }
}


1 commentaires

Ouais, je fais déjà quelque chose comme ça mais je règle généralement une variable d'état booléenne comme Boolean stageFailed = false au début du bloc stage , puis essaye / attrape des trucs et vérifie-le plus tard. J'avais catchError que catchError simplifierait un peu cela, mais il semble que cela fonctionne un peu comme un bloc try spécialisé avec un catch caché qui définit un état qui n'est pas accessible au pipeline, ce qui limite son utilité pour nous. Cela change si je peux accéder au statut de l'étape actuelle d'une manière ou d'une autre ... mais il semble que ce n'est pas possible pour le moment. :(



0
votes

Comme alternative à ajouter à la réponse de Dibakar Aditya, il est possible de tout envelopper dans une fonction qui ressemble à des étapes régulières. C'est à dire:

stage("1") {
    def localSuccess = catchLocalError {
        // do stuff
    }
    if(!localSuccess) {
        // do something special if we're unstable
    }
}

boolean catchLocalError(Closure c) {
    try {
        c()
        return true
    } catch (Exception e) {
        return false
    }
}


2 commentaires

Ce que j'aime dans l'utilisation éventuelle de catchError c'est qu'il peut définir le statut d'une étape individuelle sur UNSTABLE, etc. et cela apparaît dans la vue de la scène dans Jenkins ... y a-t-il un moyen de définir le statut d'une étape individuelle sans en utilisant catchError?


Il devrait être possible de corriger si vous êtes prêt à déplacer l'étape de scène à l'intérieur de catchLocalError / catchError. Si vous êtes intéressé, je peux mettre à jour ma réponse.



3
votes

Je l'ai fait comme ça (pour garder le catchError):

def boolean test_results = false

pipeline {
    ...
    stage( 'x' ) {
        steps{
            catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                
                <Do some dangerous stuff here>
                
                //
                // If we reached here the above step hasn't failed
                //
                script { test_results = true }
            }
        }
    }
    stage( 'y' ) {
        steps{
            script{
                if( test_results == true ) {
                } else {
                }
            }
        }
    }
}


0 commentaires

0
votes

Quant à moi, la façon la plus élégante de le faire, c'est une section de publication . Dans votre exemple, vous marquez la scène comme UNSTABLE afin de pouvoir l'attraper en utilisant post->unstable .

stage("1") {
    steps {
        catchError(buildResult: 'SUCCESS', stageResult: 'UNSTABLE') {
            error 'Something goes wrong'
        }
    }
    post {
        always { echo 'Executed on every build'}
        unstable { echo 'Executed only if build is unstable (marked by catchError)'}
    }
}


0 commentaires