Since CodeNarc 3.5.0
Classes in Jenkins libraries should generally implement the Serializable interface because every expression/variable used in a CPS transformed method can potentially be serialized. Generally all user defined classes (not from external libraries) in pipeline libraries or Jenkinsfiles are already implicitly Serializable in Jenkins but it makes static analysis easier later on if all classes are marked Serializable explicitly.
Example of violation:
class SomeClass {}
Since CodeNarc 3.5.0
Closures are CPS transformed by Jenkins and will cause an error at runtime when used in GStrings. Typically they can be replaced by variable interpolation. Closures that are used as argument to method calls on the other hand are fine. See also the Jenkins docs about Closures inside GString.
Examples:
def s1 = "some string ${-> x}" // Violation
def s2 = "some string ${x}" // OK
def s3 = "some string ${ [1,2,3].collect { i -> i * i }.toString() }" // OK
Since CodeNarc 3.5.0
CPS transformed methods may not be called from non CPS transformed methods in Jenkins.
Every analyzed Method is assumed to be CPS transformed, except it is annotated with com.cloudbees.groovy.cps.NonCPS
, is a constructor or a library method that is not configured in cpsPackages
.
Pipeline steps are assumed to be CPS transformed except for ‘echo’, ‘properties’ and ‘getContext’.
See also the Jenkins docs on Pipeline CPS Method Mismatches.
Property | Description | Default Value |
---|---|---|
cpsScriptVariableName | Jenkins pipeline script variable name | ‘script’ |
cpsPackages | Package names of used Jenkins pipeline libraries | [] |
Known limitations:
script
).Examples:
class SomeClass() {
public int value = cpsMethod() // Violation
SomeClass() {}
}
@NonCPS
void nonCpsMethod() {}
void cpsMethod() {}
@NonCPS
void someMethod() {
nonCpsMethod() // OK
new SomeClass() // OK
cpsMethod() // Violation
script.sh('echo hello') // Violation
}
Since CodeNarc 3.5.0
Every expression/variable in a CPS transformed method in Jenkins can potentially be serialized and should therefore implement the Serializable
interface.
Note: The interfaces List
, Map
and Set
are treated as Serializable because nearly every implementation is Serializable
.
It would be bad codestyle to use the implementation as type (see ImplementationAsType Rule).
Known limitations:
Examples:
class SomeClass {}
class SerializableClass implements Serializable {}
SomeClass some = new SomeClass() // Violation
SerializableClass ser = new SerializableClass() // OK
Map map = new HashMap<String, String>() //OK
Since CodeNarc 3.5.0
Some methods from the standard library cannot be CPS transformed and therefore must not be called with CPS transformed closure arguments. See also the Jenkins docs on Calling non-CPS-transformed methods with CPS-transformed arguments
Examples:
void cpsMethod() {
List l = [4,1,3]
l.sort { a, b -> a > b } // Violation
l.toSorted { a, b -> a > b } // Violation
"hello".eachLine { l, n -> println(l) } // Violation
"hello".eachLine(2) { l, n -> println(l) } // Violation
}
Since CodeNarc 3.5.0
Overridden methods of the standard library (e.g. from java.lang.Object) are often called from there and therefore must not be CPS transformed in Jenkins. See also the Jenkins docs on Overrides of non-CPS-transformed methods.
Examples:
class SomeClass {
@Override // Violation
String toString() {
return ''
}
@NonCPS
@Override // OK
boolean equals(Object other) {
return false
}
}
Since CodeNarc 3.5.0
Every parameter and return type has to implement the Serializable interface in Jenkins CPS tranformed Code.
Examples:
class SomeClass {}
class SerializableClass implements Serializable {}
void method(int i, SomeClass s) {} // Violation
SomeClass returnMethod() { return null } // Violation
SerializableClass safeMethod(SerializableClass s) { return null } // OK