Kostenlose DevOps-Analyse
Zurück zum Glossar
DevOps Glossar·CI/CD

CPS-Transformation (Jenkins)

// Direkte Antwort

Was ist die CPS-Transformation in Jenkins-Pipelines?

Jenkins führt Pipeline-Groovy durch den Continuation Passing Style (CPS) Transformer, damit Pipelines nach einem Controller-Neustart an der letzten Stage fortgesetzt werden können. Das erzwingt Serialisierbarkeit und verbietet bestimmte Groovy-Features in regulären Pipeline-Steps. Mit der @NonCPS-Annotation werden einzelne Methoden aus der CPS-Transformation ausgenommen — nötig z. B. für Stream-Operationen oder Jenkins-API-Aufrufe.

CPS-Patterns im Workshop
// Im DetailCPS-Transformation (Jenkins)

Die CPS-Transformation ist die technische Grundlage dafür, dass Jenkins-Pipelines durability bieten: Eine Pipeline kann einen Controller-Neustart überleben und an der zuletzt erreichten Stage fortsetzen. Damit das funktioniert, schreibt Jenkins den Programmzustand laufend auf die Festplatte. Der Continuation Passing Style Transformer überführt den Pipeline-Groovy dazu in eine serialisierbare Form, in der jeder Schritt seinen Folgeschritt als fortsetzbare Continuation kennt.

Diese Mechanik hat einen Preis, den jeder Pipeline-Entwickler kennen muss: Lokale Variablen müssen serialisierbar sein, und bestimmte Groovy-Konstrukte — insbesondere Closure-basierte Stream- und Collection-Operationen oder direkte Jenkins-API-Aufrufe — verhalten sich im CPS-Modus nicht wie erwartet oder werfen NotSerializableException. Wer das nicht weiß, sucht stundenlang nach scheinbar unerklärlichen Fehlern bei eigentlich trivialem Groovy.

Das Gegenmittel ist die @NonCPS-Annotation: Eine so markierte Methode wird außerhalb der CPS-Transformation ausgeführt — normales, schnelles Groovy, das aber innerhalb seines Aufrufs keinen Pipeline-Step nutzen und keinen Restart überdauern darf. Die Faustregel lautet, reine Datenverarbeitung in @NonCPS-Methoden zu kapseln und Pipeline-Steps im CPS-Kontext zu belassen. KI-Assistenz hilft, bestehende Pipelines auf riskante Stellen zu durchsuchen und @NonCPS-Refactorings vorzuschlagen.

// Beispiele aus der Praxis3 Szenarien
/01

JSON-Parsing in einer @NonCPS-Methode

Eine Pipeline parst eine umfangreiche JSON-Antwort und filtert sie mit Stream-Operationen — die Logik wird in eine @NonCPS-Methode ausgelagert, die nur das fertige Ergebnis zurückgibt, statt im CPS-Kontext an Serialisierungsfehlern zu scheitern.

/02

Restart-fester langer Deploy

Ein mehrstufiger OT-Deploy mit Wartungsfenster läuft über mehrere Stunden; dank CPS-Durability setzt die Pipeline nach einem unplanmäßigen Controller-Neustart an der letzten abgeschlossenen Stage fort, statt von vorn zu beginnen.

/03

KI-Audit auf CPS-Fallstricke

Vor einem Library-Release lässt das Team Claude Code die vars- und src-Dateien auf nicht-serialisierbare Closures und ungekapselte API-Aufrufe prüfen und erhält eine Liste mit Vorschlägen, welche Methoden @NonCPS markiert werden sollten.

// Häufige FragenFAQ
Wann sollte man @NonCPS verwenden und wann nicht?
@NonCPS eignet sich für reine Datenverarbeitung wie Parsen, Filtern oder Mappen ohne Pipeline-Steps. Nicht geeignet ist es für Code, der sh, echo oder andere Steps aufruft oder einen Restart überdauern muss — solcher Code gehört in den regulären CPS-Kontext.
Warum scheitern Stream- und collect-Operationen manchmal in Pipelines?
Closure-basierte Operationen wie collect oder findAll sind im CPS-Transformer problematisch, weil ihre internen Closures nicht zuverlässig serialisierbar sind. Die robuste Lösung ist, solche Verarbeitung in eine @NonCPS-Methode auszulagern oder auf einfache for-Schleifen umzustellen.
Beeinträchtigt @NonCPS die Restart-Fähigkeit der gesamten Pipeline?
Nein. Nur die Ausführung innerhalb der @NonCPS-Methode selbst ist nicht fortsetzbar; sie muss daher kurz und atomar sein. Die umgebende CPS-Pipeline bleibt restart-fest, solange der @NonCPS-Aufruf abgeschlossen ist, bevor ein Neustart eintritt.
Wie behebt man eine NotSerializableException in einer Jenkins-Pipeline?
Die Exception entsteht, wenn eine nicht-serialisierbare Variable über einen Pipeline-Step hinweg im CPS-Kontext gehalten wird — häufig ein JsonSlurper-Ergebnis oder eine Closure aus collect/findAll. Die Lösung ist, die betroffene Verarbeitung in eine @NonCPS-Methode zu kapseln, die nur ein serialisierbares Ergebnis (etwa eine einfache Map oder Liste) zurückgibt, oder die Closure-Operation durch eine for-Schleife zu ersetzen.
// Nächster Schritt

Erstgespräch.
Kostenlos.
90 Tage zum Ergebnis.

Wir klären gemeinsam, wie Sie in 90 Tagen die ersten messbaren Industrial-DevOps-Erfolge erzielen.

Erstgespräch buchen
Seit 2006 · 47+ Projekte
Industrie · Automotive · Finance