diff --git a/docs/matrix.md b/docs/matrix.md index f8f7505bffd..720ea1e1c9a 100644 --- a/docs/matrix.md +++ b/docs/matrix.md @@ -24,8 +24,10 @@ weight: 406 - [Results from fanned out PipelineTasks](#results-from-fanned-out-pipelinetasks) - [Retries](#retries) - [Examples](#examples) - - [`PipelineTasks` with `Tasks`](#pipelinetasks-with-tasks) - - [`PipelineTasks` with `Custom Tasks`](#pipelinetasks-with-custom-tasks) + - [`Matrix` Combinations with `Matrix.Params` only](#-matrix--combinations-with--matrixparams--only) + - [`Matrix` Combinations with `Matrix.Params` and `Matrix.Include`](#-matrix--combinations-with--matrixparams--and--matrixinclude-) + - [`PipelineTasks` with `Tasks`](#-pipelinetasks--with--tasks-) + - [`PipelineTasks` with `Custom Tasks`](#-pipelinetasks--with--custom-tasks-) ## Overview @@ -62,25 +64,95 @@ The `Matrix.Params` is used to generate combinations to fan out a `PipelineTask` ... ``` -### Explicit Combinations +Combinations generated -> :warning: This feature is in a preview mode. -> It is still in a very early stage of development and is not yet fully functional. +```json! +{ "platform": "linux", "browser": "safari" } +{ "platform": "linux", "browser": "chrome"} +{ "platform": "mac", "browser": "safari" } +{ "platform": "mac", "browser": "chrome"} +``` +[See another example](#-matrix--combinations-with--matrixparams--only) -The `Matrix.Include` is used to add explicit combinations to fan out a `PipelineTask`, but is not yet functional. +### Explicit Combinations + +The `Matrix.Include` is used to add explicit combinations to fan out a `PipelineTask`. ```yaml matrix: + params: + - name: platform + value: + - linux + - mac + - name: browser + value: + - safari + - chrome include: - - name: s390x-no-race + - name: linux-url params: - - name: GOARCH - value: "linux/s390x" - - name: flags - value: "-cover -v" + - name: platform + value: linux + - name: url + value: some-url + - name: non-existent-browser + params: + - name: browser + value: "i-do-not-exist" ... ``` +The first `Matrix.Include` clause adds `"url": "some-url"` only to the original `matrix` combinations that include `"platform": "linux"` and the second `Matrix.Include` clause cannot be added to any original `matrix` combination without overwriting any `params` of the original combinations, so it is added as an additional `matrix` combination: + +Combinations generated +```json! +{ "platform": "linux", "browser": "safari", "url": "some-url" } +{ "platform": "linux", "browser": "chrome", "url": "some-url"} +{ "platform": "mac", "browser": "safari" } +{ "platform": "mac", "browser": "chrome"} +{ "browser": "i-do-not-exist"} +``` + +[See another example](#-matrix--combinations-with--matrixparams--and--matrixinclude-) + +The `Matrix.Include` can also be used without `Matrix.Params` to generate explicit combinations to fan out a `PipelineTask`. + +```yaml + matrix: + include: + - name: build-1 + params: + - name: IMAGE + value: "image-1" + - name: DOCKERFILE + value: "path/to/Dockerfile1" + - name: build-2 + params: + - name: IMAGE + value: "image-2" + - name: DOCKERFILE + value: "path/to/Dockerfile2" + - name: build-3 + params: + - name: IMAGE + value: "image-3" + - name: DOCKERFILE + value: "path/to/Dockerfile3" + ... +``` + +This configuration allows users to take advantage of `Matrix` to fan out without having an auto-populated `Matrix`. `Matrix` with include section without `Params` section creates the number of `TaskRuns` specified in the `Include` section with the specified `Parameters`. + + +Combinations generated + +```json! +{ "IMAGE": "image-1", "DOCKERFILE": "path/to/Dockerfile1" } +{ "IMAGE": "image-2", "DOCKERFILE": "path/to/Dockerfile2"} +{ "IMAGE": "image-3", "DOCKERFILE": "path/to/Dockerfile3} +``` + ## Concurrency Control The default maximum count of `TaskRuns` or `Runs` from a given `Matrix` is **256**. To customize the maximum count of @@ -321,6 +393,123 @@ spec: ## Examples +### `Matrix` Combinations with `Matrix.Params` only + +```yaml +matrix: + params: + - name: GOARCH + value: + - "linux/amd64" + - "linux/ppc64le" + - "linux/s390x" + - name: version + value: + - "go1.17" + - "go1.18.1" +``` + +This `matrix` specification will result in six `taskRuns` with the following `matrix` combinations: + +```json! +{ "GOARCH": "linux/amd64", "version": "go1.17" } +{ "GOARCH": "linux/amd64", "version": "go1.18.1" } +{ "GOARCH": "linux/ppc64le", "version": "go1.17" } +{ "GOARCH": "linux/ppc64le", "version": "go1.18.1" } +{ "GOARCH": "linux/s390x", "version": "go1.17" } +{ "GOARCH": "linux/s390x", "version": "go1.18.1" } +``` + +Let's expand this use case to showcase a little more complex combinations in the next example. + +### `Matrix` Combinations with `Matrix.Params` and `Matrix.Include` + +Now, let's introduce `include` with a couple of `Parameters`: `"package"`, `"flags"` and `"context"`: + +```yaml + matrix: + params: + - name: GOARCH + value: + - "linux/amd64" + - "linux/ppc64le" + - "linux/s390x" + - name: version + value: + - "go1.17" + - "go1.18.1" + include: + - name: common-package + params: + - name: package + value: "path/to/common/package/" + - name: s390x-no-race + params: + - name: GOARCH + value: "linux/s390x" + - name: flags + value: "-cover -v" + + - name: go117-context + params: + - name: version + value: "go1.17" + - name: context + value: "path/to/go117/context" + - name: non-existent-arch + params: + - name: GOARCH + value: "I-do-not-exist" +``` + +The first `include` clause is added to all the original `matrix` combintations without overwriting any `parameters` of +the original combinations: + +```json! +{ "GOARCH": "linux/amd64", "version": "go1.17", **"package": "path/to/common/package/"** } +{ "GOARCH": "linux/amd64", "version": "go1.18.1", **"package": "path/to/common/package/"** } +{ "GOARCH": "linux/ppc64le", "version": "go1.17", **"package": "path/to/common/package/"** } +{ "GOARCH": "linux/ppc64le", "version": "go1.18.1", **"package": "path/to/common/package/"** } +{ "GOARCH": "linux/s390x", "version": "go1.17", **"package": "path/to/common/package/"** } +{ "GOARCH": "linux/s390x", "version": "go1.18.1", **"package": "path/to/common/package/"** } +``` + +The second `include` clause adds `"flags": "-cover -v"` only to the original `matrix` combinations that include +`"GOARCH": "linux/s390x"`: + +```json! +{ "GOARCH": "linux/s390x", "version": "go1.17", "package": "path/to/common/package/", **"flags": "-cover -v"** } +{ "GOARCH": "linux/s390x", "version": "go1.18.1", "package": "path/to/common/package/", **"flags": "-cover -v"** } +``` + +The third `include` clause adds `"context": "path/to/go117/context"` only to the original `matrix` combinations +that include `"version": "go1.17"`: + +```json! +{ "GOARCH": "linux/amd64", "version": "go1.17", "package": "path/to/common/package/", **"context": "path/to/go117/context"** } +{ "GOARCH": "linux/ppc64le", "version": "go1.17", "package": "path/to/common/package/", **"context": "path/to/go117/context"** } +{ "GOARCH": "linux/s390x", "version": "go1.17", "package": "path/to/common/package/", "flags": "-cover -v", **"context": "path/to/go117/context"** } +``` + +The fourth `include` clause cannot be added to any original `matrix` combination without overwriting any `params` of the +original combinations, so it is added as an additional `matrix` combination: + +```json! +* { **"GOARCH": "I-do-not-exist"** } +``` + +The above specification will result in seven `taskRuns` with the following matrix combinations: + +```json! +{ "GOARCH": "linux/amd64", "version": "go1.17", "package": "path/to/common/package/", "context": "path/to/go117/context" } +{ "GOARCH": "linux/amd64", "version": "go1.18.1", "package": "path/to/common/package/" } +{ "GOARCH": "linux/ppc64le", "version": "go1.17", "package": "path/to/common/package/", "context": "path/to/go117/context" } +{ "GOARCH": "linux/ppc64le", "version": "go1.18.1", "package": "path/to/common/package/" } +{ "GOARCH": "linux/s390x", "version": "go1.17", "package": "path/to/common/package/", "flags": "-cover -v", "context": "path/to/go117/context" } +{ "GOARCH": "linux/s390x", "version": "go1.18.1", "package": "path/to/common/package/", "flags": "-cover -v" } +{ "GOARCH": "I-do-not-exist" } +``` + ### `PipelineTasks` with `Tasks` When a `PipelineTask` has a `Task` and a `Matrix`, the `Task` will be executed in parallel `TaskRuns` with diff --git a/docs/pipeline-api.md b/docs/pipeline-api.md index 41fa555253c..176b6999d41 100644 --- a/docs/pipeline-api.md +++ b/docs/pipeline-api.md @@ -1481,8 +1481,7 @@ TaskSpec

IncludeParams

-

IncludeParams allows passing in a specific combinations of Parameters into the Matrix. -Note this struct is in preview mode and not yet supported

+

IncludeParams allows passing in a specific combinations of Parameters into the Matrix.

@@ -1562,8 +1561,7 @@ IncludeParamsList @@ -8614,8 +8612,7 @@ TaskSpec

IncludeParams

-

IncludeParams allows passing in a specific combinations of Parameters into the Matrix. -Note this struct is in preview mode and not yet supported

+

IncludeParams allows passing in a specific combinations of Parameters into the Matrix.

(Optional) -

Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix. -Note that Include is in preview mode and not yet supported.

+

Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix.

@@ -8695,8 +8692,7 @@ IncludeParamsList diff --git a/examples/v1beta1/pipelineruns/alpha/pipelinerun-with-matrix-include-explicit.yaml b/examples/v1beta1/pipelineruns/alpha/pipelinerun-with-matrix-include-explicit.yaml new file mode 100644 index 00000000000..90f99b2a15f --- /dev/null +++ b/examples/v1beta1/pipelineruns/alpha/pipelinerun-with-matrix-include-explicit.yaml @@ -0,0 +1,48 @@ +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: mytask + annotations: + description: | + A task that echoes image and dockerfile +spec: + params: + - name: IMAGE + - name: DOCKERFILE + steps: + - name: echo + image: alpine + script: | + echo "$(params.IMAGE) and $(params.DOCKERFILE)" +--- +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + generateName: explicit-combos +spec: + serviceAccountName: 'default' + pipelineSpec: + tasks: + - name: matrix-include + matrix: + include: + - name: build-1 + params: + - name: IMAGE + value: image-1 + - name: DOCKERFILE + value: path/to/Dockerfile1 + - name: build-2 + params: + - name: IMAGE + value: image-2 + - name: DOCKERFILE + value: path/to/Dockerfile2 + - name: build-3 + params: + - name: IMAGE + value: image-3 + - name: DOCKERFILE + value: path/to/Dockerfile3 + taskRef: + name: mytask diff --git a/examples/v1beta1/pipelineruns/alpha/pipelinerun-with-matrix-include.yaml b/examples/v1beta1/pipelineruns/alpha/pipelinerun-with-matrix-include.yaml new file mode 100644 index 00000000000..59674831cff --- /dev/null +++ b/examples/v1beta1/pipelineruns/alpha/pipelinerun-with-matrix-include.yaml @@ -0,0 +1,68 @@ +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: mytask + annotations: + description: | + A task that does something cool with GOARCH and version +spec: + params: + - name: GOARCH + default: '' + - name: version + default: '' + - name: flags + default: '' + - name: context + default: '' + - name: package + default: '' + steps: + - name: echo + image: alpine + script: | + echo $(params.GOARCH) and $(params.version) flags? $(params.flags) context? $(params.context) package? $(params.package) +--- +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + generateName: matrixed-include-pr +spec: + serviceAccountName: default + pipelineSpec: + tasks: + - name: matrix-include + matrix: + params: + - name: GOARCH + value: + - linux/amd64 + - linux/ppc64le + - linux/s390x + - name: version + value: + - go1.17 + - go1.18.1 + include: + - name: common-package + params: + - name: package + value: path/to/common/package/ + - name: s390x-no-race + params: + - name: GOARCH + value: linux/s390x + - name: flags + value: '-cover -v' + - name: go117-context + params: + - name: version + value: go1.17 + - name: context + value: path/to/go117/context + - name: non-existent-arch + params: + - name: GOARCH + value: I-do-not-exist + taskRef: + name: mytask diff --git a/pkg/apis/pipeline/v1/matrix_types.go b/pkg/apis/pipeline/v1/matrix_types.go index 854751303f8..6ae8142a9b2 100644 --- a/pkg/apis/pipeline/v1/matrix_types.go +++ b/pkg/apis/pipeline/v1/matrix_types.go @@ -35,7 +35,6 @@ type Matrix struct { Params Params `json:"params,omitempty"` // Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix. - // Note that Include is in preview mode and not yet supported. // +optional // +listType=atomic Include IncludeParamsList `json:"include,omitempty"` @@ -45,7 +44,6 @@ type Matrix struct { type IncludeParamsList []IncludeParams // IncludeParams allows passing in a specific combinations of Parameters into the Matrix. -// Note this struct is in preview mode and not yet supported type IncludeParams struct { // Name the specified combination Name string `json:"name,omitempty"` @@ -64,13 +62,85 @@ type Combinations []Combination // FanOut returns an list of params that represent combinations func (m *Matrix) FanOut() []Params { - var combinations Combinations + var combinations, includeCombinations Combinations + includeCombinations = m.getIncludeCombinations() + if m.HasInclude() && !m.HasParams() { + // If there are only Matrix Include Parameters return explicit combinations + return includeCombinations.toParams() + } + // Generate combinations from Matrix Parameters for _, parameter := range m.Params { combinations = combinations.fanOutMatrixParams(parameter) } + combinations = combinations.overwriteCombinations(includeCombinations) + combinations = combinations.addNewCombinations(includeCombinations) return combinations.toParams() } +// overwriteCombinations replaces any missing include params in the initial +// matrix params combinations by overwriting the initial combinations with the +// include combinations +func (cs Combinations) overwriteCombinations(ics Combinations) Combinations { + for _, paramCombination := range cs { + for _, includeCombination := range ics { + if paramCombination.contains(includeCombination) { + includeCombination.overwrite(paramCombination) + } + } + } + return cs +} + +// addNewCombinations creates a new combination for any include parameter +// values that are missing entirely from the initial combinations and +// returns all combinations +func (cs Combinations) addNewCombinations(ics Combinations) Combinations { + for _, includeCombination := range ics { + if cs.shouldAddNewCombination(includeCombination) { + cs = append(cs, includeCombination) + } + } + return cs +} + +// contains returns true if the include parameter name and value exists in combinations +func (c Combination) contains(includeCombination Combination) bool { + for name, val := range includeCombination { + if _, exist := c[name]; exist { + if c[name] != val { + return false + } + } + } + return true +} + +// overwrite the parameter name and value exists in combination with the include combination +func (c Combination) overwrite(oldCombination Combination) Combination { + for name, val := range c { + oldCombination[name] = val + } + return oldCombination +} + +// shouldAddNewCombination returns true if the include parameter name exists but the value is +// missing from combinations +func (cs Combinations) shouldAddNewCombination(includeCombination map[string]string) bool { + if len(includeCombination) == 0 { + return false + } + for _, paramCombination := range cs { + for name, val := range includeCombination { + if _, exist := paramCombination[name]; exist { + if paramCombination[name] == val { + return false + } + } + } + } + return true +} + // toParams transforms Combinations from a slice of map[string]string to a slice of Params // such that, these combinations can be directly consumed in creating taskRun/run object func (cs Combinations) toParams() []Params { @@ -98,6 +168,20 @@ func (cs Combinations) fanOutMatrixParams(param Param) Combinations { return cs.distribute(param) } +// getIncludeCombinations generates combinations based on Matrix Include Parameters +func (m *Matrix) getIncludeCombinations() Combinations { + var combinations Combinations + for i := range m.Include { + includeParams := m.Include[i].Params + newCombination := make(Combination) + for _, param := range includeParams { + newCombination[param.Name] = param.Value.StringVal + } + combinations = append(combinations, newCombination) + } + return combinations +} + // distribute generates a new Combination of Parameters by adding a new Parameter to an existing list of Combinations. func (cs Combinations) distribute(param Param) Combinations { var expandedCombinations Combinations diff --git a/pkg/apis/pipeline/v1/matrix_types_test.go b/pkg/apis/pipeline/v1/matrix_types_test.go index 4394e61171b..ff2588b3275 100644 --- a/pkg/apis/pipeline/v1/matrix_types_test.go +++ b/pkg/apis/pipeline/v1/matrix_types_test.go @@ -114,7 +114,474 @@ func TestMatrix_FanOut(t *testing.T) { Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, }, }}, - }} + }, { + name: "Fan out explicit combinations, no matrix params", + matrix: Matrix{ + Include: IncludeParamsList{{ + Name: "build-1", + Params: []Param{{ + Name: "IMAGE", Value: ParamValue{Type: ParamTypeString, StringVal: "image-1"}, + }, { + Name: "DOCKERFILE", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile1"}}}, + }, { + Name: "build-2", + Params: []Param{{ + Name: "IMAGE", Value: ParamValue{Type: ParamTypeString, StringVal: "image-2"}, + }, { + Name: "DOCKERFILE", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile2"}}}, + }, { + Name: "build-3", + Params: []Param{{ + Name: "IMAGE", Value: ParamValue{Type: ParamTypeString, StringVal: "image-3"}, + }, { + Name: "DOCKERFILE", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile3"}}}, + }}, + }, + want: []Params{{ + { + Name: "DOCKERFILE", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile1"}, + }, { + Name: "IMAGE", + Value: ParamValue{Type: ParamTypeString, StringVal: "image-1"}, + }, + }, { + { + Name: "DOCKERFILE", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile2"}, + }, { + Name: "IMAGE", + Value: ParamValue{Type: ParamTypeString, StringVal: "image-2"}, + }, + }, { + { + Name: "DOCKERFILE", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile3"}, + }, { + Name: "IMAGE", + Value: ParamValue{Type: ParamTypeString, StringVal: "image-3"}, + }, + }}, + }, { + name: "matrix include unknown param name, append to all combinations", + matrix: Matrix{ + Params: Params{{ + Name: "GOARCH", Value: ParamValue{ArrayVal: []string{"linux/amd64", "linux/ppc64le", "linux/s390x"}}, + }, { + Name: "version", Value: ParamValue{ArrayVal: []string{"go1.17", "go1.18.1"}}}, + }, + Include: IncludeParamsList{{ + Name: "common-package", + Params: Params{{ + Name: "package", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}}}, + }}, + }, + want: []Params{{ + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }}, + }, { + name: "matrix include param value does not exist, generate a new combination", + matrix: Matrix{ + Params: Params{{ + Name: "GOARCH", Value: ParamValue{ArrayVal: []string{"linux/amd64", "linux/ppc64le", "linux/s390x"}}, + }, { + Name: "version", Value: ParamValue{ArrayVal: []string{"go1.17", "go1.18.1"}}}, + }, + Include: IncludeParamsList{{ + Name: "non-existent-arch", + Params: Params{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "I-do-not-exist"}}}, + }}, + }, + want: []Params{{ + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "I-do-not-exist"}, + }, + }}, + }, { + name: "Matrix include filters single parameter and appends missing values", + matrix: Matrix{ + Params: Params{{ + Name: "GOARCH", Value: ParamValue{ArrayVal: []string{"linux/amd64", "linux/ppc64le", "linux/s390x"}}, + }, { + Name: "version", Value: ParamValue{ArrayVal: []string{"go1.17", "go1.18.1"}}}, + }, + Include: IncludeParamsList{{ + Name: "s390x-no-race", + Params: []Param{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}}}, + }}, + }, + want: []Params{{ + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }}, + }, + { + name: "Matrix include filters multiple parameters and append new parameters", + matrix: Matrix{ + Params: Params{{ + Name: "GOARCH", Value: ParamValue{ArrayVal: []string{"linux/amd64", "linux/ppc64le", "linux/s390x"}}, + }, { + Name: "version", Value: ParamValue{ArrayVal: []string{"go1.17", "go1.18.1"}}}, + }, + Include: IncludeParamsList{ + { + Name: "390x-no-race", + Params: Params{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}}, { + Name: "flags", Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}}, { + Name: "version", Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}}}, + }, + { + Name: "amd64-no-race", + Params: Params{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}}, { + Name: "flags", Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}}, { + Name: "version", Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}}}, + }, + }, + }, + want: []Params{{ + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }}, + }, { + name: "Matrix params and include params handles filter, appending, and generating new combinations at once", + matrix: Matrix{ + Params: Params{{ + Name: "GOARCH", Value: ParamValue{ArrayVal: []string{"linux/amd64", "linux/ppc64le", "linux/s390x"}}, + }, { + Name: "version", Value: ParamValue{ArrayVal: []string{"go1.17", "go1.18.1"}}}, + }, + Include: IncludeParamsList{{ + Name: "common-package", + Params: []Param{{ + Name: "package", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}}}, + }, { + Name: "s390x-no-race", + Params: []Param{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}}}, + }, { + Name: "go117-context", + Params: []Param{{ + Name: "version", Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, { + Name: "context", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/go117/context"}}}, + }, { + Name: "non-existent-arch", + Params: []Param{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "I-do-not-exist"}}, + }, + }}, + }, + want: []Params{{ + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "context", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/go117/context"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "context", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/go117/context"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "context", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/go117/context"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}}, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "I-do-not-exist"}, + }, + }}, + }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if d := cmp.Diff(tt.want, tt.matrix.FanOut()); d != "" { diff --git a/pkg/apis/pipeline/v1/openapi_generated.go b/pkg/apis/pipeline/v1/openapi_generated.go index 62a5fcd92ec..7215742d812 100644 --- a/pkg/apis/pipeline/v1/openapi_generated.go +++ b/pkg/apis/pipeline/v1/openapi_generated.go @@ -654,7 +654,7 @@ func schema_pkg_apis_pipeline_v1_IncludeParams(ref common.ReferenceCallback) com return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "IncludeParams allows passing in a specific combinations of Parameters into the Matrix. Note this struct is in preview mode and not yet supported", + Description: "IncludeParams allows passing in a specific combinations of Parameters into the Matrix.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "name": { @@ -724,7 +724,7 @@ func schema_pkg_apis_pipeline_v1_Matrix(ref common.ReferenceCallback) common.Ope }, }, SchemaProps: spec.SchemaProps{ - Description: "Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix. Note that Include is in preview mode and not yet supported.", + Description: "Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ diff --git a/pkg/apis/pipeline/v1/swagger.json b/pkg/apis/pipeline/v1/swagger.json index a08d40d8846..a271e73570a 100644 --- a/pkg/apis/pipeline/v1/swagger.json +++ b/pkg/apis/pipeline/v1/swagger.json @@ -286,7 +286,7 @@ } }, "v1.IncludeParams": { - "description": "IncludeParams allows passing in a specific combinations of Parameters into the Matrix. Note this struct is in preview mode and not yet supported", + "description": "IncludeParams allows passing in a specific combinations of Parameters into the Matrix.", "type": "object", "properties": { "name": { @@ -309,7 +309,7 @@ "type": "object", "properties": { "include": { - "description": "Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix. Note that Include is in preview mode and not yet supported.", + "description": "Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix.", "type": "array", "items": { "default": {}, diff --git a/pkg/apis/pipeline/v1beta1/matrix_types.go b/pkg/apis/pipeline/v1beta1/matrix_types.go index 45b80ae187f..9b322fe6084 100644 --- a/pkg/apis/pipeline/v1beta1/matrix_types.go +++ b/pkg/apis/pipeline/v1beta1/matrix_types.go @@ -35,7 +35,6 @@ type Matrix struct { Params Params `json:"params,omitempty"` // Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix. - // Note that Include is in preview mode and not yet supported. // +optional // +listType=atomic Include IncludeParamsList `json:"include,omitempty"` @@ -45,7 +44,6 @@ type Matrix struct { type IncludeParamsList []IncludeParams // IncludeParams allows passing in a specific combinations of Parameters into the Matrix. -// Note this struct is in preview mode and not yet supported type IncludeParams struct { // Name the specified combination Name string `json:"name,omitempty"` @@ -64,13 +62,85 @@ type Combinations []Combination // FanOut returns an list of params that represent combinations func (m *Matrix) FanOut() []Params { - var combinations Combinations + var combinations, includeCombinations Combinations + includeCombinations = m.getIncludeCombinations() + if m.HasInclude() && !m.HasParams() { + // If there are only Matrix Include Parameters return explicit combinations + return includeCombinations.toParams() + } + // Generate combinations from Matrix Parameters for _, parameter := range m.Params { combinations = combinations.fanOutMatrixParams(parameter) } + combinations = combinations.overwriteCombinations(includeCombinations) + combinations = combinations.addNewCombinations(includeCombinations) return combinations.toParams() } +// overwriteCombinations replaces any missing include params in the initial +// matrix params combinations by overwriting the initial combinations with the +// include combinations +func (cs Combinations) overwriteCombinations(ics Combinations) Combinations { + for _, paramCombination := range cs { + for _, includeCombination := range ics { + if paramCombination.contains(includeCombination) { + includeCombination.overwrite(paramCombination) + } + } + } + return cs +} + +// addNewCombinations creates a new combination for any include parameter +// values that are missing entirely from the initial combinations and +// returns all combinations +func (cs Combinations) addNewCombinations(ics Combinations) Combinations { + for _, includeCombination := range ics { + if cs.shouldAddNewCombination(includeCombination) { + cs = append(cs, includeCombination) + } + } + return cs +} + +// contains returns true if the include parameter name and value exists in combinations +func (c Combination) contains(includeCombination Combination) bool { + for name, val := range includeCombination { + if _, exist := c[name]; exist { + if c[name] != val { + return false + } + } + } + return true +} + +// overwrite the parameter name and value exists in combination with the include combination +func (c Combination) overwrite(oldCombination Combination) Combination { + for name, val := range c { + oldCombination[name] = val + } + return oldCombination +} + +// shouldAddNewCombination returns true if the include parameter name exists but the value is +// missing from combinations +func (cs Combinations) shouldAddNewCombination(includeCombination map[string]string) bool { + if len(includeCombination) == 0 { + return false + } + for _, paramCombination := range cs { + for name, val := range includeCombination { + if _, exist := paramCombination[name]; exist { + if paramCombination[name] == val { + return false + } + } + } + } + return true +} + // toParams transforms Combinations from a slice of map[string]string to a slice of Params // such that, these combinations can be directly consumed in creating taskRun/run object func (cs Combinations) toParams() []Params { @@ -98,6 +168,20 @@ func (cs Combinations) fanOutMatrixParams(param Param) Combinations { return cs.distribute(param) } +// getIncludeCombinations generates combinations based on Matrix Include Parameters +func (m *Matrix) getIncludeCombinations() Combinations { + var combinations Combinations + for i := range m.Include { + includeParams := m.Include[i].Params + newCombination := make(Combination) + for _, param := range includeParams { + newCombination[param.Name] = param.Value.StringVal + } + combinations = append(combinations, newCombination) + } + return combinations +} + // distribute generates a new Combination of Parameters by adding a new Parameter to an existing list of Combinations. func (cs Combinations) distribute(param Param) Combinations { var expandedCombinations Combinations diff --git a/pkg/apis/pipeline/v1beta1/matrix_types_test.go b/pkg/apis/pipeline/v1beta1/matrix_types_test.go index 6471db631be..a3298c03384 100644 --- a/pkg/apis/pipeline/v1beta1/matrix_types_test.go +++ b/pkg/apis/pipeline/v1beta1/matrix_types_test.go @@ -114,7 +114,474 @@ func TestMatrix_FanOut(t *testing.T) { Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, }, }}, - }} + }, { + name: "Fan out explicit combinations, no matrix params", + matrix: Matrix{ + Include: IncludeParamsList{{ + Name: "build-1", + Params: Params{{ + Name: "IMAGE", Value: ParamValue{Type: ParamTypeString, StringVal: "image-1"}, + }, { + Name: "DOCKERFILE", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile1"}}}, + }, { + Name: "build-2", + Params: Params{{ + Name: "IMAGE", Value: ParamValue{Type: ParamTypeString, StringVal: "image-2"}, + }, { + Name: "DOCKERFILE", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile2"}}}, + }, { + Name: "build-3", + Params: Params{{ + Name: "IMAGE", Value: ParamValue{Type: ParamTypeString, StringVal: "image-3"}, + }, { + Name: "DOCKERFILE", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile3"}}}, + }}, + }, + want: []Params{{ + { + Name: "DOCKERFILE", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile1"}, + }, { + Name: "IMAGE", + Value: ParamValue{Type: ParamTypeString, StringVal: "image-1"}, + }, + }, { + { + Name: "DOCKERFILE", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile2"}, + }, { + Name: "IMAGE", + Value: ParamValue{Type: ParamTypeString, StringVal: "image-2"}, + }, + }, { + { + Name: "DOCKERFILE", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/Dockerfile3"}, + }, { + Name: "IMAGE", + Value: ParamValue{Type: ParamTypeString, StringVal: "image-3"}, + }, + }}, + }, { + name: "matrix include unknown param name, append to all combinations", + matrix: Matrix{ + Params: Params{{ + Name: "GOARCH", Value: ParamValue{ArrayVal: []string{"linux/amd64", "linux/ppc64le", "linux/s390x"}}, + }, { + Name: "version", Value: ParamValue{ArrayVal: []string{"go1.17", "go1.18.1"}}}, + }, + Include: IncludeParamsList{{ + Name: "common-package", + Params: Params{{ + Name: "package", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}}}, + }}, + }, + want: []Params{{ + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }}, + }, { + name: "matrix include param value does not exist, generate a new combination", + matrix: Matrix{ + Params: Params{{ + Name: "GOARCH", Value: ParamValue{ArrayVal: []string{"linux/amd64", "linux/ppc64le", "linux/s390x"}}, + }, { + Name: "version", Value: ParamValue{ArrayVal: []string{"go1.17", "go1.18.1"}}}, + }, + Include: IncludeParamsList{{ + Name: "non-existent-arch", + Params: Params{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "I-do-not-exist"}}}, + }}, + }, + want: []Params{{ + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "I-do-not-exist"}, + }, + }}, + }, { + name: "Matrix include filters single parameter and appends missing values", + matrix: Matrix{ + Params: Params{{ + Name: "GOARCH", Value: ParamValue{ArrayVal: []string{"linux/amd64", "linux/ppc64le", "linux/s390x"}}, + }, { + Name: "version", Value: ParamValue{ArrayVal: []string{"go1.17", "go1.18.1"}}}, + }, + Include: IncludeParamsList{{ + Name: "s390x-no-race", + Params: Params{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}}}, + }}, + }, + want: []Params{{ + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }}, + }, + { + name: "Matrix include filters multiple parameters and append new parameters", + matrix: Matrix{ + Params: Params{{ + Name: "GOARCH", Value: ParamValue{ArrayVal: []string{"linux/amd64", "linux/ppc64le", "linux/s390x"}}, + }, { + Name: "version", Value: ParamValue{ArrayVal: []string{"go1.17", "go1.18.1"}}}, + }, + Include: IncludeParamsList{ + { + Name: "390x-no-race", + Params: Params{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}}, { + Name: "flags", Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}}, { + Name: "version", Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}}}, + }, + { + Name: "amd64-no-race", + Params: Params{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}}, { + Name: "flags", Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}}, { + Name: "version", Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}}}, + }, + }, + }, + want: []Params{{ + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }}, + }, { + name: "Matrix params and include params handles filter, appending, and generating new combinations at once", + matrix: Matrix{ + Params: Params{{ + Name: "GOARCH", Value: ParamValue{ArrayVal: []string{"linux/amd64", "linux/ppc64le", "linux/s390x"}}, + }, { + Name: "version", Value: ParamValue{ArrayVal: []string{"go1.17", "go1.18.1"}}}, + }, + Include: IncludeParamsList{{ + Name: "common-package", + Params: Params{{ + Name: "package", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}}}, + }, { + Name: "s390x-no-race", + Params: Params{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}}}, + }, { + Name: "go117-context", + Params: Params{{ + Name: "version", Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, { + Name: "context", Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/go117/context"}}}, + }, { + Name: "non-existent-arch", + Params: Params{{ + Name: "GOARCH", Value: ParamValue{Type: ParamTypeString, StringVal: "I-do-not-exist"}}, + }, + }}, + }, + want: []Params{{ + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "context", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/go117/context"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "context", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/go117/context"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "context", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/go117/context"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.17"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/amd64"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}}, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/ppc64le"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "linux/s390x"}, + }, { + Name: "flags", + Value: ParamValue{Type: ParamTypeString, StringVal: "-cover -v"}, + }, { + Name: "package", + Value: ParamValue{Type: ParamTypeString, StringVal: "path/to/common/package/"}, + }, { + Name: "version", + Value: ParamValue{Type: ParamTypeString, StringVal: "go1.18.1"}, + }, + }, { + { + Name: "GOARCH", + Value: ParamValue{Type: ParamTypeString, StringVal: "I-do-not-exist"}, + }, + }}, + }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if d := cmp.Diff(tt.want, tt.matrix.FanOut()); d != "" { diff --git a/pkg/apis/pipeline/v1beta1/openapi_generated.go b/pkg/apis/pipeline/v1beta1/openapi_generated.go index 92bbcf4afd3..c4ebbdcf945 100644 --- a/pkg/apis/pipeline/v1beta1/openapi_generated.go +++ b/pkg/apis/pipeline/v1beta1/openapi_generated.go @@ -1063,7 +1063,7 @@ func schema_pkg_apis_pipeline_v1beta1_IncludeParams(ref common.ReferenceCallback return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "IncludeParams allows passing in a specific combinations of Parameters into the Matrix. Note this struct is in preview mode and not yet supported", + Description: "IncludeParams allows passing in a specific combinations of Parameters into the Matrix.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "name": { @@ -1133,7 +1133,7 @@ func schema_pkg_apis_pipeline_v1beta1_Matrix(ref common.ReferenceCallback) commo }, }, SchemaProps: spec.SchemaProps{ - Description: "Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix. Note that Include is in preview mode and not yet supported.", + Description: "Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix.", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ diff --git a/pkg/apis/pipeline/v1beta1/swagger.json b/pkg/apis/pipeline/v1beta1/swagger.json index e8171739b5e..186c60518e5 100644 --- a/pkg/apis/pipeline/v1beta1/swagger.json +++ b/pkg/apis/pipeline/v1beta1/swagger.json @@ -506,7 +506,7 @@ } }, "v1beta1.IncludeParams": { - "description": "IncludeParams allows passing in a specific combinations of Parameters into the Matrix. Note this struct is in preview mode and not yet supported", + "description": "IncludeParams allows passing in a specific combinations of Parameters into the Matrix.", "type": "object", "properties": { "name": { @@ -529,7 +529,7 @@ "type": "object", "properties": { "include": { - "description": "Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix. Note that Include is in preview mode and not yet supported.", + "description": "Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix.", "type": "array", "items": { "default": {}, diff --git a/pkg/reconciler/pipelinerun/pipelinerun_test.go b/pkg/reconciler/pipelinerun/pipelinerun_test.go index 2462224bbc3..34972d45a91 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_test.go @@ -7991,6 +7991,766 @@ spec: }) } } +func TestReconciler_PipelineTaskIncludeParams(t *testing.T) { + names.TestingSeed() + + task := parse.MustParseV1beta1Task(t, ` +metadata: + name: mytask + namespace: foo +spec: + params: + - name: GOARCH + - name: version + - name: flags + default: "" + - name: context + default: "" + - name: package + default: "" + steps: + - name: echo + image: alpine + script: | + echo "$(params.GOARCH) and $(params.version)" +`) + + expectedTaskRuns := []*v1beta1.TaskRun{ + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-matrix-include-0", "foo", + "pr", "p", "matrix-include", false), + ` +spec: + params: + - name: GOARCH + value: linux/amd64 + - name: context + value: path/to/go117/context + - name: package + value: path/to/common/package/ + - name: version + value: go1.17 + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-matrix-include-1", "foo", + "pr", "p", "matrix-include", false), + ` +spec: + params: + - name: GOARCH + value: linux/ppc64le + - name: context + value: path/to/go117/context + - name: package + value: path/to/common/package/ + - name: version + value: go1.17 + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-matrix-include-2", "foo", + "pr", "p", "matrix-include", false), + ` +spec: + params: + - name: GOARCH + value: linux/s390x + - name: context + value: path/to/go117/context + - name: flags + value: -cover -v + - name: package + value: path/to/common/package/ + - name: version + value: go1.17 + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-matrix-include-3", "foo", + "pr", "p", "matrix-include", false), + ` +spec: + params: + - name: GOARCH + value: linux/amd64 + - name: package + value: path/to/common/package/ + - name: version + value: go1.18.1 + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-matrix-include-4", "foo", + "pr", "p", "matrix-include", false), + ` +spec: + params: + - name: GOARCH + value: linux/ppc64le + - name: package + value: path/to/common/package/ + - name: version + value: go1.18.1 + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-matrix-include-5", "foo", + "pr", "p", "matrix-include", false), + ` +spec: + params: + - name: GOARCH + value: linux/s390x + - name: flags + value: -cover -v + - name: package + value: path/to/common/package/ + - name: version + value: go1.18.1 + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-matrix-include-6", "foo", + "pr", "p", "matrix-include", false), + ` +spec: + params: + - name: GOARCH + value: I-do-not-exist + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + } + cms := []*corev1.ConfigMap{withEnabledAlphaAPIFields(newFeatureFlagsConfigMap())} + cms = append(cms, withMaxMatrixCombinationsCount(newDefaultsConfigMap(), 10)) + + tests := []struct { + name string + memberOf string + p *v1beta1.Pipeline + tr *v1beta1.TaskRun + expectedPipelineRun *v1beta1.PipelineRun + }{{ + name: "p-dag", + memberOf: "tasks", + p: parse.MustParseV1beta1Pipeline(t, fmt.Sprintf(` +metadata: + name: %s + namespace: foo +spec: + tasks: + - name: matrix-include + taskRef: + name: mytask + matrix: + params: + - name: GOARCH + value: + - linux/amd64 + - linux/ppc64le + - linux/s390x + - name: version + value: + - go1.17 + - go1.18.1 + include: + - name: common-package + params: + - name: package + value: path/to/common/package/ + - name: s390x-no-race + params: + - name: GOARCH + value: linux/s390x + - name: flags + value: '-cover -v' + - name: go117-context + params: + - name: version + value: go1.17 + - name: context + value: path/to/go117/context + - name: non-existent-arch + params: + - name: GOARCH + value: I-do-not-exist +`, "p-dag")), + expectedPipelineRun: parse.MustParseV1beta1PipelineRun(t, ` +metadata: + name: pr + namespace: foo + annotations: {} + labels: + tekton.dev/pipeline: p-dag +spec: + serviceAccountName: test-sa + pipelineRef: + name: p-dag +status: + pipelineSpec: + tasks: + - name: matrix-include + taskRef: + name: mytask + kind: Task + matrix: + params: + - name: GOARCH + value: + - linux/amd64 + - linux/ppc64le + - linux/s390x + - name: version + value: + - go1.17 + - go1.18.1 + include: + - name: common-package + params: + - name: package + value: path/to/common/package/ + - name: s390x-no-race + params: + - name: GOARCH + value: linux/s390x + - name: flags + value: '-cover -v' + - name: go117-context + params: + - name: version + value: go1.17 + - name: context + value: path/to/go117/context + - name: non-existent-arch + params: + - name: GOARCH + value: I-do-not-exist + conditions: + - type: Succeeded + status: "Unknown" + reason: "Running" + message: "Tasks Completed: 0 (Failed: 0, Cancelled 0), Incomplete: 1, Skipped: 0" + childReferences: + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-0 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-1 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-2 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-3 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-4 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-5 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-6 + pipelineTaskName: matrix-include +`), + }, { + name: "p-finally", + memberOf: "finally", + p: parse.MustParseV1beta1Pipeline(t, fmt.Sprintf(` +metadata: + name: %s + namespace: foo +spec: + tasks: + - name: unmatrixed-pt + params: + - name: GOARCH + value: "test" + - name: version + value: "test" + - name: flags + value: "test" + - name: context + value: "test" + - name: package + value: "test" + taskRef: + name: mytask + finally: + - name: matrix-include + taskRef: + name: mytask + matrix: + params: + - name: GOARCH + value: + - linux/amd64 + - linux/ppc64le + - linux/s390x + - name: version + value: + - go1.17 + - go1.18.1 + include: + - name: common-package + params: + - name: package + value: path/to/common/package/ + - name: s390x-no-race + params: + - name: GOARCH + value: linux/s390x + - name: flags + value: '-cover -v' + - name: go117-context + params: + - name: version + value: go1.17 + - name: context + value: path/to/go117/context + - name: non-existent-arch + params: + - name: GOARCH + value: I-do-not-exist +`, "p-finally")), + tr: mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-unmatrixed-pt", "foo", + "pr", "p-finally", "unmatrixed-pt", false), + ` +spec: + params: + - name: GOARCH + value: "test" + - name: version + value: "test" + - name: flags + value: "test" + - name: context + value: "test" + - name: package + value: "test" + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +status: + conditions: + - type: Succeeded + status: "True" + reason: Succeeded + message: All Tasks have completed executing +`), + expectedPipelineRun: parse.MustParseV1beta1PipelineRun(t, ` +metadata: + name: pr + namespace: foo + annotations: {} + labels: + tekton.dev/pipeline: p-finally +spec: + serviceAccountName: test-sa + pipelineRef: + name: p-finally +status: + pipelineSpec: + tasks: + - name: unmatrixed-pt + params: + - name: GOARCH + value: "test" + - name: version + value: "test" + - name: flags + value: "test" + - name: context + value: "test" + - name: package + value: "test" + taskRef: + name: mytask + kind: Task + finally: + - name: matrix-include + taskRef: + name: mytask + kind: Task + matrix: + params: + - name: GOARCH + value: + - linux/amd64 + - linux/ppc64le + - linux/s390x + - name: version + value: + - go1.17 + - go1.18.1 + include: + - name: common-package + params: + - name: package + value: path/to/common/package/ + - name: s390x-no-race + params: + - name: GOARCH + value: linux/s390x + - name: flags + value: '-cover -v' + - name: go117-context + params: + - name: version + value: go1.17 + - name: context + value: path/to/go117/context + - name: non-existent-arch + params: + - name: GOARCH + value: I-do-not-exist + conditions: + - type: Succeeded + status: "Unknown" + reason: "Running" + message: "Tasks Completed: 1 (Failed: 0, Cancelled 0), Incomplete: 1, Skipped: 0" + childReferences: + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-unmatrixed-pt + pipelineTaskName: unmatrixed-pt + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-0 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-1 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-2 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-3 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-4 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-5 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-6 + pipelineTaskName: matrix-include +`), + }} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + pr := parse.MustParseV1beta1PipelineRun(t, fmt.Sprintf(` +metadata: + name: pr + namespace: foo +spec: + serviceAccountName: test-sa + pipelineRef: + name: %s +`, tt.name)) + d := test.Data{ + PipelineRuns: []*v1beta1.PipelineRun{pr}, + Pipelines: []*v1beta1.Pipeline{tt.p}, + Tasks: []*v1beta1.Task{task}, + ConfigMaps: cms, + } + if tt.tr != nil { + d.TaskRuns = []*v1beta1.TaskRun{tt.tr} + } + prt := newPipelineRunTest(t, d) + defer prt.Cancel() + + _, clients := prt.reconcileRun("foo", "pr", []string{}, false) + taskRuns, err := clients.Pipeline.TektonV1beta1().TaskRuns("foo").List(prt.TestAssets.Ctx, metav1.ListOptions{ + LabelSelector: fmt.Sprintf("tekton.dev/pipelineRun=pr,tekton.dev/pipeline=%s,tekton.dev/pipelineTask=matrix-include", tt.name), + Limit: 1, + }) + if err != nil { + t.Fatalf("Failure to list TaskRun's %s", err) + } + + if len(taskRuns.Items) != 7 { + t.Fatalf("Expected 7 TaskRuns got %d", len(taskRuns.Items)) + } + + for i := range taskRuns.Items { + expectedTaskRun := expectedTaskRuns[i] + expectedTaskRun.Labels["tekton.dev/pipeline"] = tt.name + expectedTaskRun.Labels["tekton.dev/memberOf"] = tt.memberOf + if d := cmp.Diff(expectedTaskRun, &taskRuns.Items[i], ignoreResourceVersion, ignoreTypeMeta); d != "" { + t.Errorf("expected to see TaskRun %v created. Diff %s", expectedTaskRuns[i].Name, diff.PrintWantGot(d)) + } + } + + pipelineRun, err := clients.Pipeline.TektonV1beta1().PipelineRuns("foo").Get(prt.TestAssets.Ctx, "pr", metav1.GetOptions{}) + if err != nil { + t.Fatalf("Got an error getting reconciled run out of fake client: %s", err) + } + if d := cmp.Diff(tt.expectedPipelineRun, pipelineRun, ignoreResourceVersion, ignoreTypeMeta, ignoreLastTransitionTime, ignoreStartTime, ignoreFinallyStartTime, cmpopts.EquateEmpty()); d != "" { + t.Errorf("expected PipelineRun was not created. Diff %s", diff.PrintWantGot(d)) + } + }) + } +} + +func TestReconciler_PipelineTaskExplicitCombos(t *testing.T) { + names.TestingSeed() + + task := parse.MustParseV1beta1Task(t, ` +metadata: + name: mytask + namespace: foo +spec: + params: + - name: IMAGE + - name: DOCKERFILE + steps: + - name: echo + image: alpine + script: | + echo "$(params.IMAGE) and $(params.DOCKERFILE)" +`) + + expectedTaskRuns := []*v1beta1.TaskRun{ + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-matrix-include-0", "foo", + "pr", "p", "matrix-include", false), + ` +spec: + params: + - name: DOCKERFILE + value: path/to/Dockerfile1 + - name: IMAGE + value: image-1 + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-matrix-include-1", "foo", + "pr", "p", "matrix-include", false), + ` +spec: + params: + - name: DOCKERFILE + value: path/to/Dockerfile2 + - name: IMAGE + value: image-2 + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("pr-matrix-include-2", "foo", + "pr", "p", "matrix-include", false), + ` +spec: + params: + - name: DOCKERFILE + value: path/to/Dockerfile3 + - name: IMAGE + value: image-3 + serviceAccountName: test-sa + taskRef: + name: mytask + kind: Task +`), + } + cms := []*corev1.ConfigMap{withEnabledAlphaAPIFields(newFeatureFlagsConfigMap())} + cms = append(cms, withMaxMatrixCombinationsCount(newDefaultsConfigMap(), 10)) + + tests := []struct { + name string + memberOf string + p *v1beta1.Pipeline + tr *v1beta1.TaskRun + expectedPipelineRun *v1beta1.PipelineRun + }{{ + name: "p-dag", + memberOf: "tasks", + p: parse.MustParseV1beta1Pipeline(t, fmt.Sprintf(` +metadata: + name: %s + namespace: foo +spec: + tasks: + - name: matrix-include + taskRef: + name: mytask + matrix: + include: + - name: build-1 + params: + - name: IMAGE + value: image-1 + - name: DOCKERFILE + value: path/to/Dockerfile1 + - name: build-2 + params: + - name: IMAGE + value: image-2 + - name: DOCKERFILE + value: path/to/Dockerfile2 + - name: build-3 + params: + - name: IMAGE + value: image-3 + - name: DOCKERFILE + value: path/to/Dockerfile3 +`, "p-dag")), + expectedPipelineRun: parse.MustParseV1beta1PipelineRun(t, ` +metadata: + name: pr + namespace: foo + annotations: {} + labels: + tekton.dev/pipeline: p-dag +spec: + serviceAccountName: test-sa + pipelineRef: + name: p-dag +status: + pipelineSpec: + tasks: + - name: matrix-include + taskRef: + name: mytask + kind: Task + matrix: + include: + - name: build-1 + params: + - name: IMAGE + value: image-1 + - name: DOCKERFILE + value: path/to/Dockerfile1 + - name: build-2 + params: + - name: IMAGE + value: image-2 + - name: DOCKERFILE + value: path/to/Dockerfile2 + - name: build-3 + params: + - name: IMAGE + value: image-3 + - name: DOCKERFILE + value: path/to/Dockerfile3 + conditions: + - type: Succeeded + status: "Unknown" + reason: "Running" + message: "Tasks Completed: 0 (Failed: 0, Cancelled 0), Incomplete: 1, Skipped: 0" + childReferences: + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-0 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-1 + pipelineTaskName: matrix-include + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: pr-matrix-include-2 + pipelineTaskName: matrix-include +`), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + pr := parse.MustParseV1beta1PipelineRun(t, fmt.Sprintf(` +metadata: + name: pr + namespace: foo +spec: + serviceAccountName: test-sa + pipelineRef: + name: %s +`, tt.name)) + d := test.Data{ + PipelineRuns: []*v1beta1.PipelineRun{pr}, + Pipelines: []*v1beta1.Pipeline{tt.p}, + Tasks: []*v1beta1.Task{task}, + ConfigMaps: cms, + } + if tt.tr != nil { + d.TaskRuns = []*v1beta1.TaskRun{tt.tr} + } + prt := newPipelineRunTest(t, d) + defer prt.Cancel() + + _, clients := prt.reconcileRun("foo", "pr", []string{}, false) + taskRuns, err := clients.Pipeline.TektonV1beta1().TaskRuns("foo").List(prt.TestAssets.Ctx, metav1.ListOptions{ + LabelSelector: fmt.Sprintf("tekton.dev/pipelineRun=pr,tekton.dev/pipeline=%s,tekton.dev/pipelineTask=matrix-include", tt.name), + Limit: 1, + }) + if err != nil { + t.Fatalf("Failure to list TaskRun's %s", err) + } + + if len(taskRuns.Items) != 3 { + t.Fatalf("Expected 3 TaskRuns got %d", len(taskRuns.Items)) + } + + for i := range taskRuns.Items { + expectedTaskRun := expectedTaskRuns[i] + expectedTaskRun.Labels["tekton.dev/pipeline"] = tt.name + expectedTaskRun.Labels["tekton.dev/memberOf"] = tt.memberOf + if d := cmp.Diff(expectedTaskRun, &taskRuns.Items[i], ignoreResourceVersion, ignoreTypeMeta); d != "" { + t.Errorf("expected to see TaskRun %v created. Diff %s", expectedTaskRuns[i].Name, diff.PrintWantGot(d)) + } + } + + pipelineRun, err := clients.Pipeline.TektonV1beta1().PipelineRuns("foo").Get(prt.TestAssets.Ctx, "pr", metav1.GetOptions{}) + if err != nil { + t.Fatalf("Got an error getting reconciled run out of fake client: %s", err) + } + if d := cmp.Diff(tt.expectedPipelineRun, pipelineRun, ignoreResourceVersion, ignoreTypeMeta, ignoreLastTransitionTime, ignoreStartTime, ignoreFinallyStartTime, cmpopts.EquateEmpty()); d != "" { + t.Errorf("expected PipelineRun was not created. Diff %s", diff.PrintWantGot(d)) + } + }) + } +} func TestReconciler_PipelineTaskMatrixWithResults(t *testing.T) { names.TestingSeed()
(Optional) -

Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix. -Note that Include is in preview mode and not yet supported.

+

Include is a list of IncludeParams which allows passing in specific combinations of Parameters into the Matrix.