Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic matrix section of Jenkinsfile #608

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.lesfurets.jenkins.unit.declarative

import com.lesfurets.jenkins.unit.declarative.matrix.MatrixDeclaration

import static groovy.lang.Closure.*

Expand All @@ -10,6 +11,7 @@ class StageDeclaration extends GenericPipelineDeclaration {
WhenDeclaration when
ParallelDeclaration parallel
boolean failFast = false
MatrixDeclaration matrix
List<Closure> options = []

StageDeclaration(String name) {
Expand All @@ -32,6 +34,10 @@ class StageDeclaration extends GenericPipelineDeclaration {
this.parallel = createComponent(ParallelDeclaration, closure).with { it.failFast = failFast; it }
}

def matrix(@DelegatesTo(strategy = DELEGATE_FIRST, value = MatrixDeclaration) Closure closure) {
this.matrix = createComponent(MatrixDeclaration, closure)
}

def when(@DelegatesTo(strategy = DELEGATE_FIRST, value = WhenDeclaration) Closure closure) {
this.when = createComponent(WhenDeclaration, closure)
}
Expand All @@ -46,6 +52,9 @@ class StageDeclaration extends GenericPipelineDeclaration {
if(parallel) {
actions++
}
if(matrix) {
actions++
}
if(stages.size()>0) {
actions++
}
Expand All @@ -64,6 +73,10 @@ class StageDeclaration extends GenericPipelineDeclaration {
parallel.execute(delegate)
}

if(matrix) {
matrix.execute(delegate)
}

if(delegate.binding.variables.currentBuild.result == "FAILURE"){
executeWith(delegate, { echo "Stage \"$name\" skipped due to earlier failure(s)" })
return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.lesfurets.jenkins.unit.declarative.matrix

import com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration
import groovy.transform.ToString

import static groovy.lang.Closure.DELEGATE_FIRST

@ToString(includePackage = false, includeNames = true, ignoreNulls = true)
class AxesDeclaration extends GenericPipelineDeclaration {
List<AxisDeclaration> axis = []

def axis(@DelegatesTo(strategy = DELEGATE_FIRST, value = AxisDeclaration) Closure closure) {
this.axis.add( createComponent(AxisDeclaration, closure))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.lesfurets.jenkins.unit.declarative.matrix


import com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration
import groovy.transform.ToString

@ToString(includePackage = false, includeNames = true, ignoreNulls = true)
class AxisDeclaration extends GenericPipelineDeclaration {

String name
List<String> values = []

def name(String name) {
this.name = name
}

def values(String... values) {
this.values = Arrays.asList(values)
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.lesfurets.jenkins.unit.declarative.matrix

import com.lesfurets.jenkins.unit.declarative.GenericPipelineDeclaration

import static groovy.lang.Closure.DELEGATE_FIRST

class MatrixDeclaration extends GenericPipelineDeclaration {

AxesDeclaration axes

def axes(@DelegatesTo(strategy = DELEGATE_FIRST, value = AxesDeclaration) Closure closure) {
this.axes = createComponent(AxesDeclaration, closure)
}

def execute(Object delegate) {
super.execute(delegate)

axes.axis.each {
it.name
it.values
}


axes.axis.combinations()
def matrixAxes = getMatrixAxes()
matrixAxes.each {
this.stages.entrySet().forEach { e ->
def savedEnv = [:]
def env = e.value.binding.getVariable('env') as Map
savedEnv.putAll(env)
env.putAll(it)
e.value.execute(delegate)
e.value.binding.setVariable('env', savedEnv)
}
}
}

private List<Map> getMatrixAxes() {
List calculatedAxes = []
axes.axis.each { axis ->
List axisList = []
axis.values.each { value ->
axisList << [(axis.name): value]
}
calculatedAxes << axisList
}
// calculate cartesian product
calculatedAxes.combinations()*.sum()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -796,5 +796,16 @@ class TestDeclarativePipeline extends DeclarativePipelineTest {
void test_stage_and_steps() {
runScript("StageAndSteps_Jenkinsfile")
}

@Test void should_matrix() throws Exception {
runScript('Matrix_Jenkinsfile')
printCallStack()
assertCallStack().contains('echo(axe_1_value_1 axe_2_value_1)')
assertCallStack().contains('echo(axe_1_value_1 axe_2_value_2)')
assertCallStack().contains('echo(axe_1_value_2 axe_2_value_1)')
assertCallStack().contains('echo(axe_1_value_2 axe_2_value_2)')
assertJobStatusSuccess()
}

}

26 changes: 26 additions & 0 deletions src/test/jenkins/jenkinsfiles/Matrix_Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
pipeline {
agent none
stages {
stage("stage") {
matrix {
axes {
axis {
name 'AXE_1'
values "axe_1_value_1", "axe_1_value_2"
}
axis {
name 'AXE_2'
values "axe_2_value_1", "axe_2_value_2"
}
}
stages {
stage("matrix stage") {
steps {
echo "${AXE_1} ${AXE_2}"
}
}
}
}
}
}
}
Loading