Quel est l'effet de @NonCPS dans un script de pipeline Jenkins

110

J'ai un script de pipeline dans Jenkins.

J'avais l'habitude d'obtenir cette exception:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: les scripts ne sont pas autorisés à utiliser la méthode groovy.json.JsonSlurperClassic parseText java.lang.String

J'ai recherché l'exception et j'ai trouvé quelques indications que je devrais annoter la méthode où l'exception se produit @NonCPS. J'ai fait cela, sans vraiment comprendre ce que cela fait.

Après cela cependant, une exception que je lançais dans cette méthode n'était plus interceptée par une tryclause.

Alors, quelle est l'idée derrière @NonCPS? Quels sont les effets de son utilisation?

octave
la source
1
Le blog officiel jenkins contient un article qui présente cette annotation et peut vous aider. jenkins.io/blog/2017/02/01/pipeline-scalability-best-practice
袁文涛

Réponses:

142

L'exception que vous voyez est due à la sécurité des scripts et au sandboxing. Fondamentalement, par défaut, lorsque vous exécutez un script de pipeline, il s'exécute dans un bac à sable qui autorise uniquement l'utilisation de certaines méthodes et classes. Il existe des moyens de mettre les opérations sur liste blanche, consultez le lien ci-dessus.

L' @NonCPSannotation est utile lorsque vous avez des méthodes qui utilisent des objets qui ne sont pas sérialisables. Normalement, tous les objets que vous créez dans votre script de pipeline doivent être sérialisables (la raison en est que Jenkins doit pouvoir sérialiser l'état du script afin qu'il puisse être mis en pause et stocké sur le disque).

Lorsque vous mettez @NonCPSsur une méthode, Jenkins exécutera la méthode entière en une seule fois sans possibilité de pause. De plus, vous n'êtes pas autorisé à référencer des étapes de pipeline ou des méthodes transformées CPS à partir d'une @NonCPSméthode annotée. Vous trouverez plus d'informations à ce sujet ici .

Quant à la gestion des exceptions: pas sûr à 100% de ce que vous vivez; J'ai essayé ce qui suit et cela fonctionne comme prévu:

@NonCPS
def myFunction() {
    throw new RuntimeException();
}

try {
    myFunction();
} catch (Exception e) {
    echo "Caught";
}

et

@NonCPS
def myFunction() {
    throw new RuntimeException();
}

def mySecondFunction() {
    try {
        myFunction();
    } catch (Exception e) {
        echo "Caught";
    }
}

mySecondFunction();

et enfin:

@NonCPS
def myFunction() {
    throw new RuntimeException();
}

@NonCPS
def mySecondFunction() {
    try {
        myFunction();
    } catch (Exception e) {
        echo "Caught";
    }
}

mySecondFunction();

Tous impriment "Caught" comme prévu.

Jon S
la source