¿Cuál es el efecto de @NonCPS en un script de canalización de Jenkins?

110

Tengo un script de canalización en Jenkins.

Solía ​​obtener esta excepción:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Los scripts no pueden utilizar el método groovy.json.JsonSlurperClassic parseText java.lang.String

Busqué la excepción y encontré algunas indicaciones de que debería anotar el método con el que ocurre la excepción @NonCPS. Hice esto, sin entender realmente lo que hace.

Sin embargo, después de eso, una excepción que estaba lanzando en ese método ya no estaba atrapada por una trycláusula.

Entonces, ¿cuál es la idea detrás @NonCPS? ¿Cuáles son los efectos de usarlo?

octaviano
fuente
1
El blog oficial de jenkins tiene un artículo que presenta esta anotación y puede ayudarlo. jenkins.io/blog/2017/02/01/pipeline-scalability-best-practice
袁文涛

Respuestas:

141

La excepción que está viendo se debe a la seguridad del script y al sandboxing. Básicamente, de forma predeterminada, cuando ejecuta un script de canalización, se ejecuta en una caja de arena que solo permite el uso de ciertos métodos y clases. Hay formas de incluir operaciones en la lista blanca, consulte el enlace de arriba.

La @NonCPSanotación es útil cuando tiene métodos que usan objetos que no son serializables. Normalmente, todos los objetos que crea en su secuencia de comandos de canalización deben ser serializables (la razón de esto es que Jenkins debe poder serializar el estado de la secuencia de comandos para que pueda pausarse y almacenarse en el disco).

Cuando pones @NonCPSun método, Jenkins ejecutará todo el método de una vez sin la capacidad de pausar. Además, no se le permite hacer referencia a ningún paso de canalización o métodos transformados de CPS desde un @NonCPSmétodo anotado. Puede encontrar más información sobre esto aquí .

En cuanto al manejo de excepciones: No estoy 100% seguro de lo que está experimentando; Probé lo siguiente y funciona como se esperaba:

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

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

y

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

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

mySecondFunction();

y finalmente:

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

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

mySecondFunction();

Todos imprimen "Atrapado" como se esperaba.

Jon S
fuente