diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/InterceptingGCL.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/InterceptingGCL.groovy index d1aef4ca..e224e7bc 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/InterceptingGCL.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/InterceptingGCL.groovy @@ -11,7 +11,8 @@ class InterceptingGCL extends GroovyClassLoader { metaClazz.invokeMethod = helper.getMethodInterceptor() metaClazz.static.invokeMethod = helper.getMethodInterceptor() metaClazz.methodMissing = helper.getMethodMissingInterceptor() - metaClazz.getEnv = {return binding.env} + metaClazz.propertyMissing = helper.getPropertyMissingInterceptor() + metaClazz.getEnv = { return binding.env } // find and replace script method closure with any matching allowed method closure metaClazz.methods.forEach { scriptMethod -> def signature = method(scriptMethod.name, scriptMethod.nativeParameterTypes) @@ -66,11 +67,8 @@ class InterceptingGCL extends GroovyClassLoader { return super.loadClass(name) } - // Copy from this.parseClass(GroovyCodeSource, boolean) - cls.metaClass.invokeMethod = helper.getMethodInterceptor() - cls.metaClass.static.invokeMethod = helper.getMethodInterceptor() - cls.metaClass.methodMissing = helper.getMethodMissingInterceptor() + interceptClassMethods(cls.metaClass, helper, binding) return cls; } -} \ No newline at end of file +} diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/PipelineTestHelper.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/PipelineTestHelper.groovy index 95f6b230..23b84a6d 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/PipelineTestHelper.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/PipelineTestHelper.groovy @@ -185,9 +185,9 @@ class PipelineTestHelper { return callClosure(intercepted.value, args) } // if not search for the method declaration - MetaMethod m = delegate.metaClass.getMetaMethod(name, args) + MetaMethod metaMethod = delegate.metaClass.getMetaMethod(name, args) // ...and call it. If we cannot find it, delegate call to methodMissing - def result = (m ? this.callMethod(m, delegate, args) : delegate.metaClass.invokeMissingMethod(delegate, name, args)) + def result = (metaMethod ? this.callMethod(metaMethod, delegate, args) : delegate.metaClass.invokeMissingMethod(delegate, name, args)) return result } @@ -234,6 +234,20 @@ class PipelineTestHelper { return methodMissingInterceptor } + def propertyMissingInterceptor = { String propertyName -> + if (binding.hasVariable("params") && (binding.getVariable("params") as Map).containsKey(propertyName)) { + return (binding.getVariable("params") as Map).get(propertyName) + } + if (binding.getVariable("env") && (binding.getVariable("env") as Map).containsKey(propertyName)) { + return (binding.getVariable("env") as Map).get(propertyName) + } + throw new MissingPropertyException(propertyName) + } + + def getPropertyMissingInterceptor() { + return propertyMissingInterceptor + } + def callIfClosure(Object closure, Object currentResult) { if (closure instanceof Closure) { currentResult = callClosure(closure) diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AgentDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AgentDeclaration.groovy index 23c6137b..906af6ab 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AgentDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AgentDeclaration.groovy @@ -4,10 +4,10 @@ import com.lesfurets.jenkins.unit.declarative.agent.DockerAgentDeclaration import com.lesfurets.jenkins.unit.declarative.agent.KubernetesAgentDeclaration import groovy.transform.ToString -import static groovy.lang.Closure.DELEGATE_FIRST +import static com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration.executeWith @ToString(includePackage = false, includeNames = true, ignoreNulls = true) -class AgentDeclaration extends GenericPipelineDeclaration { +class AgentDeclaration { String label DockerAgentDeclaration docker @@ -16,13 +16,12 @@ class AgentDeclaration extends GenericPipelineDeclaration { String dockerfileDir Boolean reuseNode = null String customWorkspace - def binding = null def label(String label) { this.label = label } - def node(@DelegatesTo(AgentDeclaration) Closure closure) { + def node(Closure closure) { closure.call() } @@ -35,26 +34,29 @@ class AgentDeclaration extends GenericPipelineDeclaration { } def docker(String image) { - this.docker = new DockerAgentDeclaration().with { it.image = image; it } + this.docker = new DockerAgentDeclaration().with{ da -> da.image = image; da } } - def docker(@DelegatesTo(strategy = DELEGATE_FIRST, value = DockerAgentDeclaration) Closure closure) { - this.docker = createComponent(DockerAgentDeclaration, closure) + def docker(Closure closure) { + this.docker = new DockerAgentDeclaration(); + executeWith(this.docker, closure); } def kubernetes(Object kubernetesAgent) { this.@kubernetes = kubernetesAgent as KubernetesAgentDeclaration } - def kubernetes(@DelegatesTo(strategy = DELEGATE_FIRST, value = KubernetesAgentDeclaration) Closure closure) { - this.@kubernetes = createComponent(KubernetesAgentDeclaration, closure) + def kubernetes(Closure closure) { + this.@kubernetes = new KubernetesAgentDeclaration(); + def kubernetesDecl = this.@kubernetes + executeWith(kubernetesDecl, closure, Closure.DELEGATE_FIRST) } def dockerfile(boolean dockerfile) { this.dockerfile = dockerfile } - def dockerfile(@DelegatesTo(AgentDeclaration) Closure closure) { + def dockerfile(Closure closure) { closure.call() } @@ -62,19 +64,7 @@ class AgentDeclaration extends GenericPipelineDeclaration { this.dockerfileDir = dir } - def getCurrentBuild() { - return binding?.currentBuild - } - - def getEnv() { - return binding?.env - } - - def getParams() { - return binding?.params - } - - def execute(Object delegate) { + def execute(Script script) { def agentDesc = null if (label) { @@ -95,6 +85,6 @@ class AgentDeclaration extends GenericPipelineDeclaration { else { throw new IllegalStateException("No agent description found") } - executeWith(delegate, { echo "Executing on agent $agentDesc" }) + executeWith(script, { echo "Executing on agent $agentDesc" }) } } diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AllOfDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AllOfDeclaration.groovy index 109a2f89..8a55eb7f 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AllOfDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AllOfDeclaration.groovy @@ -2,12 +2,12 @@ package com.lesfurets.jenkins.unit.declarative import org.springframework.util.AntPathMatcher -import static groovy.lang.Closure.DELEGATE_FIRST +import static com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration.executeWith class AllOfDeclaration extends WhenDeclaration { List branches = [] - List expressions = [] + List expressions = [] List anyOfs = [] def branch(String name) { @@ -18,35 +18,29 @@ class AllOfDeclaration extends WhenDeclaration { this.expressions.add(closure) } - def anyOf(@DelegatesTo(strategy = DELEGATE_FIRST, value = AnyOfDeclaration) Closure closure) { - this.anyOfs.add(createComponent(AnyOfDeclaration, closure)) + def anyOf(Closure closure) { + AnyOfDeclaration anyOfDeclaration = new AnyOfDeclaration(); + this.anyOfs.add(anyOfDeclaration) + executeWith(anyOfDeclaration, closure, Closure.DELEGATE_FIRST) } - def expressions(Object delegate) { - return this.expressions.collect {executeWith(delegate, it)}.every() - } - - def anyOf(Object delegate) { - return this.anyOfs.collect {it.execute(delegate)} - } - - Boolean execute(Object delegate) { - def results = [] + Boolean execute(Script script) { + List results = [] AntPathMatcher antPathMatcher = new AntPathMatcher() if (this.branches.size() > 0) { branches.each { branch -> - results.add(antPathMatcher.match(branch, delegate.env.BRANCH_NAME)) + results.add(antPathMatcher.match(branch, script.env.BRANCH_NAME)) } } if (this.expressions.size() > 0) { - results.add(expressions(delegate)) + results.add(this.expressions.collect { executeWith(script, it) }.every()) } if (this.anyOfs.size() > 0) { - results.addAll(anyOf(delegate)) + results.addAll(this.anyOfs.collect {it.execute(script)}) } return results.every() diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AnyOfDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AnyOfDeclaration.groovy index deb62c9d..38cc5c45 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AnyOfDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/AnyOfDeclaration.groovy @@ -1,16 +1,14 @@ package com.lesfurets.jenkins.unit.declarative -import static com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration.executeWith import org.springframework.util.AntPathMatcher -import static groovy.lang.Closure.DELEGATE_FIRST - +import static com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration.executeWith class AnyOfDeclaration extends WhenDeclaration { List tags = [] List branches = [] - List expressions = [] + List expressions = [] List allOfs = [] def tag(String name) { @@ -25,41 +23,35 @@ class AnyOfDeclaration extends WhenDeclaration { this.expressions.add(closure) } - def allOf(@DelegatesTo(strategy = DELEGATE_FIRST, value = AllOfDeclaration) Closure closure) { - this.allOfs.add(createComponent(AllOfDeclaration, closure)) - } - - def allOf(Object delegate) { - return this.allOfs.collect {it.execute(delegate)} - } - - def expressions(Object delegate) { - return this.expressions.collect {executeWith(delegate, it)}.any() + def allOf(Closure closure) { + AllOfDeclaration allOfDeclaration = new AllOfDeclaration(); + this.allOfs.add(allOfDeclaration) + executeWith(allOfDeclaration, closure, Closure.DELEGATE_FIRST) } - Boolean execute(Object delegate) { + Boolean execute(Script script) { def results = [] AntPathMatcher antPathMatcher = new AntPathMatcher() if (this.tags.size() > 0) { tags.each { tag -> - results.add(antPathMatcher.match(tag, delegate.env.TAG_NAME)) + results.add(antPathMatcher.match(tag, script.env.TAG_NAME)) } } if (this.branches.size() > 0) { branches.each { branch -> - results.add(antPathMatcher.match(branch, delegate.env.BRANCH_NAME)) + results.add(antPathMatcher.match(branch, script.env.BRANCH_NAME)) } } if (this.expressions.size() > 0) { - results.add(expressions(delegate)) + results.add(this.expressions.collect {executeWith(delegate, it)}.any()) } if (this.allOfs.size() > 0) { - results.addAll(allOf(delegate)) + results.addAll(this.allOfs.collect {it.execute(script)}) } return results.any() diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/DeclarativePipeline.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/DeclarativePipeline.groovy index d223af2d..4abf77fd 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/DeclarativePipeline.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/DeclarativePipeline.groovy @@ -1,14 +1,12 @@ package com.lesfurets.jenkins.unit.declarative -import static groovy.lang.Closure.* - class DeclarativePipeline extends GenericPipelineDeclaration { def properties = [:] List options = [] Closure triggers - ParametersDeclaration params = null + ParametersDeclaration parameters = null DeclarativePipeline() { properties.put('any', 'any') @@ -24,37 +22,37 @@ class DeclarativePipeline extends GenericPipelineDeclaration { } } - def propertyMissing(String name, arg) { - - } - - def options(@DelegatesTo(DeclarativePipeline) Closure closure) { + def options(Closure closure) { options.add(closure) } - def triggers(@DelegatesTo(DeclarativePipeline) Closure closure) { + def triggers(Closure closure) { this.triggers = closure } def parameters(Object o) { - this.params = new ParametersDeclaration().with { it.label = o; it } + this.parameters = new ParametersDeclaration().with { it.label = o; it } } - def parameters(@DelegatesTo(strategy=DELEGATE_FIRST, value=ParametersDeclaration) Closure closure) { - this.params = createComponent(ParametersDeclaration, closure) + def parameters(Closure closure) { + this.parameters = new ParametersDeclaration() + this.parameters.binding = closure.binding; + executeWith(this.parameters, closure) } - def execute(Object delegate) { - super.execute(delegate) + def execute(Script script) { + super.execute(script) this.options.forEach { - executeOn(delegate, it) + executeWith(script, it) + } + this.agent?.execute(script) + if (this.triggers) { + executeWith(script, this.triggers) } - this.agent?.execute(delegate) - executeOn(delegate, this.triggers) this.stages.entrySet().forEach { e -> - e.value.execute(delegate) + e.value.execute(script) } - this.post?.execute(delegate) + this.post?.execute(script) } } diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/DeclarativePipelineTest.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/DeclarativePipelineTest.groovy index e4095ccc..237e093a 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/DeclarativePipelineTest.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/DeclarativePipelineTest.groovy @@ -8,15 +8,18 @@ import static com.lesfurets.jenkins.unit.MethodSignature.method abstract class DeclarativePipelineTest extends BasePipelineTest { def pipelineInterceptor = { Closure closure -> - GenericPipelineDeclaration.binding = binding - GenericPipelineDeclaration.createComponent(DeclarativePipeline, closure).execute(delegate) + def declarativePipeline = new DeclarativePipeline() + def rehydratedPipelineCl = closure.rehydrate(declarativePipeline, closure.owner, closure) + rehydratedPipelineCl.resolveStrategy + rehydratedPipelineCl.call(); + declarativePipeline.execute(closure.owner) } def paramInterceptor = { Map desc -> addParam(desc.name, desc.defaultValue, false) } - def stringInterceptor = { Map desc-> + def stringInterceptor = { Map desc -> if (desc) { // we are in context of parameters { string(...)} if (desc.name) { diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/GenericPipelineDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/GenericPipelineDeclaration.groovy index 4300935c..32b7f574 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/GenericPipelineDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/GenericPipelineDeclaration.groovy @@ -1,7 +1,5 @@ package com.lesfurets.jenkins.unit.declarative -import static groovy.lang.Closure.DELEGATE_FIRST - abstract class GenericPipelineDeclaration { AgentDeclaration agent @@ -9,35 +7,14 @@ abstract class GenericPipelineDeclaration { Closure tools PostDeclaration post Map stages = [:] - static def binding = null - - static T createComponent(Class componentType, @DelegatesTo(strategy = DELEGATE_FIRST) Closure closure) { - // declare componentInstance as final to prevent any multithreaded issues, since it is used inside closure - final def componentInstance = componentType.newInstance() - def rehydrate = closure.rehydrate(componentInstance, closure, componentInstance) - if (binding && componentInstance.hasProperty('binding') && componentInstance.binding != binding) { - componentInstance.binding = binding - } - rehydrate.call() - return componentInstance - } - static T executeOn(@DelegatesTo.Target Object delegate, - @DelegatesTo(strategy = DELEGATE_FIRST) Closure closure) { + static T executeWith(Object delegate, Closure closure, Integer resolveStrategy = null) { if (closure) { - def cl = closure.rehydrate(delegate, delegate, delegate) - cl.resolveStrategy = DELEGATE_FIRST - return cl.call() - } - return null - } - - static T executeWith(@DelegatesTo.Target Object delegate, - @DelegatesTo(strategy = DELEGATE_FIRST) Closure closure) { - if (closure) { - def cl = closure.rehydrate(delegate, delegate, delegate) - cl.resolveStrategy = DELEGATE_FIRST - return cl.call() + closure.delegate = delegate; + if(resolveStrategy) { + closure.resolveStrategy = resolveStrategy + } + return closure.call() } return null } @@ -46,8 +23,9 @@ abstract class GenericPipelineDeclaration { this.agent = new AgentDeclaration().with { it.label = o; it } } - def agent(@DelegatesTo(strategy = DELEGATE_FIRST, value = AgentDeclaration) Closure closure) { - this.agent = createComponent(AgentDeclaration, closure) + def agent(Closure closure) { + this.@agent = new AgentDeclaration(); + executeWith(this.@agent, closure) } def environment(Closure closure) { @@ -58,54 +36,50 @@ abstract class GenericPipelineDeclaration { this.tools = closure } - def post(@DelegatesTo(strategy = DELEGATE_FIRST, value = PostDeclaration) Closure closure) { - this.post = createComponent(PostDeclaration, closure) + def post(Closure closure) { + this.post = new PostDeclaration(); + executeWith(this.post, closure) } - def stages(@DelegatesTo(DeclarativePipeline) Closure closure) { + def stages(Closure closure) { closure.call() } - def stage(String name, - @DelegatesTo(strategy = DELEGATE_FIRST, value = StageDeclaration) Closure closure) { - this.stages.put(name, createComponent(StageDeclaration, closure).with { it.name = name; it }) + def stage(String stageName, Closure closure) { + def stageDeclaration = new StageDeclaration(stageName) + executeWith(stageDeclaration, closure, Closure.DELEGATE_FIRST); + this.stages.put(stageName, stageDeclaration) } - def getProperty(String propertyName) { - def metaProperty = this.metaClass.getMetaProperty(propertyName) - if (metaProperty) { - return metaProperty.getProperty(this) - } else { - if (binding?.hasProperty(propertyName) || binding?.hasVariable(propertyName)) { - return binding.getProperty(propertyName) - } - if (binding?.hasVariable("params") && (binding?.getProperty("params") as Map).containsKey(propertyName)) { - return (binding?.getProperty("params") as Map).get(propertyName) - } - if (binding?.hasVariable("env") && (binding?.getProperty("env") as Map).containsKey(propertyName)) { - return (binding?.getProperty("env") as Map).get(propertyName) - } - def metaMethod = this.metaClass.getMetaMethod("propertyMissing", propertyName) - if (metaMethod) { - metaMethod.invoke(this, propertyName) - } else { - throw new MissingPropertyException(propertyName) - } - } - } + def execute(Script script) { + Map envValuestoRestore = [:] - def execute(Object delegate) { // set environment if (this.environment) { - def env = delegate.binding.env - // let access env and currentBuild properties in environment closure - env.env = env - env.currentBuild = delegate.binding.currentBuild + envValuestoRestore = initEnvironment(this.environment, script) + } + resetEnvironment(envValuestoRestore, script) + } - def cl = this.environment.rehydrate(env, delegate, this) - cl.resolveStrategy = DELEGATE_FIRST - cl.call() + public static Map initEnvironment(Closure environment, Object delegate) { + Map envValuestoRestore = [:] + Binding subBinding = new Binding() + subBinding.metaClass.setProperty = { String propertyName, Object newValue -> + if (delegate.hasProperty(propertyName)) { + envValuestoRestore.put(propertyName, delegate.getProperty(propertyName)) + } + (delegate.env as Map).put(propertyName, newValue) } + def envClosure = environment.rehydrate(subBinding, environment, delegate) + envClosure.resolveStrategy = Closure.DELEGATE_FIRST + envClosure.call() + return envValuestoRestore } + public static resetEnvironment(Map envValuestoRestore, Object delegate) { + envValuestoRestore.entrySet().forEach { entry -> + def envMap = delegate.env as Map + envMap.put(entry.getKey(), entry.getValue()) + } + } } diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/NotDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/NotDeclaration.groovy index aaeffc87..90ab1b6b 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/NotDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/NotDeclaration.groovy @@ -2,8 +2,8 @@ package com.lesfurets.jenkins.unit.declarative class NotDeclaration extends WhenDeclaration { - Boolean execute(Object delegate) { - return !super.execute(delegate) + Boolean execute(Script script) { + return !super.execute(script) } } diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/ParallelDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/ParallelDeclaration.groovy index d536a75b..0600abcc 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/ParallelDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/ParallelDeclaration.groovy @@ -1,10 +1,8 @@ package com.lesfurets.jenkins.unit.declarative -import static groovy.lang.Closure.DELEGATE_FIRST -//import static com.lesfurets.jenkins.unit.declarative.DeclarativePipeline.executeOn - -class ParallelDeclaration extends GenericPipelineDeclaration { +class ParallelDeclaration { + Map stages = [:] boolean failFast ParallelDeclaration(boolean failFast) { @@ -15,15 +13,15 @@ class ParallelDeclaration extends GenericPipelineDeclaration { this.failFast = false } - def stage(String name, - @DelegatesTo(strategy = DELEGATE_FIRST, value = StageDeclaration) Closure closure) { - this.stages.put(name, createComponent(StageDeclaration, closure).with{it.name = name;it} ) + def stage(String name, Closure closure) { + def stageDeclaration = new StageDeclaration(name); + GenericPipelineDeclaration.executeWith(stageDeclaration, closure); + this.stages.put(name, stageDeclaration) } - def execute(Object delegate) { - super.execute(delegate) + def execute(Script script) { this.stages.entrySet().forEach { e -> - e.value.execute(delegate) + e.value.execute(script) } } diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/ParametersDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/ParametersDeclaration.groovy index 13ef5806..2d0ba6e5 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/ParametersDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/ParametersDeclaration.groovy @@ -1,12 +1,15 @@ package com.lesfurets.jenkins.unit.declarative -class ParametersDeclaration extends GenericPipelineDeclaration { +class ParametersDeclaration { + Binding binding - void setParams(String key, Object val) { - Map params = this.params - if (params != null && (!params.containsKey(key))) { - params[key] = val + void setParams(String key, Object defaultValue) { + if (!binding.hasVariable("params")) { + binding.setVariable("params", [:]) + } + if (!binding.params.containsKey(key)) { + binding.params[key] = defaultValue } } diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/PostDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/PostDeclaration.groovy index fb36eec4..64f4dcba 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/PostDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/PostDeclaration.groovy @@ -1,6 +1,6 @@ package com.lesfurets.jenkins.unit.declarative -import static com.lesfurets.jenkins.unit.declarative.DeclarativePipeline.executeOn +import static com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration.executeWith class PostDeclaration { @@ -55,52 +55,52 @@ class PostDeclaration { this.regression = closure } - def execute(Object delegate) { - def currentBuild = delegate.currentBuild.result - def previousBuild = delegate.currentBuild?.previousBuild?.result + def execute(Script script) { + def currentBuild = script.currentBuild.result + def previousBuild = script.currentBuild?.previousBuild?.result if (this.always) { - executeOn(delegate, this.always) + executeWith(script, this.always) } switch (currentBuild) { case 'SUCCESS': - executeOn(delegate, this.success) + executeWith(script, this.success) break case 'FAILURE': - executeOn(delegate, this.failure) + executeWith(script, this.failure) break case 'ABORTED': - executeOn(delegate, this.aborted) + executeWith(script,this.aborted) break case 'UNSTABLE': - executeOn(delegate, this.unstable) + executeWith(script,this.unstable) break } if(currentBuild != previousBuild && this.changed) { - executeOn(delegate, this.changed) + executeWith(script,this.changed) } if(currentBuild != 'SUCCESS' && this.unsuccessful) { - executeOn(delegate, this.unsuccessful) + executeWith(script, this.unsuccessful) } if(this.fixed){ if(currentBuild == 'SUCCESS' && (previousBuild == 'FAILURE' || previousBuild == 'UNSTABLE')) { - executeOn(delegate, this.fixed) + executeWith(script, this.fixed) } } if(this.regression) { if((currentBuild == 'FAILURE' || currentBuild == 'UNSTABLE') && previousBuild == 'SUCCESS'){ - executeOn(delegate, this.regression) + executeWith(script, this.regression) } } // Cleanup is always performed last if(this.cleanup){ - executeOn(delegate, this.cleanup) + executeWith(script, this.cleanup) } } diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy index f3a38fd1..2a4d0955 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/StageDeclaration.groovy @@ -1,8 +1,5 @@ package com.lesfurets.jenkins.unit.declarative - -import static groovy.lang.Closure.* - class StageDeclaration extends GenericPipelineDeclaration { String name @@ -24,52 +21,63 @@ class StageDeclaration extends GenericPipelineDeclaration { this.failFast = failFast } - def getBinding_var() { - return binding?.var - } - - def parallel(@DelegatesTo(strategy = DELEGATE_FIRST, value = ParallelDeclaration) Closure closure) { - this.parallel = createComponent(ParallelDeclaration, closure).with { it.failFast = failFast; it } + def parallel(Closure closure) { + this.parallel = new ParallelDeclaration(failFast); + executeWith(this.parallel, closure); } - def when(@DelegatesTo(strategy = DELEGATE_FIRST, value = WhenDeclaration) Closure closure) { - this.when = createComponent(WhenDeclaration, closure) + def when(Closure closure) { + this.when = new WhenDeclaration(); + executeWith(this.when, closure) } - def options(@DelegatesTo(StageDeclaration) Closure closure) { + def options(Closure closure) { options.add(closure) } - def execute(Object delegate) { + def execute(Script script) { String name = this.name this.options.each { - executeOn(delegate, it) + executeWith(script, it) } - if(parallel) { - parallel.execute(delegate) + if (parallel) { + parallel.execute(script) } - if(delegate.binding.variables.currentBuild.result == "FAILURE"){ - executeWith(delegate, { echo "Stage \"$name\" skipped due to earlier failure(s)" }) + if (script.currentBuild.result == "FAILURE") { + executeWith(script, { echo "Stage \"$name\" skipped due to earlier failure(s)" }) return } - if (!when || when.execute(delegate)) { - super.execute(delegate) + if (!when || when.execute(script)) { + Map envValuestoRestore = [:] + + // set environment + if (this.environment) { + envValuestoRestore = initEnvironment(this.environment, script) + } + // TODO handle credentials - this.stages.entrySet().forEach { e -> - e.value.execute(delegate) + this.stages.entrySet().forEach { stageEntry -> + stageEntry.value.execute(script) } - if(steps) { - Closure stageBody = { agent?.execute(delegate) } >> steps.rehydrate(delegate, this, this) - Closure cl = { stage("$name", stageBody) } - executeWith(delegate, cl) + if (steps) { + Closure rehydratedSteps = steps.rehydrate(script, this, steps); + rehydratedSteps.setResolveStrategy(Closure.DELEGATE_FIRST) + Closure stageBody = { + agent?.execute(script) + } >> rehydratedSteps + Closure cl = { + stage("$name", stageBody) + } + executeWith(script, cl, Closure.DELEGATE_ONLY) } if (post) { - this.post.execute(delegate) + this.post.execute(script) } + resetEnvironment(envValuestoRestore, script) } else { - executeWith(delegate, { echo "Skipping stage $name" }) + executeWith(script, { echo "Skipping stage $name" }) } } diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/WhenDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/WhenDeclaration.groovy index bb434938..834d1b55 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/WhenDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/WhenDeclaration.groovy @@ -4,9 +4,9 @@ import org.springframework.util.AntPathMatcher import java.util.regex.Pattern -import static groovy.lang.Closure.DELEGATE_FIRST +import static com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration.executeWith -class WhenDeclaration extends GenericPipelineDeclaration { +class WhenDeclaration { AllOfDeclaration allOf AnyOfDeclaration anyOf @@ -23,16 +23,19 @@ class WhenDeclaration extends GenericPipelineDeclaration { return Pattern.compile('^' + Pattern.quote(glob).replace('*', '\\E.*\\Q').replace('?', '\\E.\\Q') + '$') } - def allOf(@DelegatesTo(strategy = DELEGATE_FIRST, value = AllOfDeclaration) Closure closure) { - this.allOf = createComponent(AllOfDeclaration, closure) + def allOf(Closure closure) { + this.allOf = new AllOfDeclaration() + executeWith(this.allOf, closure, Closure.DELEGATE_FIRST) } - def anyOf(@DelegatesTo(strategy = DELEGATE_FIRST, value = AnyOfDeclaration) Closure closure) { - this.anyOf = createComponent(AnyOfDeclaration, closure) + def anyOf(Closure closure) { + this.anyOf = new AnyOfDeclaration(); + executeWith(this.anyOf, closure, Closure.DELEGATE_FIRST); } - def not(@DelegatesTo(strategy = DELEGATE_FIRST, value = NotDeclaration) Closure closure) { - this.not = createComponent(NotDeclaration, closure) + def not(Closure closure) { + this.not = new NotDeclaration(); + executeWith(this.not, closure, Closure.DELEGATE_FIRST) } def branch (String name) { @@ -56,7 +59,7 @@ class WhenDeclaration extends GenericPipelineDeclaration { this.envValue = args.value as String } - Boolean execute(Object delegate) { + Boolean execute(Script script) { boolean expressionCheck = true boolean branchCheck = true boolean tagCheck = true @@ -66,29 +69,29 @@ class WhenDeclaration extends GenericPipelineDeclaration { boolean notCheck = true if (allOf) { - allOfCheck = allOf.execute(delegate) + allOfCheck = allOf.execute(script) } if (anyOf) { - anyOfCheck = anyOf.execute(delegate) + anyOfCheck = anyOf.execute(script) } if (not) { - notCheck = not.execute(delegate) + notCheck = not.execute(script) } if (expression) { - expressionCheck = executeWith(delegate, expression) + expressionCheck = executeWith(script, expression) } if (branch) { AntPathMatcher antPathMatcher = new AntPathMatcher() - branchCheck = antPathMatcher.match(branch, delegate.env.BRANCH_NAME) + branchCheck = antPathMatcher.match(branch, script.env.BRANCH_NAME) } if (buildingTag) { - tagCheck = delegate?.env?.containsKey("TAG_NAME") + tagCheck = script?.env?.containsKey("TAG_NAME") } if (tag) { - tagCheck = delegate.env.TAG_NAME =~ tag + tagCheck = script.env.TAG_NAME =~ tag } if (envName != null) { - def val = delegate?.env[envName] + def val = script?.env[envName] envCheck = (val == envValue) } diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/agent/DockerAgentDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/agent/DockerAgentDeclaration.groovy index 2febf1ec..93d631fc 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/agent/DockerAgentDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/agent/DockerAgentDeclaration.groovy @@ -1,13 +1,12 @@ package com.lesfurets.jenkins.unit.declarative.agent -import com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration import groovy.transform.Memoized import groovy.transform.ToString import static com.lesfurets.jenkins.unit.declarative.ObjectUtils.printNonNullProperties @ToString(includePackage = false, includeNames = true, ignoreNulls = true) -class DockerAgentDeclaration extends GenericPipelineDeclaration { +class DockerAgentDeclaration { String label String args = "" diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/agent/KubernetesAgentDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/agent/KubernetesAgentDeclaration.groovy index 9d0823c7..8bba30f3 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/agent/KubernetesAgentDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/agent/KubernetesAgentDeclaration.groovy @@ -6,25 +6,24 @@ import com.lesfurets.jenkins.unit.declarative.kubernetes.WorkspaceVolumeDeclarat import groovy.transform.Memoized import groovy.transform.ToString -import static com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration.createComponent +import static com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration.executeWith import static com.lesfurets.jenkins.unit.declarative.ObjectUtils.printNonNullProperties -import static groovy.lang.Closure.DELEGATE_FIRST @ToString(includePackage = false, includeNames = true, ignoreNulls = true) -class KubernetesAgentDeclaration extends GenericPipelineDeclaration { +class KubernetesAgentDeclaration { String label; String customWorkspace; String cloud; String inheritFrom; - int idleMinutes; - int instanceCap; + Integer idleMinutes; + Integer instanceCap; String serviceAccount; String nodeSelector; String namespace; String workingDir; - int activeDeadlineSeconds; - int slaveConnectTimeout; + Integer activeDeadlineSeconds; + Integer slaveConnectTimeout; String podRetention; ContainerTemplateDeclaration containerTemplate; List containerTemplates; @@ -87,13 +86,16 @@ class KubernetesAgentDeclaration extends GenericPipelineDeclaration { this.podRetention = podRetention } - def containerTemplate(@DelegatesTo(strategy = DELEGATE_FIRST, value = ContainerTemplateDeclaration) Closure closure) { - this.containerTemplate = createComponent(ContainerTemplateDeclaration, closure) + def containerTemplate(Closure closure) { + this.containerTemplate = new ContainerTemplateDeclaration(); + executeWith(this.containerTemplate, closure) } - def containerTemplates(@DelegatesTo(strategy = DELEGATE_FIRST, value = ContainerTemplateDeclaration) List closures) { - this.containerTemplates = closures.each { ct -> - return createComponent(ContainerTemplateDeclaration, ct) + def containerTemplates(List closures) { + this.containerTemplates = closures.collect { ctClosure -> + def containerTemplateDeclaration = new ContainerTemplateDeclaration(); + executeWith(containerTemplateDeclaration, ctClosure) + return containerTemplateDeclaration; } as List } @@ -113,8 +115,9 @@ class KubernetesAgentDeclaration extends GenericPipelineDeclaration { this.yamlMergeStrategy = yamlMergeStrategy } - def workspaceVolume(@DelegatesTo(strategy = DELEGATE_FIRST, value = WorkspaceVolumeDeclaration) Closure closure) { - this.workspaceVolume = createComponent(WorkspaceVolumeDeclaration, closure) + def workspaceVolume(Closure closure) { + this.workspaceVolume = new WorkspaceVolumeDeclaration(); + executeWith(this.workspaceVolume, closure) } def supplementalGroups(final String supplementalGroups) { diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/ContainerLivenessProbeDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/ContainerLivenessProbeDeclaration.groovy index 8951a4aa..a541fbbc 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/ContainerLivenessProbeDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/ContainerLivenessProbeDeclaration.groovy @@ -1,8 +1,6 @@ package com.lesfurets.jenkins.unit.declarative.kubernetes -import com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration - -class ContainerLivenessProbeDeclaration extends GenericPipelineDeclaration { +class ContainerLivenessProbeDeclaration { String execArgs int timeoutSeconds diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/ContainerTemplateDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/ContainerTemplateDeclaration.groovy index 555a6983..9613a0ff 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/ContainerTemplateDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/ContainerTemplateDeclaration.groovy @@ -4,12 +4,11 @@ import com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration import groovy.transform.Memoized import groovy.transform.ToString -import static com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration.createComponent +import static com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration.executeWith import static com.lesfurets.jenkins.unit.declarative.ObjectUtils.printNonNullProperties -import static groovy.lang.Closure.DELEGATE_FIRST @ToString(includePackage = false, includeNames = true, ignoreNulls = true) -class ContainerTemplateDeclaration extends GenericPipelineDeclaration { +class ContainerTemplateDeclaration { String name; String image; @@ -90,14 +89,17 @@ class ContainerTemplateDeclaration extends GenericPipelineDeclaration { this.shell = shell } - def ports(@DelegatesTo(strategy = DELEGATE_FIRST, value = PortMappingDeclaration) List closures) { + def ports(List closures) { this.ports = closures.each { ct -> - return createComponent(PortMappingDeclaration, ct) + def portMappingDeclaration = new PortMappingDeclaration() + executeWith(portMappingDeclaration, closure) + return portMappingDeclaration } as List } - def livenessProbe(@DelegatesTo(strategy = DELEGATE_FIRST, value = ContainerLivenessProbeDeclaration) Closure closure) { - this.livenessProbe = createComponent(ContainerLivenessProbeDeclaration, ct) + def livenessProbe(Closure closure) { + this.livenessProbe = new ContainerLivenessProbeDeclaration(); + executeWith(this.livenessProbe, closure) } @Memoized diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/PodTemplateDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/PodTemplateDeclaration.groovy index 2a9dc9b8..a1838446 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/PodTemplateDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/PodTemplateDeclaration.groovy @@ -1,7 +1,4 @@ package com.lesfurets.jenkins.unit.declarative.kubernetes -import com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration - - -class PodTemplateDeclaration extends GenericPipelineDeclaration { +class PodTemplateDeclaration { } diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/PortMappingDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/PortMappingDeclaration.groovy index 03f56ffa..513293df 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/PortMappingDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/PortMappingDeclaration.groovy @@ -1,13 +1,13 @@ package com.lesfurets.jenkins.unit.declarative.kubernetes -import com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration + import groovy.transform.Memoized import groovy.transform.ToString import static com.lesfurets.jenkins.unit.declarative.ObjectUtils.printNonNullProperties @ToString(includePackage = false, includeNames = true, ignoreNulls = true) -class PortMappingDeclaration extends GenericPipelineDeclaration { +class PortMappingDeclaration { String name int containerPort int hostPort diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/TemplateEnvVarDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/TemplateEnvVarDeclaration.groovy index 9948ee8a..d72b3e42 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/TemplateEnvVarDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/TemplateEnvVarDeclaration.groovy @@ -1,8 +1,6 @@ package com.lesfurets.jenkins.unit.declarative.kubernetes -import com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration - -class TemplateEnvVarDeclaration extends GenericPipelineDeclaration { +class TemplateEnvVarDeclaration { KeyValueVar containerEnvVar; KeyValueVar envVar; diff --git a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/WorkspaceVolumeDeclaration.groovy b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/WorkspaceVolumeDeclaration.groovy index e0918009..0e6f7fdc 100644 --- a/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/WorkspaceVolumeDeclaration.groovy +++ b/src/main/groovy/com/lesfurets/jenkins/unit/declarative/kubernetes/WorkspaceVolumeDeclaration.groovy @@ -5,10 +5,9 @@ import groovy.transform.Memoized import groovy.transform.ToString import static com.lesfurets.jenkins.unit.declarative.ObjectUtils.printNonNullProperties -import static groovy.lang.Closure.DELEGATE_FIRST @ToString(includePackage = false, includeNames = true, ignoreNulls = true) -class WorkspaceVolumeDeclaration extends GenericPipelineDeclaration { +class WorkspaceVolumeDeclaration { DynamicWorkspaceVolume dynamicPVC EmptyDirWorkspaceVolume emptyDirWorkspaceVolume @@ -16,24 +15,31 @@ class WorkspaceVolumeDeclaration extends GenericPipelineDeclaration { NfsWorkspaceVolume nfsWorkspaceVolume PersistentVolumeClaimWorkspaceVolume persistentVolumeClaimWorkspaceVolume - void dynamicPVC(@DelegatesTo(strategy = DELEGATE_FIRST, value = DynamicWorkspaceVolume) Closure closure) { - this.dynamicPVC = createComponent(DynamicWorkspaceVolume, closure) + void dynamicPVC(Closure closure) { + this.dynamicPVC = new DynamicWorkspaceVolume(); + GenericPipelineDeclaration.executeWith(this.dynamicPVC, closure); } - void emptyDirWorkspaceVolume(@DelegatesTo(strategy = DELEGATE_FIRST, value = EmptyDirWorkspaceVolume) Closure closure) { - this.emptyDirWorkspaceVolume = createComponent(EmptyDirWorkspaceVolume, closure) + void emptyDirWorkspaceVolume(Closure closure) { + this.emptyDirWorkspaceVolume = new EmptyDirWorkspaceVolume(); + closure.delegate= this.emptyDirWorkspaceVolume; + closure.call(); } - void hostPathWorkspaceVolume(@DelegatesTo(strategy = DELEGATE_FIRST, value = HostPathWorkspaceVolume) Closure closure) { - this.hostPathWorkspaceVolume = createComponent(HostPathWorkspaceVolume, closure) + void hostPathWorkspaceVolume(Closure closure) { + this.hostPathWorkspaceVolume = new HostPathWorkspaceVolume(); + GenericPipelineDeclaration.executeWith(this.hostPathWorkspaceVolume, closure); + } - void nfsWorkspaceVolume(@DelegatesTo(strategy = DELEGATE_FIRST, value = NfsWorkspaceVolume) Closure closure) { - nfsWorkspaceVolume = createComponent(NfsWorkspaceVolume, closure) + void nfsWorkspaceVolume(Closure closure) { + nfsWorkspaceVolume = new NfsWorkspaceVolume(); + GenericPipelineDeclaration.executeWith(this.nfsWorkspaceVolume, closure); } - void persistentVolumeClaimWorkspaceVolume(@DelegatesTo(strategy = DELEGATE_FIRST, value = PersistentVolumeClaimWorkspaceVolume) Closure closure) { - persistentVolumeClaimWorkspaceVolume = createComponent(PersistentVolumeClaimWorkspaceVolume, closure) + void persistentVolumeClaimWorkspaceVolume(Closure closure) { + persistentVolumeClaimWorkspaceVolume = new PersistentVolumeClaimWorkspaceVolume(); + GenericPipelineDeclaration.executeWith(this.persistentVolumeClaimWorkspaceVolume, closure); } @Memoized diff --git a/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy b/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy index 47f9a246..dd793d72 100644 --- a/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy +++ b/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativePipeline.groovy @@ -453,10 +453,19 @@ class TestDeclarativePipeline extends DeclarativePipelineTest { runScript('Environment_Jenkinsfile') printCallStack() assertCallStack().contains('echo(LEVAR1 LE NEW VALUE)') + assertCallStack().contains('echo(LEVAR1 LE NEW VALUE without pefixing env)') assertCallStack().contains('echo(LEVAR2 A COPY OF LE NEW VALUE in build#1)') assertJobStatusSuccess() } + @Test void should_be_able_to_access_upper_score_var() throws Exception { + String envVarValue = "envVarValue" + addEnvVar("envVar", envVarValue) + runScript('Scoping_Jenkinsfile') + assertCallStack().contains("echo(Upperscoped string : UpperScope string with envVar: $envVarValue)") + printCallStack() + } + @Test void not_running_stage_after_failure() throws Exception { runScript('StageFailed_Jenkinsfile') printCallStack() @@ -493,8 +502,7 @@ class TestDeclarativePipeline extends DeclarativePipelineTest { } @Test void agent_with_mock_param_label() throws Exception { - def params = binding.getVariable('params') - params['AGENT'] = 'mockSlave' + addParam('AGENT', 'mockSlave') runScript('AgentParam_Jenkinsfile') printCallStack() assertCallStack().contains('mockSlave') @@ -524,4 +532,11 @@ class TestDeclarativePipeline extends DeclarativePipelineTest { assertJobStatusSuccess() } + @Test void jenkinsfile_thisObject() throws Exception { + def script = runScript('Declarative_thisObject_JenkinsFile') + printCallStack() + assertJobStatusSuccess() + assertCallStack().doesNotContain("This is a script?: false") + assertCallStack().contains("This is a script?: true") + } } diff --git a/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclaraticeWithCredentials.groovy b/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativeWithCredentials.groovy similarity index 95% rename from src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclaraticeWithCredentials.groovy rename to src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativeWithCredentials.groovy index e82ae780..d113d2b5 100644 --- a/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclaraticeWithCredentials.groovy +++ b/src/test/groovy/com/lesfurets/jenkins/unit/declarative/TestDeclarativeWithCredentials.groovy @@ -6,7 +6,7 @@ import org.junit.Test import static org.junit.Assert.assertTrue -class TestDeclaraticeWithCredentials extends DeclarativePipelineTest { +class TestDeclarativeWithCredentials extends DeclarativePipelineTest { @Override @Before diff --git a/src/test/jenkins/jenkinsfiles/Declarative_thisObject_JenkinsFile b/src/test/jenkins/jenkinsfiles/Declarative_thisObject_JenkinsFile new file mode 100644 index 00000000..accf0778 --- /dev/null +++ b/src/test/jenkins/jenkinsfiles/Declarative_thisObject_JenkinsFile @@ -0,0 +1,50 @@ +pipeline { + + agent any + + environment { + CC = testThis(this, 'gcc') + } + + options { + buildDiscarder(logRotator(numToKeepStr: testThis(this, '10'))) + } + + triggers { + pollSCM(testThis(this, '*/5 * * * *')) + } + + stages { + stage('Checkout') { + when { + environment name: 'CC', value: testThis(this, 'clang') + } + steps { + echo testThis(this, "Steps") + } + } + + stage('build') { + agent { docker testThis(this, 'maven:3-alpine') } + options { + timeout(time: 20, unit: 'MINUTES') + } + steps { + withEnv(["GRADLE_HOME=${tool name: 'GRADLE_3', type: 'hudson.plugins.gradle.GradleInstallation'}"]) { + echo testThis(this, "In env") + } + } + } + } + + post { + always { + echo testThis(this, 'pipeline unit tests completed') + } + + } +} + +String testThis(Script scriptRef, String text){ + return "$text: This is a script?: ${scriptRef instanceof Script}" +} \ No newline at end of file diff --git a/src/test/jenkins/jenkinsfiles/Environment_Jenkinsfile b/src/test/jenkins/jenkinsfiles/Environment_Jenkinsfile index 288910a0..9afee301 100644 --- a/src/test/jenkins/jenkinsfiles/Environment_Jenkinsfile +++ b/src/test/jenkins/jenkinsfiles/Environment_Jenkinsfile @@ -11,6 +11,7 @@ pipeline { } steps { echo "LEVAR1 ${env.LEVAR1}" + echo "LEVAR1 ${LEVAR1} without pefixing env" echo "LEVAR2 ${env.LEVAR2}" } } diff --git a/src/test/jenkins/jenkinsfiles/Scoping_Jenkinsfile b/src/test/jenkins/jenkinsfiles/Scoping_Jenkinsfile new file mode 100644 index 00000000..a46eb140 --- /dev/null +++ b/src/test/jenkins/jenkinsfiles/Scoping_Jenkinsfile @@ -0,0 +1,16 @@ +def call() { + String upperscopeSTring = "UpperScope string with envVar: ${envVar}" + + pipeline { + agent upperscopeSTring + stages { + stage('Echo stage') { + steps { + echo "Upperscoped string : $upperscopeSTring" + } + } + } + } +} + +call() \ No newline at end of file