Skip to content

Commit 002c650

Browse files
committed
TEP-0090: Matrix - Consume Results
[TEP-0090: Matrix][tep-0090] proposed executing a `PipelineTask` in parallel `TaskRuns` and `Runs` with substitutions from combinations of `Parameters` in a `Matrix`. In this change, we implement consuming `Results` in a `Matrix`. This was disallowed in previous iterations of `Matrix` - validation failed. With this change, `Matrix` supports Results of type String that are passed in individually. `Results` of type Array are not yet available at the `Pipeline` level - this will be handled when it's available. [tep-0090]: https://github.com/tektoncd/community/blob/main/teps/0090-matrix.md
1 parent df074f2 commit 002c650

File tree

12 files changed

+960
-18
lines changed

12 files changed

+960
-18
lines changed

docs/matrix.md

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,39 @@ Similarly to the `Parameters` in the `Params` field, the `Parameters` in the `Ma
160160
#### Specifying Results in a Matrix
161161

162162
Consuming `Results` from previous `TaskRuns` or `Runs` in a `Matrix`, which would dynamically generate
163-
`TaskRuns` or `Runs` from the fanned out `PipelineTask`, is not yet supported. This dynamic fan out of
164-
`PipelineTasks` through consuming `Results` will be supported soon.
163+
`TaskRuns` or `Runs` from the fanned out `PipelineTask`, is supported.
164+
165+
`Matrix` supports Results of type String that are passed in individually:
166+
167+
```yaml
168+
tasks:
169+
...
170+
- name: task-4
171+
taskRef:
172+
name: task-4
173+
matrix:
174+
- name: values
175+
value:
176+
- (tasks.task-1.results.foo) # string
177+
- (tasks.task-2.results.bar) # string
178+
- (tasks.task-3.results.rad) # string
179+
```
180+
181+
For further information, see the example in [`PipelineRun` with `Matrix` and `Results`][pr-with-matrix-and-results].
182+
183+
When we support `Results` of type Array at the `Pipeline` level, we will support passing Results into the `Matrix`.
184+
> Note: Results of type Array are not yet supported in the Pipeline level.
185+
186+
```yaml
187+
tasks:
188+
...
189+
- name: task-5
190+
taskRef:
191+
name: task-5
192+
matrix:
193+
- name: values
194+
value: (tasks.task-4.results.foo) # array
195+
```
165196

166197
#### Results from fanned out PipelineTasks
167198

@@ -490,4 +521,5 @@ status:
490521
```
491522

492523
[cel]: https://github.com/tektoncd/experimental/tree/1609827ea81d05c8d00f8933c5c9d6150cd36989/cel
493-
[pr-with-matrix]: ../examples/v1beta1/pipelineruns/alpha/pipelinerun-with-matrix.yaml
524+
[pr-with-matrix]: ../examples/v1beta1/pipelineruns/alpha/pipelinerun-with-matrix.yaml
525+
[pr-with-matrix-and-results]: ../examples/v1beta1/pipelineruns/alpha/pipelinerun-with-matrix-and-results.yaml
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
apiVersion: tekton.dev/v1beta1
2+
kind: Task
3+
metadata:
4+
name: platform-browsers
5+
annotations:
6+
description: |
7+
A task that does something cool with platforms and browsers
8+
spec:
9+
params:
10+
- name: platform
11+
- name: browser
12+
steps:
13+
- name: echo
14+
image: alpine
15+
script: |
16+
echo "$(params.platform) and $(params.browser)"
17+
---
18+
apiVersion: tekton.dev/v1beta1
19+
kind: PipelineRun
20+
metadata:
21+
generateName: matrixed-pr-
22+
spec:
23+
serviceAccountName: 'default'
24+
pipelineSpec:
25+
tasks:
26+
- name: get-platforms
27+
taskSpec:
28+
results:
29+
- name: one
30+
- name: two
31+
- name: three
32+
steps:
33+
- name: echo
34+
image: alpine
35+
script: |
36+
printf linux | tee /tekton/results/one
37+
printf mac | tee /tekton/results/two
38+
printf windows | tee /tekton/results/three
39+
- name: get-browsers
40+
taskSpec:
41+
results:
42+
- name: one
43+
- name: two
44+
- name: three
45+
steps:
46+
- name: echo
47+
image: alpine
48+
script: |
49+
printf chrome | tee /tekton/results/one
50+
printf safari | tee /tekton/results/two
51+
printf firefox | tee /tekton/results/three
52+
- name: platforms-and-browsers-dag
53+
matrix:
54+
- name: platform
55+
value:
56+
- $(tasks.get-platforms.results.one)
57+
- $(tasks.get-platforms.results.two)
58+
- $(tasks.get-platforms.results.three)
59+
- name: browser
60+
value:
61+
- $(tasks.get-browsers.results.one)
62+
- $(tasks.get-browsers.results.two)
63+
taskRef:
64+
name: platform-browsers

pkg/apis/pipeline/v1beta1/param_types.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -306,10 +306,6 @@ func validateParametersInTaskMatrix(matrix []Param) (errs *apis.FieldError) {
306306
if param.Value.Type != ParamTypeArray {
307307
errs = errs.Also(apis.ErrInvalidValue("parameters of type array only are allowed in matrix", "").ViaFieldKey("matrix", param.Name))
308308
}
309-
// results are not yet allowed in parameters in a matrix - dynamic fanning out will be supported in future milestone
310-
if expressions, ok := GetVarSubstitutionExpressionsForParam(param); ok && LooksLikeContainsResultRefs(expressions) {
311-
return errs.Also(apis.ErrInvalidValue("result references are not allowed in parameters in a matrix", "value").ViaFieldKey("matrix", param.Name))
312-
}
313309
}
314310
return errs
315311
}

pkg/apis/pipeline/v1beta1/pipeline_types_test.go

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,24 @@ func TestPipelineTaskList_Deps(t *testing.T) {
469469
expectedDeps: map[string][]string{
470470
"task-2": {"task-1"},
471471
},
472+
}, {
473+
name: "valid pipeline with resource deps - Task Results in Matrix",
474+
tasks: []PipelineTask{{
475+
Name: "task-1",
476+
}, {
477+
Name: "task-2",
478+
Matrix: []Param{{
479+
Value: ArrayOrString{
480+
Type: ParamTypeArray,
481+
ArrayVal: []string{
482+
"$(tasks.task-1.results.result)",
483+
},
484+
}},
485+
}},
486+
},
487+
expectedDeps: map[string][]string{
488+
"task-2": {"task-1"},
489+
},
472490
}, {
473491
name: "valid pipeline with resource deps - When Expressions",
474492
tasks: []PipelineTask{{
@@ -515,12 +533,25 @@ func TestPipelineTaskList_Deps(t *testing.T) {
515533
Operator: "in",
516534
Values: []string{"foo"},
517535
}},
536+
}, {
537+
Name: "task-6",
538+
RunAfter: []string{"task-1"},
539+
Matrix: []Param{{
540+
Value: ArrayOrString{
541+
Type: ParamTypeArray,
542+
ArrayVal: []string{
543+
"$(tasks.task-2.results.result)",
544+
"$(tasks.task-5.results.result)",
545+
},
546+
}},
547+
},
518548
}},
519549
expectedDeps: map[string][]string{
520550
"task-2": {"task-1"},
521551
"task-3": {"task-1", "task-2"},
522552
"task-4": {"task-1", "task-3"},
523553
"task-5": {"task-1", "task-4"},
554+
"task-6": {"task-1", "task-2", "task-5"},
524555
},
525556
}, {
526557
name: "valid pipeline with ordering deps and resource deps - verify unique dependencies",
@@ -577,12 +608,45 @@ func TestPipelineTaskList_Deps(t *testing.T) {
577608
Operator: "in",
578609
Values: []string{"foo"},
579610
}},
611+
}, {
612+
Name: "task-6",
613+
RunAfter: []string{"task-1", "task-2", "task-3", "task-4", "task-5"},
614+
Resources: &PipelineTaskResources{
615+
Inputs: []PipelineTaskInputResource{{
616+
From: []string{"task-1", "task-2"},
617+
}},
618+
},
619+
Params: []Param{{
620+
Value: ArrayOrString{
621+
Type: "string",
622+
StringVal: "$(tasks.task-4.results.result)",
623+
}},
624+
},
625+
WhenExpressions: WhenExpressions{{
626+
Input: "$(tasks.task-3.results.result)",
627+
Operator: "in",
628+
Values: []string{"foo"},
629+
}, {
630+
Input: "$(tasks.task-4.results.result)",
631+
Operator: "in",
632+
Values: []string{"foo"},
633+
}},
634+
Matrix: []Param{{
635+
Value: ArrayOrString{
636+
Type: ParamTypeArray,
637+
ArrayVal: []string{
638+
"$(tasks.task-2.results.result)",
639+
"$(tasks.task-5.results.result)",
640+
},
641+
}},
642+
},
580643
}},
581644
expectedDeps: map[string][]string{
582645
"task-2": {"task-1"},
583646
"task-3": {"task-1", "task-2"},
584647
"task-4": {"task-1", "task-2", "task-3"},
585648
"task-5": {"task-1", "task-2", "task-3", "task-4"},
649+
"task-6": {"task-1", "task-2", "task-3", "task-4", "task-5"},
586650
},
587651
}}
588652
for _, tc := range pipelines {
@@ -743,10 +807,6 @@ func TestPipelineTask_validateMatrix(t *testing.T) {
743807
Name: "a-param", Value: ArrayOrString{Type: ParamTypeArray, ArrayVal: []string{"$(tasks.foo-task.results.a-result)"}},
744808
}},
745809
},
746-
wantErrs: &apis.FieldError{
747-
Message: "invalid value: result references are not allowed in parameters in a matrix",
748-
Paths: []string{"matrix[a-param].value"},
749-
},
750810
}, {
751811
name: "count of combinations of parameters in the matrix exceeds the maximum",
752812
pt: &PipelineTask{

pkg/apis/pipeline/v1beta1/pipeline_validation_test.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2895,10 +2895,6 @@ func Test_validateMatrix(t *testing.T) {
28952895
Name: "b-param", Value: ArrayOrString{Type: ParamTypeArray, ArrayVal: []string{"$(tasks.bar-task.results.b-result)"}},
28962896
}},
28972897
}},
2898-
wantErrs: &apis.FieldError{
2899-
Message: "invalid value: result references are not allowed in parameters in a matrix",
2900-
Paths: []string{"[0].matrix[a-param].value", "[1].matrix[b-param].value"},
2901-
},
29022898
}}
29032899
for _, tt := range tests {
29042900
t.Run(tt.name, func(t *testing.T) {

pkg/apis/pipeline/v1beta1/resultref.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ func parseExpression(substitutionExpression string) (string, string, int, string
185185
// in a PipelineTask and returns a list of any references that are found.
186186
func PipelineTaskResultRefs(pt *PipelineTask) []*ResultRef {
187187
refs := []*ResultRef{}
188-
for _, p := range pt.Params {
188+
for _, p := range append(pt.Params, pt.Matrix...) {
189189
expressions, _ := GetVarSubstitutionExpressionsForParam(p)
190190
refs = append(refs, NewResultRefs(expressions)...)
191191
}

pkg/apis/pipeline/v1beta1/resultref_test.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,11 @@ func TestPipelineTaskResultRefs(t *testing.T) {
652652
"$(tasks.pt4.results.r4)",
653653
},
654654
}},
655+
Matrix: []v1beta1.Param{{
656+
Value: *v1beta1.NewArrayOrString("$(tasks.pt5.results.r5)", "$(tasks.pt6.results.r6)"),
657+
}, {
658+
Value: *v1beta1.NewArrayOrString("$(tasks.pt7.results.r7)", "$(tasks.pt8.results.r8)"),
659+
}},
655660
}
656661
refs := v1beta1.PipelineTaskResultRefs(&pt)
657662
expectedRefs := []*v1beta1.ResultRef{{
@@ -666,8 +671,24 @@ func TestPipelineTaskResultRefs(t *testing.T) {
666671
}, {
667672
PipelineTask: "pt4",
668673
Result: "r4",
674+
}, {
675+
PipelineTask: "pt5",
676+
Result: "r5",
677+
}, {
678+
PipelineTask: "pt6",
679+
Result: "r6",
680+
}, {
681+
PipelineTask: "pt7",
682+
Result: "r7",
683+
}, {
684+
PipelineTask: "pt8",
685+
Result: "r8",
669686
}}
670-
if d := cmp.Diff(refs, expectedRefs); d != "" {
687+
if d := cmp.Diff(refs, expectedRefs, cmpopts.SortSlices(lessResultRef)); d != "" {
671688
t.Errorf("%v", d)
672689
}
673690
}
691+
692+
func lessResultRef(i, j *v1beta1.ResultRef) bool {
693+
return i.PipelineTask+i.Result < j.PipelineTask+i.Result
694+
}

0 commit comments

Comments
 (0)