Skip to content

Commit ca25fe8

Browse files
authored
Merge pull request #20 from raydouglass/list-excludes
Allow for lists as values in excludes mappings
2 parents 8f0fcd2 + c077263 commit ca25fe8

File tree

5 files changed

+121
-10
lines changed

5 files changed

+121
-10
lines changed

README.md

+38-2
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,16 @@ Generate yaml based matrix and run job :muscle:
6262
6363
## Detail
6464
### Excluding logic
65-
Excluding pattern may be specified with `List` of `Map` (e.g. `List<Map<String, String>>`)
65+
Excluding pattern may be specified with `List` of `Map` (e.g. `List<Map<String, [String or List]>>`)
6666

67+
Elements in the `Map` may be a List to exclude multiple items for one key
6768
```yaml
6869
# axis.yml
6970
exclude:
7071
- RUBY_VERSION: 2.1.8
7172
- RUBY_VERSION: 2.3.0
7273
DATABASE: oracle
7374
```
74-
7575
When specified 2 axes
7676

7777
![axis](doc/axis.png)
@@ -86,3 +86,39 @@ This results in a 3x3 build matrix.
8686
* `RUBY_VERSION` value `2.1.8` and `DATABASE` value `oracle` is excluded
8787
* When specified `RUBY_VERSION` value `2.3.0` and `DATABASE` value `oracle`, 1 result is excluded
8888
* `RUBY_VERSION` value `2.3.0` and `DATABASE` value `oracle` is excluded
89+
90+
#### Another example
91+
```yaml
92+
# axis2.yml
93+
exclude:
94+
- RUBY_VERSION: 2.1.8
95+
- RUBY_VERSION: 2.3.0
96+
DATABASE:
97+
- oracle
98+
- mysql
99+
```
100+
* When specified `RUBY_VERSION` value `2.1.8`, 3 results are excluded
101+
* `RUBY_VERSION` value `2.1.8` and `DATABASE` value `mysql` is excluded
102+
* `RUBY_VERSION` value `2.1.8` and `DATABASE` value `postgres` is excluded
103+
* `RUBY_VERSION` value `2.1.8` and `DATABASE` value `oracle` is excluded
104+
* When specified `RUBY_VERSION` value `2.3.0`, 2 results are excluded
105+
* `RUBY_VERSION` value `2.3.0` and `DATABASE` value `oracle` is excluded
106+
* `RUBY_VERSION` value `2.3.0` and `DATABASE` value `mysql` is excluded
107+
108+
#### Final example
109+
Using multiple lists will exclude the cartesian product of those lists.
110+
```yaml
111+
# axis3.yml
112+
exclude:
113+
- RUBY_VERSION:
114+
- 2.1.8
115+
- 2.3.0
116+
DATABASE:
117+
- oracle
118+
- mysql
119+
```
120+
* 4 results are excluded
121+
* `RUBY_VERSION` value `2.1.8` and `DATABASE` value `mysql` is excluded
122+
* `RUBY_VERSION` value `2.1.8` and `DATABASE` value `oracle` is excluded
123+
* `RUBY_VERSION` value `2.3.0` and `DATABASE` value `oracle` is excluded
124+
* `RUBY_VERSION` value `2.3.0` and `DATABASE` value `mysql` is excluded

src/main/groovy/org/jenkinsci/plugins/yamlaxis/YamlLoader.groovy

+9-2
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,21 @@ abstract class YamlLoader {
1515
* @param key
1616
* @return if key is not found, return null
1717
*/
18-
List<Map<String, String>> loadMaps(String key){
18+
List<Map<String, ?>> loadMaps(String key){
1919
Map content = getContent()
2020
def values = content.get(key)
2121
if(values == null){
2222
return null
2323
}
2424
values.collect {
25-
it.collectEntries { k, v -> [k, v.toString()] }
25+
it.collectEntries { k, v ->
26+
if(v instanceof List){
27+
[k, v.collect { it.toString() }]
28+
}else{
29+
[k, v.toString()]
30+
}
31+
}
32+
2633
}
2734
}
2835

src/main/groovy/org/jenkinsci/plugins/yamlaxis/YamlMatrixExecutionStrategy.groovy

+40-1
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,53 @@ class YamlMatrixExecutionStrategy extends BaseMES {
6262
BuildUtils.log(execution, "[WARN] NotFound excludeKey ${excludeKey}")
6363
return []
6464
}
65-
values.collect { new Combination(it) }
65+
collectExcludeCombinations(values)
6666

6767
} catch (IOException e) {
6868
BuildUtils.log(execution, "[WARN] Can not read yamlFile: ${yamlFile}", e)
6969
[]
7070
}
7171
}
7272

73+
public static List<Combination> collectExcludeCombinations(List<Map<String, ?>> excludes) {
74+
List<Map<String, String>> result = []
75+
for (value in excludes) {
76+
List<Map<String, String>> combos = []
77+
boolean isList = false
78+
for (Map.Entry<String, ?> entry in value) {
79+
if (entry.value instanceof List) {
80+
isList = true
81+
List<Map<String, String>> newCombos = []
82+
for (def v in entry.value) {
83+
if (combos) {
84+
for (def c in combos) {
85+
Map<String, String> clone = new HashMap<>(c)
86+
clone.put(entry.key, v)
87+
newCombos.add(clone)
88+
}
89+
} else {
90+
newCombos.add([(entry.key): v])
91+
}
92+
}
93+
combos = newCombos
94+
}
95+
}
96+
if (isList) {
97+
for (Map.Entry<String, ?> entry in value) {
98+
if (entry.value instanceof String) {
99+
for (def c in combos) {
100+
c.put(entry.key, entry.value)
101+
}
102+
}
103+
}
104+
} else {
105+
combos.add(value)
106+
}
107+
result.addAll(combos)
108+
}
109+
result.collect { new Combination(it) }
110+
}
111+
73112
private YamlLoader getYamlLoader(MatrixBuild.MatrixBuildExecution execution){
74113
switch(yamlType){
75114
case YamlFileLoader.RADIO_VALUE:

src/test/groovy/org/jenkinsci/plugins/yamlaxis/YamlMatrixExecutionStrategySpec.groovy

+12-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class YamlMatrixExecutionStrategySpec extends Specification {
3030
def "run"() {
3131
setup:
3232
def matrixProject = configure()
33-
List<Combination> excludeCombinations = excludes.collect { new Combination(it) }
33+
List<Combination> excludeCombinations = YamlMatrixExecutionStrategy.collectExcludeCombinations(excludes)
3434
matrixProject.executionStrategy = new YamlMatrixExecutionStrategy(excludeCombinations)
3535
def build = matrixProject.scheduleBuild2(0).get()
3636

@@ -40,9 +40,16 @@ class YamlMatrixExecutionStrategySpec extends Specification {
4040
build.runs.size() == runsCount
4141

4242
where:
43-
excludes || runsCount
44-
[] || 9
45-
[[axis1: "c", axis2: "z"]] || 8
46-
[[axis1: "c"]] || 6
43+
excludes || runsCount
44+
[] || 9
45+
[[axis1: "c", axis2: "z"]] || 8
46+
[[axis1: "c", axis2: ["z"]]] || 8
47+
[[axis1: ["c"], axis2: "z"]] || 8
48+
[[axis1: ["c"], axis2: ["z"]]] || 8
49+
[[axis1: "c"]] || 6
50+
[[axis1: ["b", "c"]]] || 3
51+
[[axis1: "b"], [axis1: "c"]] || 3
52+
[[axis1: "b", axis2: ["x", "y"]]] || 7
53+
[[axis1: ["a", "b"], axis2: ["x", "y"]]] || 5
4754
}
4855
}

src/test/groovy/org/jenkinsci/plugins/yamlaxis/YamlTextLoaderSpock.groovy

+22
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,26 @@ exclude:
5252
"exclude" || [[a: "1", b: "2"], [c: "3"]]
5353
"not_found" || null
5454
}
55+
56+
def "loadValuesList"(){
57+
setup:
58+
String yamlText = """
59+
exclude:
60+
- a: 1
61+
b:
62+
- 2
63+
- 3
64+
- c: 4
65+
"""
66+
67+
def loader = new YamlTextLoader(yamlText: yamlText)
68+
69+
expect:
70+
loader.loadMaps(key) == expected
71+
72+
where:
73+
key || expected
74+
"exclude" || [[a: "1", b: ["2", "3"]], [c: "4"]]
75+
"not_found" || null
76+
}
5577
}

0 commit comments

Comments
 (0)