Repository: tektoncd/operator
Pull request #630 (2022-02-23 14:58:03)

Add Tekton Chains to the operator
Add chains to the operator

# Submitter Checklist

These are the criteria that every PR should meet, please check them off as you
review them:

- [x] Includes [tests](https://github.com/tektoncd/community/blob/master/standards.md#principles) (if functionality changed/added)
- [x] Includes [docs](https://github.com/tektoncd/community/blob/master/standards.md#principles) (if user facing)
- [x] Commit messages follow [commit message best practices](https://github.com/tektoncd/community/blob/master/standards.md#commit-messages)

_See [the contribution guide](https://github.com/tektoncd/operator/blob/master/CONTRIBUTING.md) for more details._

# Release Notes

```release-note
Add Tekton Chains to the operator
```


tekton-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **sm43**
You can assign the PR to them by writing `/assign @sm43` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=tektoncd%2Foperator).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/tektoncd/operator/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["sm43"]} -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-unit-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-unit-tests/1496499690785476610/) | `/test pull-tekton-operator-unit-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-go-coverage | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496499690785476608/) | `/test pull-tekton-operator-go-coverage`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following tests **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-go-coverage | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496499690785476608/) | `/test pull-tekton-operator-go-coverage`
pull-tekton-operator-unit-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-unit-tests/1496499690785476610/) | `/test pull-tekton-operator-unit-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following tests **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-go-coverage | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496499690785476608/) | `/test pull-tekton-operator-go-coverage`
pull-tekton-operator-unit-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-unit-tests/1496499690785476610/) | `/test pull-tekton-operator-unit-tests`
pull-tekton-operator-build-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-build-tests/1496499690785476611/) | `/test pull-tekton-operator-build-tests`
pull-tekton-operator-integration-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1496499690785476609/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following tests **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-go-coverage | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496499690785476608/) | `/test pull-tekton-operator-go-coverage`
pull-tekton-operator-unit-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-unit-tests/1496499690785476610/) | `/test pull-tekton-operator-unit-tests`
pull-tekton-operator-build-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-build-tests/1496499690785476611/) | `/test pull-tekton-operator-build-tests`
pull-tekton-operator-integration-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1496499690785476609/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496502710969569283/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496502710969569283/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496502710969569283/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496502710969569283/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496502710969569283/artifacts/line-cov.html#file7) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496502710969569283/artifacts/line-cov.html#file8) | Do not exist | 74.1% | 

tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-unit-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-unit-tests/1496502710969569281/) | `/test pull-tekton-operator-unit-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following tests **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-build-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-build-tests/1496499690785476611/) | `/test pull-tekton-operator-build-tests`
pull-tekton-operator-integration-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1496499690785476609/) | `/test pull-tekton-operator-integration-tests`
pull-tekton-operator-unit-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-unit-tests/1496502710969569281/) | `/test pull-tekton-operator-unit-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following tests **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1496499690785476609/) | `/test pull-tekton-operator-integration-tests`
pull-tekton-operator-unit-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-unit-tests/1496502710969569281/) | `/test pull-tekton-operator-unit-tests`
pull-tekton-operator-build-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-build-tests/1496502710969569282/) | `/test pull-tekton-operator-build-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following tests **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 6ef0723ed9368b74fc2a4b0118cce08173e97511 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1496499690785476609/) | `/test pull-tekton-operator-integration-tests`
pull-tekton-operator-unit-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-unit-tests/1496502710969569281/) | `/test pull-tekton-operator-unit-tests`
pull-tekton-operator-build-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-build-tests/1496502710969569282/) | `/test pull-tekton-operator-build-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following tests **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-unit-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-unit-tests/1496502710969569281/) | `/test pull-tekton-operator-unit-tests`
pull-tekton-operator-build-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-build-tests/1496502710969569282/) | `/test pull-tekton-operator-build-tests`
pull-tekton-operator-integration-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1496502710969569280/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following tests **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-unit-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-unit-tests/1496502710969569281/) | `/test pull-tekton-operator-unit-tests`
pull-tekton-operator-build-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-build-tests/1496502710969569282/) | `/test pull-tekton-operator-build-tests`
pull-tekton-operator-integration-tests | 40b2f80c99a431f0dea9cb738164b8e0094aa400 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1496502710969569280/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496507617848070144/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496507617848070144/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496507617848070144/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496507617848070144/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496507617848070144/artifacts/line-cov.html#file7) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1496507617848070144/artifacts/line-cov.html#file8) | Do not exist | 74.1% | 

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498009513372946434/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498009513372946434/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498009513372946434/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498009513372946434/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498009513372946434/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498009513372946434/artifacts/line-cov.html#file9) | Do not exist | 74.1% | 

tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | cdbe445258920ade72e332ac1cb1525bd425fb2a | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498009513377140736/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | cdbe445258920ade72e332ac1cb1525bd425fb2a | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498009513377140736/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
piyush-garg: /test pull-tekton-operator-integration-tests
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498166045788082179/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498166045788082179/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498166045788082179/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498166045788082179/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498166045788082179/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498166045788082179/artifacts/line-cov.html#file9) | Do not exist | 74.1% | 

tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 1ee7170f05bd242ccb29fd12e9ce5b838f4195cd | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498166045788082177/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 1ee7170f05bd242ccb29fd12e9ce5b838f4195cd | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498166045788082177/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
piyush-garg: /retest
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 1ee7170f05bd242ccb29fd12e9ce5b838f4195cd | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498183787069050880/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 1ee7170f05bd242ccb29fd12e9ce5b838f4195cd | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498183787069050880/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498224430675922947/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498224430675922947/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498224430675922947/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498224430675922947/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498224430675922947/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498224430675922947/artifacts/line-cov.html#file9) | Do not exist | 74.1% | 

tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | a54860a269e575f467807b2cd59a8a537626460f | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498224430675922944/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | a54860a269e575f467807b2cd59a8a537626460f | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498224430675922944/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498233489600811008/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498233489600811008/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498233489600811008/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498233489600811008/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498233489600811008/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498233489600811008/artifacts/line-cov.html#file9) | Do not exist | 74.1% | 

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498239656255295490/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498239656255295490/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498239656255295490/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498239656255295490/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498239656255295490/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498239656255295490/artifacts/line-cov.html#file9) | Do not exist | 74.1% | 

tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 377c2eb1c3d281985b68ef9ebc158bda2d1faace | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498239656255295489/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 377c2eb1c3d281985b68ef9ebc158bda2d1faace | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498239656255295489/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498251233515802627/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498251233515802627/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498251233515802627/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498251233515802627/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498251233515802627/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498251233515802627/artifacts/line-cov.html#file9) | Do not exist | 74.1% | 

tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 56dafbe6fdb7e57e310c560f6e7de1a1ac478896 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498251233515802624/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 56dafbe6fdb7e57e310c560f6e7de1a1ac478896 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498251233515802624/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498276021336543232/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498276021336543232/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498276021336543232/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498276021336543232/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498276021336543232/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498276021336543232/artifacts/line-cov.html#file9) | Do not exist | 74.1% | 

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498283948277501955/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498283948277501955/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498283948277501955/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498283948277501955/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498283948277501955/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498283948277501955/artifacts/line-cov.html#file9) | Do not exist | 74.1% | 

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498558886230102018/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498558886230102018/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498558886230102018/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498558886230102018/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498558886230102018/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498558886230102018/artifacts/line-cov.html#file9) | Do not exist | 74.1% | 

tekton-robot: @vdemeester: GitHub didn't allow me to request PR reviews from the following users: piyush-garg.

Note that only [tektoncd members](https://github.com/orgs/tektoncd/people) and repo collaborators can review this PR, and authors cannot review their own PRs.

<details>

In response to [this](https://github.com/tektoncd/operator/pull/630#pullrequestreview-896051263):

>We need to add support for `targetNamespace: openshift-pipelines` in a follow-up, before releasing.
>
>/cc @nikhil-thomas @piyush-garg 


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
tekton-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/tektoncd/operator/pull/630#pullrequestreview-896051263" title="Approved">vdemeester</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=tektoncd%2Foperator).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/tektoncd/operator/blob/main/OWNERS)~~ [vdemeester]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
sm43: LGTM
other than the few nit and cleanup !
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498911082834563072/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498911082834563072/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498911082834563072/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498911082834563072/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498911082834563072/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498911082834563072/artifacts/line-cov.html#file9) | Do not exist | 76.4% | 

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498912844727455746/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498912844727455746/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498912844727455746/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498912844727455746/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498912844727455746/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498912844727455746/artifacts/line-cov.html#file9) | Do not exist | 76.4% | 

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498914103094153219/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498914103094153219/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498914103094153219/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498914103094153219/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498914103094153219/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498914103094153219/artifacts/line-cov.html#file9) | Do not exist | 76.4% | 

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498918254725304320/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498918254725304320/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498918254725304320/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498918254725304320/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498918254725304320/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498918254725304320/artifacts/line-cov.html#file9) | Do not exist | 76.4% | 

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498920016643362818/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498920016643362818/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498920016643362818/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498920016643362818/artifacts/line-cov.html#file6) | 41.9% | 41.3% | -0.7
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498920016643362818/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1498920016643362818/artifacts/line-cov.html#file9) | Do not exist | 76.4% | 

tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | b4822d8a0328ffafd5e43a56f899d199176e09c0 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498920016643362816/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | b4822d8a0328ffafd5e43a56f899d199176e09c0 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498920016643362816/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
piyush-garg: /retest
nikhil-thomas: /retest
concaf: /lgtm
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | b4822d8a0328ffafd5e43a56f899d199176e09c0 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498973495311208448/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | b4822d8a0328ffafd5e43a56f899d199176e09c0 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498973495311208448/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/tektoncd/operator/pull/630#pullrequestreview-897431528" title="Approved">concaf</a>*, *<a href="https://github.com/tektoncd/operator/pull/630#pullrequestreview-896051263" title="Approved">vdemeester</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=tektoncd%2Foperator).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/tektoncd/operator/blob/main/OWNERS)~~ [vdemeester]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
concaf: /retest
concaf: /hold
till @nikhil-thomas's comments are addressed
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | b4822d8a0328ffafd5e43a56f899d199176e09c0 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498980038266064896/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | b4822d8a0328ffafd5e43a56f899d199176e09c0 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1498980038266064896/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: PR needs rebase.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
tekton-robot: New changes are detected. LGTM label has been removed.
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499032759522299904/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499032759522299904/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499032759522299904/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499032759522299904/artifacts/line-cov.html#file6) | 41.3% | 40.6% | -0.6
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499032759522299904/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499032759522299904/artifacts/line-cov.html#file9) | Do not exist | 76.4% | 

tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 3e4fede6b608219ce36080843abaf5743582c4fe | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499034018069352449/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 3e4fede6b608219ce36080843abaf5743582c4fe | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499034018069352449/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
piyush-garg: /retest
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 3e4fede6b608219ce36080843abaf5743582c4fe | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499058680555900928/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499365955355021312/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499365955355021312/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499365955355021312/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499365955355021312/artifacts/line-cov.html#file6) | 41.3% | 40.6% | -0.6
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499365955355021312/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499365955355021312/artifacts/line-cov.html#file9) | Do not exist | 76.4% | 

tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499371870258991106/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499371870258991106/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499371870258991106/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499371870258991106/artifacts/line-cov.html#file6) | 41.3% | 40.6% | -0.6
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499371870258991106/artifacts/line-cov.html#file8) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499371870258991106/artifacts/line-cov.html#file9) | Do not exist | 59.7% | 

tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499371870258991104/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499371870258991104/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
concaf: /retest
tekton-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/tektoncd/operator/pull/630#pullrequestreview-897431528" title="Approved">concaf</a>*, *<a href="https://github.com/tektoncd/operator/pull/630#pullrequestreview-898965049" title="LGTM">vdemeester</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=tektoncd%2Foperator).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/tektoncd/operator/blob/main/OWNERS)~~ [vdemeester]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499379923867930624/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
piyush-garg: /retest
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499385836616028160/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
piyush-garg: /retest
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499397413062840320/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499397413062840320/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
sm43: /test pull-tekton-operator-integration-tests
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499414401101336576/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499414401101336576/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
piyush-garg: /retest
piyush-garg: /test pull-tekton-operator-integration-tests
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499427235050819584/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499427235050819584/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499434785116786688/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499434785116786688/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
piyush-garg: /test pull-tekton-operator-integration-tests
piyush-garg: /test pull-tekton-operator-integration-tests
piyush-garg: /test pull-tekton-operator-integration-tests
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499487759805452288/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499487759805452288/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
piyush-garg: /retest
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499498958219644928/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: @piyush-garg: The following test **failed**, say `/retest` to rerun them all:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-tekton-operator-integration-tests | 2023eca45670c66d81200e4147a7bcbf5852eb00 | [link](https://tekton-releases.appspot.com/build/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-integration-tests/1499498958219644928/) | `/test pull-tekton-operator-integration-tests`

[Full PR test history](https://tekton-releases.appspot.com/pr/tektoncd_operator/630). [Your PR dashboard](https://prow.tekton.dev/pr/piyush-garg).

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
tekton-robot: New changes are detected. LGTM label has been removed.
tekton-robot: The following is the coverage report on the affected files.
Say `/test pull-tekton-operator-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499649071860682753/artifacts/line-cov.html#file1) | Do not exist | 43.8% | 
[pkg/apis/operator/v1alpha1/tektonchains_types.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499649071860682753/artifacts/line-cov.html#file2) | Do not exist | 0.0% | 
[pkg/apis/operator/v1alpha1/tektonchains_validation.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499649071860682753/artifacts/line-cov.html#file3) | Do not exist | 75.0% | 
[pkg/reconciler/common/releases.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499649071860682753/artifacts/line-cov.html#file7) | 41.3% | 40.6% | -0.6
[pkg/reconciler/openshift/common/transformer.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499649071860682753/artifacts/line-cov.html#file9) | 80.0% | 81.2% | 1.2
[pkg/reconciler/shared/tektonconfig/chains/chains.go](https://storage.cloud.google.com/tekton-prow/pr-logs/pull/tektoncd_operator/630/pull-tekton-operator-go-coverage/1499649071860682753/artifacts/line-cov.html#file10) | Do not exist | 61.8% | 

sm43: CI 🎉 
/lgtm
/meow
tekton-robot: @sm43: ![cat image](https://cdn2.thecatapi.com/images/s42I_BL-a.jpg)

<details>

In response to [this](https://github.com/tektoncd/operator/pull/630#issuecomment-1058923963):

>CI 🎉 
>/lgtm
>/meow


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

Patch:
diff --git a/Makefile b/Makefile
index e9b48d386..4c7439dbc 100644
--- a/Makefile
+++ b/Makefile
@@ -36,6 +36,7 @@ TEKTON_DASHBOARD_VERSION ?= latest
 TEKTON_RESULTS_VERSION ?= v0.4.0 # latest returns an older version hence hard coding to v0.3.1 for now (tektoncd/results#138)
 PAC_VERSION ?= 0.5.3
 TEKTON_HUB_VERSION ?= v1.6.0 # latest doesn't returns any version hence hard coding to v1.6.0 for now
+TEKTON_CHAINS_VERSION ?= latest
 
 $(BIN)/ko: PACKAGE=github.com/google/ko
 
@@ -64,6 +65,7 @@ clean-manifest:
 ifeq ($(TARGET), openshift)
 	rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-pipeline
 	rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-trigger
+	rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-chains
 	rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-hub
 	rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-addon/pipelines-as-code
 else
@@ -91,7 +93,8 @@ bin/%: cmd/% FORCE
 
 .PHONY: get-releases
 get-releases: |
-	$Q ./hack/fetch-releases.sh $(TARGET) $(TEKTON_PIPELINE_VERSION) $(TEKTON_TRIGGERS_VERSION) $(TEKTON_DASHBOARD_VERSION) $(TEKTON_RESULTS_VERSION) $(PAC_VERSION) $(TEKTON_HUB_VERSION) || exit ;
+	$Q ./hack/fetch-releases.sh $(TARGET) $(TEKTON_PIPELINE_VERSION) $(TEKTON_TRIGGERS_VERSION) $(TEKTON_DASHBOARD_VERSION) $(TEKTON_RESULTS_VERSION) $(PAC_VERSION) $(TEKTON_HUB_VERSION) $(TEKTON_CHAINS_VERSION) || exit ;
+
 .PHONY: apply
 apply: | $(KO) $(KUSTOMIZE) get-releases ; $(info $(M) ko apply on $(TARGET)) @ ## Apply config to the current cluster
 	@ ## --load-restrictor LoadRestrictionsNone is needed in kustomize build as files which not in child tree of kustomize base are pulled
diff --git a/cmd/kubernetes/operator/main.go b/cmd/kubernetes/operator/main.go
index 3ca2e3ff4..181aa85dd 100644
--- a/cmd/kubernetes/operator/main.go
+++ b/cmd/kubernetes/operator/main.go
@@ -17,6 +17,7 @@ limitations under the License.
 package main
 
 import (
+	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektonchains"
 	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektonconfig"
 	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektondashboard"
 	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektonhub"
@@ -36,5 +37,6 @@ func main() {
 		tektonresult.NewController,
 		tektoninstallerset.NewController,
 		tektonhub.NewController,
+		tektonchains.NewController,
 	)
 }
diff --git a/cmd/openshift/operator/main.go b/cmd/openshift/operator/main.go
index 26975f14d..def786d94 100644
--- a/cmd/openshift/operator/main.go
+++ b/cmd/openshift/operator/main.go
@@ -19,6 +19,7 @@ package main
 import (
 	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset"
 	"github.com/tektoncd/operator/pkg/reconciler/openshift/tektonaddon"
+	"github.com/tektoncd/operator/pkg/reconciler/openshift/tektonchains"
 	"github.com/tektoncd/operator/pkg/reconciler/openshift/tektonconfig"
 	"github.com/tektoncd/operator/pkg/reconciler/openshift/tektonhub"
 	"github.com/tektoncd/operator/pkg/reconciler/openshift/tektonpipeline"
@@ -34,5 +35,6 @@ func main() {
 		tektonconfig.NewController,
 		tektoninstallerset.NewController,
 		tektonhub.NewController,
+		tektonchains.NewController,
 	)
 }
diff --git a/config/base/300-operator_v1alpha1_chains_crd.yaml b/config/base/300-operator_v1alpha1_chains_crd.yaml
new file mode 100644
index 000000000..4765bdbaa
--- /dev/null
+++ b/config/base/300-operator_v1alpha1_chains_crd.yaml
@@ -0,0 +1,50 @@
+# Copyright 2022 The Tekton Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  name: tektonchainses.operator.tekton.dev
+  labels:
+    version: "devel"
+    operator.tekton.dev/release: "devel"
+spec:
+  group: operator.tekton.dev
+  names:
+    kind: TektonChains
+    singular: tektonchains
+    plural: tektonchainses
+  preserveUnknownFields: false
+  scope: Cluster
+  versions:
+  - name: v1alpha1
+    served: true
+    storage: true
+    subresources:
+      status: {}
+    additionalPrinterColumns:
+    - jsonPath: .status.version
+      name: Version
+      type: string
+    - jsonPath: .status.conditions[?(@.type=="Ready")].status
+      name: Ready
+      type: string
+    - jsonPath: ".status.conditions[?(@.type==\"Ready\")].reason"
+      name: Reason
+      type: string
+    schema:
+      openAPIV3Schema:
+        type: object
+        description: Schema for the TektonChains API
+        x-kubernetes-preserve-unknown-fields: true
diff --git a/config/base/300-operator_v1alpha1_hub_crd.yaml b/config/base/300-operator_v1alpha1_hub_crd.yaml
index 6f10c8e2e..7729ba8b3 100644
--- a/config/base/300-operator_v1alpha1_hub_crd.yaml
+++ b/config/base/300-operator_v1alpha1_hub_crd.yaml
@@ -47,6 +47,9 @@ spec:
         - jsonPath: .status.apiUrl
           name: ApiUrl
           type: string
+        - jsonPath: .status.uiUrl
+          name: UiUrl
+          type: string
       schema:
         openAPIV3Schema:
           type: object
diff --git a/config/base/kustomization.yaml b/config/base/kustomization.yaml
index 0c86fb0fa..01495bac7 100644
--- a/config/base/kustomization.yaml
+++ b/config/base/kustomization.yaml
@@ -18,6 +18,7 @@ resources:
 - 300-operator_v1alpha1_pipeline_crd.yaml
 - 300-operator_v1alpha1_trigger_crd.yaml
 - 300-operator_v1alpha1_config_crd.yaml
+- 300-operator_v1alpha1_chains_crd.yaml
 - 300-operator_v1alpha1_installer_set_crd.yaml
 - 300-operator_v1alpha1_hub_crd.yaml
 - config-logging.yaml
diff --git a/config/crs/kubernetes/chains/operator_v1alpha1_chains_cr.yaml b/config/crs/kubernetes/chains/operator_v1alpha1_chains_cr.yaml
new file mode 100644
index 000000000..44cafdc91
--- /dev/null
+++ b/config/crs/kubernetes/chains/operator_v1alpha1_chains_cr.yaml
@@ -0,0 +1,20 @@
+# Copyright 2022 The Tekton Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: operator.tekton.dev/v1alpha1
+kind: TektonChains
+metadata:
+  name: chains
+spec:
+  targetNamespace: tekton-pipelines
diff --git a/config/crs/kubernetes/kustomization.yaml b/config/crs/kubernetes/kustomization.yaml
index 2505c4ce5..1494dc985 100644
--- a/config/crs/kubernetes/kustomization.yaml
+++ b/config/crs/kubernetes/kustomization.yaml
@@ -7,3 +7,4 @@ resources:
 - trigger/operator_v1alpha1_trigger_cr.yaml
 - config/all/operator_v1alpha1_config_cr.yaml
 - installerset/operator_v1alpha1_installerset_cr.yaml
+- chains/operator_v1alpha1_chains_cr.yaml
diff --git a/config/crs/openshift/chains/operator_v1alpha1_chains_cr.yaml b/config/crs/openshift/chains/operator_v1alpha1_chains_cr.yaml
new file mode 100644
index 000000000..8596dbdd7
--- /dev/null
+++ b/config/crs/openshift/chains/operator_v1alpha1_chains_cr.yaml
@@ -0,0 +1,20 @@
+# Copyright 2022 The Tekton Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: operator.tekton.dev/v1alpha1
+kind: TektonChains
+metadata:
+  name: chains
+spec:
+  targetNamespace: openshift-pipelines
diff --git a/config/crs/openshift/kustomization.yaml b/config/crs/openshift/kustomization.yaml
index c0ac0e107..58c68f68d 100644
--- a/config/crs/openshift/kustomization.yaml
+++ b/config/crs/openshift/kustomization.yaml
@@ -4,5 +4,6 @@ resources:
 - pipeline/operator_v1alpha1_pipeline_cr.yaml
 - trigger/operator_v1alpha1_trigger_cr.yaml
 - installerset/operator_v1alpha1_installerset_cr.yaml
+- chains/operator_v1alpha1_chains_cr.yaml
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
diff --git a/docs/README.md b/docs/README.md
index 9728301fe..09c3f9686 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -46,6 +46,10 @@ Tekton Operator defines the following entities:
     <td><code>TektonResult</code></td>
     <td>Configure the <a HREF="https://github.com/tektoncd/results">Tekton Result</a> component to be installed and managed.</td>
   </tr>
+  <tr>
+    <td><code>TektonChains</code></td>
+    <td>Configure the <a HREF="https://github.com/tektoncd/chains">Tekton Chains</a> component to be installed and managed.</td>
+  </tr>
   <tr>
     <td><code>TektonAddon</code></td>
     <td>Configure addons to be installed and managed.</td>
@@ -68,7 +72,7 @@ To install Operator there are multiple ways
 
   You can clone and repository and install the Operator. You can find the instruction in [here](../DEVELOPMENT.md)
 
-After installing the Operator, to install the required Tekton Component such as Tekton Pipeline, Tekton Triggers.
+After installing the Operator, to install the required Tekton Component such as Tekton Pipeline, Tekton Triggers, Tekton Chains.
 
 Create an instance of `TektonConfig` which will create the required components. You can find more details and the available configuration in [TektonConfig](TektonConfig.md).
 
@@ -90,6 +94,7 @@ You can find more about the Resources and its available configurations in their
 - [TektonTrigger](./TektonTrigger.md)
 - [TektonDashboard](./TektonDashboard.md)
 - [TektonResult](./TektonResult.md)
+- [TektonChains](./TektonChains.md)
 - [TektonAddon](./TektonAddon.md)
 
 To understand how Tekton Operator works, you can find the details [here](TektonOperator.md)
diff --git a/docs/TektonChains.md b/docs/TektonChains.md
new file mode 100644
index 000000000..e9c4471de
--- /dev/null
+++ b/docs/TektonChains.md
@@ -0,0 +1,24 @@
+<!--
+---
+linkTitle: "TektonChains"
+weight: 9
+---
+-->
+# Tekton Chains
+
+TektonChains custom resource allows user to install and manage [Tekton Chains][chains]. 
+
+It is recommended to install the components through [TektonConfig](./TektonConfig.md).
+
+The TektonChains CR is as below:
+```yaml
+apiVersion: operator.tekton.dev/v1alpha1
+kind: TektonChains
+metadata:
+  name: chains
+spec:
+  targetNamespace: tekton-pipelines
+```
+You can install this component using [TektonConfig](./TektonConfig.md) by choosing appropriate `profile`.
+
+[chains]:https://github.com/tektoncd/chains
diff --git a/docs/TektonConfig.md b/docs/TektonConfig.md
index 1491e4911..cec82e5ec 100644
--- a/docs/TektonConfig.md
+++ b/docs/TektonConfig.md
@@ -13,6 +13,7 @@ Operator provides support for installing and managing following operator compone
 
 - [TektonPipeline](./TektonPipeline.md)
 - [TektonTrigger](./TektonTrigger.md)
+- [TektonChains](./TektonChains.md)
 
 Other than the above components depending on the platform operator also provides support for
 
@@ -73,7 +74,7 @@ By default, namespace would be `tekton-pipelines` for Kubernetes and `openshift-
 
 This allows user to choose which all components to install on the cluster.
 There are 3 profiles available:
-- `all`: This profile will install all components
+- `all`: This profile will install all components (TektonPipeline, TektonTrigger and TektonChains)
 - `basic`:  This profile will install only TektonPipeline and TektonTrigger component
 - `lite`: This profile will install only TektonPipeline component
 
diff --git a/hack/fetch-releases.sh b/hack/fetch-releases.sh
index 964faf692..1a3eb51e9 100755
--- a/hack/fetch-releases.sh
+++ b/hack/fetch-releases.sh
@@ -131,7 +131,7 @@ release_yaml_hub() {
   mkdir -p ${dirPath} || true
 
   url=""
-  components="db db-migration api"
+  components="db db-migration api ui"
 
   for component in ${components}; do
     dest=${dirPath}/${component}
@@ -143,6 +143,9 @@ release_yaml_hub() {
     [[ ${component} == "api" ]] && fileName=${component}-k8s.yaml
     [[ ${component} == "api" ]] && [[ ${TARGET} == "openshift" ]] && fileName=${component}-openshift.yaml
 
+    [[ ${component} == "ui" ]] && fileName=${component}-k8s.yaml
+    [[ ${component} == "ui" ]] && [[ ${TARGET} == "openshift" ]] && fileName=${component}-openshift.yaml
+
     url="https://github.com/tektoncd/hub/releases/download/${version}/${fileName}"
     echo $url
     http_response=$(curl -s -L -o ${dest}/${fileName} -w "%{http_code}" ${url})
@@ -156,24 +159,31 @@ release_yaml_hub() {
   done
 }
 
-#Args: <target-platform> <pipelines version> <triggers version> <dashboard version> <results version> <pac version> <hub version>
+#Args: <target-platform> <pipelines version> <triggers version> <dashboard version> <results version> <pac version> <hub version> <chains version>
 main() {
   TARGET=$1
   p_version=${2}
   t_version=${3}
+  c_version=${8}
 
-
+  # get release YAML for Pipelines
   release_yaml pipeline release 00-pipelines ${p_version}
 
+  # get release YAML for Triggers
   release_yaml triggers release 00-triggers ${t_version}
   release_yaml triggers interceptors 01-interceptors ${t_version}
 
+  # get release YAML for Chains
+  release_yaml chains release 00-chains ${c_version}
+
   if [[ ${TARGET} != "openshift" ]]; then
     d_version=${4}
+    # get release YAML for Dashboard
     release_yaml dashboard tekton-dashboard-release 00-dashboard ${d_version}
     release_yaml dashboard tekton-dashboard-release-readonly 00-dashboard ${d_version}
 
     r_version=${5}
+    # get release YAML for Results
     release_yaml results release 00-results ${r_version}
   else
     pac_version=${6}
diff --git a/pkg/apis/operator/v1alpha1/const.go b/pkg/apis/operator/v1alpha1/const.go
index 9c0521a2c..42df244d1 100644
--- a/pkg/apis/operator/v1alpha1/const.go
+++ b/pkg/apis/operator/v1alpha1/const.go
@@ -98,4 +98,5 @@ var (
 	ConfigResourceName    = "config"
 	ResultResourceName    = "result"
 	HubResourceName       = "hub"
+	ChainsResourceName    = "chains"
 )
diff --git a/pkg/apis/operator/v1alpha1/register.go b/pkg/apis/operator/v1alpha1/register.go
index fb8705c0d..f72c1bfed 100644
--- a/pkg/apis/operator/v1alpha1/register.go
+++ b/pkg/apis/operator/v1alpha1/register.go
@@ -52,6 +52,9 @@ const (
 
 	// KindTektonHub is the Kind of TektonHub in a GVK context.
 	KindTektonHub = "TektonHub"
+
+	// KindTektonChains is the Kind of Tekton Chains in a GVK context.
+	KindTektonChains = "TektonChains"
 )
 
 // Resource takes an unqualified resource and returns a Group qualified GroupResource
@@ -79,6 +82,8 @@ func addKnownTypes(s *runtime.Scheme) error {
 		&TektonInstallerSetList{},
 		&TektonHub{},
 		&TektonHubList{},
+		&TektonChains{},
+		&TektonChainsList{},
 	)
 	metav1.AddToGroupVersion(s, SchemeGroupVersion)
 	return nil
diff --git a/pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go b/pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go
new file mode 100644
index 000000000..e1b578f71
--- /dev/null
+++ b/pkg/apis/operator/v1alpha1/tektonchains_lifecycle.go
@@ -0,0 +1,183 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1alpha1
+
+import (
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"knative.dev/pkg/apis"
+)
+
+var (
+	_ TektonComponentStatus = (*TektonChainsStatus)(nil)
+
+	chainsCondSet = apis.NewLivingConditionSet(
+		DependenciesInstalled,
+		PreReconciler,
+		InstallerSetAvailable,
+		InstallerSetReady,
+		PostReconciler,
+	)
+)
+
+// GroupVersionKind returns SchemeGroupVersion of a TektonChains
+func (tc *TektonChains) GroupVersionKind() schema.GroupVersionKind {
+	return SchemeGroupVersion.WithKind(KindTektonChains)
+}
+
+func (tc *TektonChains) GetGroupVersionKind() schema.GroupVersionKind {
+	return SchemeGroupVersion.WithKind(KindTektonChains)
+}
+
+// GetCondition returns the current condition of a given condition type
+func (tcs *TektonChainsStatus) GetCondition(t apis.ConditionType) *apis.Condition {
+	return chainsCondSet.Manage(tcs).GetCondition(t)
+}
+
+// InitializeConditions initializes conditions of an TektonChainsStatus
+func (tcs *TektonChainsStatus) InitializeConditions() {
+	chainsCondSet.Manage(tcs).InitializeConditions()
+}
+
+// IsReady looks at the conditions returns true if they are all true.
+func (tcs *TektonChainsStatus) IsReady() bool {
+	return chainsCondSet.Manage(tcs).IsHappy()
+}
+
+func (tcs *TektonChainsStatus) MarkPreReconcilerComplete() {
+	chainsCondSet.Manage(tcs).MarkTrue(PreReconciler)
+}
+
+func (tcs *TektonChainsStatus) MarkInstallerSetAvailable() {
+	chainsCondSet.Manage(tcs).MarkTrue(InstallerSetAvailable)
+}
+
+func (tcs *TektonChainsStatus) MarkInstallerSetReady() {
+	chainsCondSet.Manage(tcs).MarkTrue(InstallerSetReady)
+}
+
+func (tcs *TektonChainsStatus) MarkPostReconcilerComplete() {
+	chainsCondSet.Manage(tcs).MarkTrue(PostReconciler)
+}
+
+// MarkDependenciesInstalled marks the DependenciesInstalled status as true.
+func (tcs *TektonChainsStatus) MarkDependenciesInstalled() {
+	chainsCondSet.Manage(tcs).MarkTrue(DependenciesInstalled)
+}
+
+func (tcs *TektonChainsStatus) MarkNotReady(msg string) {
+	chainsCondSet.Manage(tcs).MarkFalse(
+		apis.ConditionReady,
+		"Error",
+		"Ready: %s", msg)
+}
+
+func (tcs *TektonChainsStatus) MarkPreReconcilerFailed(msg string) {
+	tcs.MarkNotReady("PreReconciliation failed")
+	chainsCondSet.Manage(tcs).MarkFalse(
+		PreReconciler,
+		"Error",
+		"PreReconciliation failed with message: %s", msg)
+}
+
+func (tcs *TektonChainsStatus) MarkInstallerSetNotAvailable(msg string) {
+	tcs.MarkNotReady("TektonInstallerSet not ready")
+	chainsCondSet.Manage(tcs).MarkFalse(
+		InstallerSetAvailable,
+		"Error",
+		"Installer set not ready: %s", msg)
+}
+
+func (tcs *TektonChainsStatus) MarkInstallerSetNotReady(msg string) {
+	tcs.MarkNotReady("TektonInstallerSet not ready")
+	chainsCondSet.Manage(tcs).MarkFalse(
+		InstallerSetReady,
+		"Error",
+		"Installer set not ready: %s", msg)
+}
+
+func (tcs *TektonChainsStatus) MarkPostReconcilerFailed(msg string) {
+	tcs.MarkNotReady("PostReconciliation failed")
+	chainsCondSet.Manage(tcs).MarkFalse(
+		PostReconciler,
+		"Error",
+		"PostReconciliation failed with message: %s", msg)
+}
+
+// MarkDependencyInstalling marks the DependenciesInstalled status as false with the
+// given message.
+func (tcs *TektonChainsStatus) MarkDependencyInstalling(msg string) {
+	tcs.MarkNotReady("Dependencies installing")
+	chainsCondSet.Manage(tcs).MarkFalse(
+		DependenciesInstalled,
+		"Error",
+		"Dependency installing: %s", msg)
+}
+
+// MarkDependencyMissing marks the DependenciesInstalled status as false with the
+// given message.
+func (tcs *TektonChainsStatus) MarkDependencyMissing(msg string) {
+	tcs.MarkNotReady("Missing Dependencies for TektonChains")
+	chainsCondSet.Manage(tcs).MarkFalse(
+		DependenciesInstalled,
+		"Error",
+		"Dependency missing: %s", msg)
+}
+
+func (tcs *TektonChainsStatus) GetTektonInstallerSet() string {
+	return tcs.TektonInstallerSet
+}
+
+func (tcs *TektonChainsStatus) SetTektonInstallerSet(installerSet string) {
+	tcs.TektonInstallerSet = installerSet
+}
+
+// GetVersion gets the currently installed version of the component.
+func (tcs *TektonChainsStatus) GetVersion() string {
+	return tcs.Version
+}
+
+// SetVersion sets the currently installed version of the component.
+func (tcs *TektonChainsStatus) SetVersion(version string) {
+	tcs.Version = version
+}
+
+// MarkInstallSucceeded marks the InstallationSucceeded status as true.
+func (tcs *TektonChainsStatus) MarkInstallSucceeded() {
+	panic("implement me")
+}
+
+// MarkInstallFailed marks the InstallationSucceeded status as false with the given
+// message.
+func (tcs *TektonChainsStatus) MarkInstallFailed(msg string) {
+	panic("implement me")
+}
+
+// MarkDeploymentsAvailable marks the DeploymentsAvailable status as true.
+func (tcs *TektonChainsStatus) MarkDeploymentsAvailable() {
+	panic("implement me")
+}
+
+// MarkDeploymentsNotReady marks the DeploymentsAvailable status as false and calls out
+// it's waiting for deployments.
+func (tcs *TektonChainsStatus) MarkDeploymentsNotReady() {
+	panic("implement me")
+}
+
+// GetManifests gets the url links of the manifests.
+func (tcs *TektonChainsStatus) GetManifests() []string {
+	panic("implement me")
+}
diff --git a/pkg/apis/operator/v1alpha1/tektonchains_types.go b/pkg/apis/operator/v1alpha1/tektonchains_types.go
new file mode 100644
index 000000000..bc1351b06
--- /dev/null
+++ b/pkg/apis/operator/v1alpha1/tektonchains_types.go
@@ -0,0 +1,79 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1alpha1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	duckv1 "knative.dev/pkg/apis/duck/v1"
+)
+
+var (
+	_ TektonComponent     = (*TektonChains)(nil)
+	_ TektonComponentSpec = (*TektonChainsSpec)(nil)
+)
+
+// TektonChains is the Schema for the tektonchains API
+// +genclient
+// +genreconciler:krshapedlogic=false
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +genclient:nonNamespaced
+type TektonChains struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   TektonChainsSpec   `json:"spec,omitempty"`
+	Status TektonChainsStatus `json:"status,omitempty"`
+}
+
+// GetSpec implements TektonComponent
+func (tc *TektonChains) GetSpec() TektonComponentSpec {
+	return &tc.Spec
+}
+
+// GetStatus implements TektonComponent
+func (tc *TektonChains) GetStatus() TektonComponentStatus {
+	return &tc.Status
+}
+
+// TektonChainsSpec defines the desired state of TektonChains
+type TektonChainsSpec struct {
+	CommonSpec `json:",inline"`
+	// Config holds the configuration for resources created by TektonChains
+	// +optional
+	Config Config `json:"config,omitempty"`
+}
+
+// TektonChainsStatus defines the observed state of TektonChains
+type TektonChainsStatus struct {
+	duckv1.Status `json:",inline"`
+
+	// The version of the installed release
+	// +optional
+	Version string `json:"version,omitempty"`
+
+	// The current installer set name for TektonChains
+	// +optional
+	TektonInstallerSet string `json:"tektonInstallerSet,omitempty"`
+}
+
+// TektonChainsList contains a list of TektonChains
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type TektonChainsList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []TektonChains `json:"items"`
+}
diff --git a/pkg/apis/operator/v1alpha1/tektonchains_validation.go b/pkg/apis/operator/v1alpha1/tektonchains_validation.go
new file mode 100644
index 000000000..778edbdf7
--- /dev/null
+++ b/pkg/apis/operator/v1alpha1/tektonchains_validation.go
@@ -0,0 +1,45 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1alpha1
+
+import (
+	"context"
+	"fmt"
+
+	"knative.dev/pkg/apis"
+)
+
+func (tc *TektonChains) Validate(ctx context.Context) (errs *apis.FieldError) {
+
+	if apis.IsInDelete(ctx) {
+		return nil
+	}
+
+	if tc.GetName() != ChainsResourceName {
+		errMsg := fmt.Sprintf("metadata.name, Only one instance of TektonChains is allowed by name, %s", ChainsResourceName)
+		errs = errs.Also(apis.ErrInvalidValue(tc.GetName(), errMsg))
+	}
+
+	if tc.Spec.TargetNamespace == "" {
+		errs = errs.Also(apis.ErrMissingField("spec.targetNamespace"))
+	}
+
+	return errs
+}
+
+func (tc *TektonChains) SetDefaults(ctx context.Context) {
+}
diff --git a/pkg/apis/operator/v1alpha1/tektonhub_defaults.go b/pkg/apis/operator/v1alpha1/tektonhub_defaults.go
index f24b1a48b..5b14e5dce 100644
--- a/pkg/apis/operator/v1alpha1/tektonhub_defaults.go
+++ b/pkg/apis/operator/v1alpha1/tektonhub_defaults.go
@@ -34,4 +34,5 @@ func (th *TektonHub) SetDefaults(ctx context.Context) {
 	if th.Spec.CommonSpec.TargetNamespace == "" {
 		th.Spec.CommonSpec.TargetNamespace = os.Getenv("DEFAULT_TARGET_NAMESPACE")
 	}
+
 }
diff --git a/pkg/apis/operator/v1alpha1/tektonhub_lifecycle.go b/pkg/apis/operator/v1alpha1/tektonhub_lifecycle.go
index 1be0b4802..afc26e28b 100644
--- a/pkg/apis/operator/v1alpha1/tektonhub_lifecycle.go
+++ b/pkg/apis/operator/v1alpha1/tektonhub_lifecycle.go
@@ -30,6 +30,9 @@ const (
 	// API
 	ApiDependenciesInstalled apis.ConditionType = "ApiDependenciesInstalled"
 	ApiInstallerSetAvailable apis.ConditionType = "ApiInstallSetAvailable"
+	// UI
+	UiDependenciesInstalled apis.ConditionType = "UiDependenciesInstalled"
+	UiInstallerSetAvailable apis.ConditionType = "UiInstallSetAvailable"
 )
 
 var (
@@ -45,6 +48,8 @@ var (
 		PreReconciler,
 		ApiDependenciesInstalled,
 		ApiInstallerSetAvailable,
+		UiDependenciesInstalled,
+		UiInstallerSetAvailable,
 		PostReconciler,
 	)
 )
@@ -161,6 +166,49 @@ func (ths *TektonHubStatus) MarkApiInstallerSetAvailable() {
 	hubCondSet.Manage(ths).MarkTrue(ApiInstallerSetAvailable)
 }
 
+// UI
+func (ths *TektonHubStatus) MarkUiDependencyInstalling(msg string) {
+	ths.MarkNotReady("Dependencies installing for UI")
+	hubCondSet.Manage(ths).MarkFalse(
+		UiDependenciesInstalled,
+		"Error",
+		"Dependencies are installing for UI: %s", msg)
+}
+
+func (ths *TektonHubStatus) MarkUiDependencyMissing(msg string) {
+	ths.MarkNotReady("Missing Dependencies for UI")
+	hubCondSet.Manage(ths).MarkFalse(
+		UiDependenciesInstalled,
+		"Error",
+		"Dependencies are missing for UI: %s", msg)
+}
+
+func (ths *TektonHubStatus) MarkUiDependenciesInstalled() {
+	hubCondSet.Manage(ths).MarkTrue(UiDependenciesInstalled)
+}
+
+func (ths *TektonHubStatus) MarkUiInstallerSetNotAvailable(msg string) {
+	ths.MarkNotReady("TektonInstallerSet not ready for UI")
+	hubCondSet.Manage(ths).MarkFalse(
+		UiInstallerSetAvailable,
+		"Error",
+		"Installer set not ready for UI: %s", msg)
+}
+
+func (ths *TektonHubStatus) MarkUiInstallerSetAvailable() {
+	hubCondSet.Manage(ths).MarkTrue(UiInstallerSetAvailable)
+}
+
+// GetManifests gets the url links of the manifests.
+func (ths *TektonHubStatus) GetUiRoute() string {
+	return ths.UiRouteUrl
+}
+
+// SetManifests sets the url links of the manifests.
+func (ths *TektonHubStatus) SetUiRoute(routeUrl string) {
+	ths.UiRouteUrl = routeUrl
+}
+
 func (ths *TektonHubStatus) MarkPreReconcilerFailed(msg string) {
 	ths.MarkNotReady("PreReconciliation failed")
 	hubCondSet.Manage(ths).MarkFalse(
diff --git a/pkg/apis/operator/v1alpha1/tektonhub_types.go b/pkg/apis/operator/v1alpha1/tektonhub_types.go
index 9873acbf7..f57ad2c06 100644
--- a/pkg/apis/operator/v1alpha1/tektonhub_types.go
+++ b/pkg/apis/operator/v1alpha1/tektonhub_types.go
@@ -83,6 +83,10 @@ type TektonHubStatus struct {
 	// +optional
 	AuthRouteUrl string `json:"authUrl,omitempty"`
 
+	// The URL route for UI which needs to be exposed
+	// +optional
+	UiRouteUrl string `json:"uiUrl,omitempty"`
+
 	// The current installer set name
 	// +optional
 	HubInstallerSet map[string]string `json:"hubInstallerSets,omitempty"`
diff --git a/pkg/apis/operator/v1alpha1/tektonhub_validation.go b/pkg/apis/operator/v1alpha1/tektonhub_validation.go
index ead6a0c0b..5c43dd74c 100644
--- a/pkg/apis/operator/v1alpha1/tektonhub_validation.go
+++ b/pkg/apis/operator/v1alpha1/tektonhub_validation.go
@@ -50,6 +50,7 @@ func (th *TektonHub) Validate(ctx context.Context) (errs *apis.FieldError) {
 	errs = errs.Also(th.Spec.Db.validate("spec.db"))
 
 	return errs.Also(th.Spec.Api.validate("spec.api"))
+
 }
 
 func (db *DbSpec) validate(path string) (errs *apis.FieldError) {
diff --git a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
index 74e0e8982..c53b6d119 100644
--- a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go
@@ -495,6 +495,102 @@ func (in *TektonAddonStatus) DeepCopy() *TektonAddonStatus {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TektonChains) DeepCopyInto(out *TektonChains) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TektonChains.
+func (in *TektonChains) DeepCopy() *TektonChains {
+	if in == nil {
+		return nil
+	}
+	out := new(TektonChains)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *TektonChains) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TektonChainsList) DeepCopyInto(out *TektonChainsList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]TektonChains, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TektonChainsList.
+func (in *TektonChainsList) DeepCopy() *TektonChainsList {
+	if in == nil {
+		return nil
+	}
+	out := new(TektonChainsList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *TektonChainsList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TektonChainsSpec) DeepCopyInto(out *TektonChainsSpec) {
+	*out = *in
+	out.CommonSpec = in.CommonSpec
+	in.Config.DeepCopyInto(&out.Config)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TektonChainsSpec.
+func (in *TektonChainsSpec) DeepCopy() *TektonChainsSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(TektonChainsSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TektonChainsStatus) DeepCopyInto(out *TektonChainsStatus) {
+	*out = *in
+	in.Status.DeepCopyInto(&out.Status)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TektonChainsStatus.
+func (in *TektonChainsStatus) DeepCopy() *TektonChainsStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(TektonChainsStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *TektonConfig) DeepCopyInto(out *TektonConfig) {
 	*out = *in
diff --git a/pkg/client/clientset/versioned/typed/operator/v1alpha1/fake/fake_operator_client.go b/pkg/client/clientset/versioned/typed/operator/v1alpha1/fake/fake_operator_client.go
index 4f5a18799..2fc52bca8 100644
--- a/pkg/client/clientset/versioned/typed/operator/v1alpha1/fake/fake_operator_client.go
+++ b/pkg/client/clientset/versioned/typed/operator/v1alpha1/fake/fake_operator_client.go
@@ -32,6 +32,10 @@ func (c *FakeOperatorV1alpha1) TektonAddons() v1alpha1.TektonAddonInterface {
 	return &FakeTektonAddons{c}
 }
 
+func (c *FakeOperatorV1alpha1) TektonChainses() v1alpha1.TektonChainsInterface {
+	return &FakeTektonChainses{c}
+}
+
 func (c *FakeOperatorV1alpha1) TektonConfigs() v1alpha1.TektonConfigInterface {
 	return &FakeTektonConfigs{c}
 }
diff --git a/pkg/client/clientset/versioned/typed/operator/v1alpha1/fake/fake_tektonchains.go b/pkg/client/clientset/versioned/typed/operator/v1alpha1/fake/fake_tektonchains.go
new file mode 100644
index 000000000..72d70eec6
--- /dev/null
+++ b/pkg/client/clientset/versioned/typed/operator/v1alpha1/fake/fake_tektonchains.go
@@ -0,0 +1,133 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	"context"
+
+	v1alpha1 "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeTektonChainses implements TektonChainsInterface
+type FakeTektonChainses struct {
+	Fake *FakeOperatorV1alpha1
+}
+
+var tektonchainsesResource = schema.GroupVersionResource{Group: "operator.tekton.dev", Version: "v1alpha1", Resource: "tektonchainses"}
+
+var tektonchainsesKind = schema.GroupVersionKind{Group: "operator.tekton.dev", Version: "v1alpha1", Kind: "TektonChains"}
+
+// Get takes name of the tektonChains, and returns the corresponding tektonChains object, and an error if there is any.
+func (c *FakeTektonChainses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.TektonChains, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootGetAction(tektonchainsesResource, name), &v1alpha1.TektonChains{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.TektonChains), err
+}
+
+// List takes label and field selectors, and returns the list of TektonChainses that match those selectors.
+func (c *FakeTektonChainses) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.TektonChainsList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootListAction(tektonchainsesResource, tektonchainsesKind, opts), &v1alpha1.TektonChainsList{})
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v1alpha1.TektonChainsList{ListMeta: obj.(*v1alpha1.TektonChainsList).ListMeta}
+	for _, item := range obj.(*v1alpha1.TektonChainsList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested tektonChainses.
+func (c *FakeTektonChainses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewRootWatchAction(tektonchainsesResource, opts))
+}
+
+// Create takes the representation of a tektonChains and creates it.  Returns the server's representation of the tektonChains, and an error, if there is any.
+func (c *FakeTektonChainses) Create(ctx context.Context, tektonChains *v1alpha1.TektonChains, opts v1.CreateOptions) (result *v1alpha1.TektonChains, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootCreateAction(tektonchainsesResource, tektonChains), &v1alpha1.TektonChains{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.TektonChains), err
+}
+
+// Update takes the representation of a tektonChains and updates it. Returns the server's representation of the tektonChains, and an error, if there is any.
+func (c *FakeTektonChainses) Update(ctx context.Context, tektonChains *v1alpha1.TektonChains, opts v1.UpdateOptions) (result *v1alpha1.TektonChains, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootUpdateAction(tektonchainsesResource, tektonChains), &v1alpha1.TektonChains{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.TektonChains), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeTektonChainses) UpdateStatus(ctx context.Context, tektonChains *v1alpha1.TektonChains, opts v1.UpdateOptions) (*v1alpha1.TektonChains, error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootUpdateSubresourceAction(tektonchainsesResource, "status", tektonChains), &v1alpha1.TektonChains{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.TektonChains), err
+}
+
+// Delete takes name of the tektonChains and deletes it. Returns an error if one occurs.
+func (c *FakeTektonChainses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewRootDeleteAction(tektonchainsesResource, name), &v1alpha1.TektonChains{})
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeTektonChainses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	action := testing.NewRootDeleteCollectionAction(tektonchainsesResource, listOpts)
+
+	_, err := c.Fake.Invokes(action, &v1alpha1.TektonChainsList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched tektonChains.
+func (c *FakeTektonChainses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.TektonChains, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootPatchSubresourceAction(tektonchainsesResource, name, pt, data, subresources...), &v1alpha1.TektonChains{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1alpha1.TektonChains), err
+}
diff --git a/pkg/client/clientset/versioned/typed/operator/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/operator/v1alpha1/generated_expansion.go
index 367ed23c4..9108de871 100644
--- a/pkg/client/clientset/versioned/typed/operator/v1alpha1/generated_expansion.go
+++ b/pkg/client/clientset/versioned/typed/operator/v1alpha1/generated_expansion.go
@@ -20,6 +20,8 @@ package v1alpha1
 
 type TektonAddonExpansion interface{}
 
+type TektonChainsExpansion interface{}
+
 type TektonConfigExpansion interface{}
 
 type TektonDashboardExpansion interface{}
diff --git a/pkg/client/clientset/versioned/typed/operator/v1alpha1/operator_client.go b/pkg/client/clientset/versioned/typed/operator/v1alpha1/operator_client.go
index f3fcadf07..d5bd292dc 100644
--- a/pkg/client/clientset/versioned/typed/operator/v1alpha1/operator_client.go
+++ b/pkg/client/clientset/versioned/typed/operator/v1alpha1/operator_client.go
@@ -27,6 +27,7 @@ import (
 type OperatorV1alpha1Interface interface {
 	RESTClient() rest.Interface
 	TektonAddonsGetter
+	TektonChainsesGetter
 	TektonConfigsGetter
 	TektonDashboardsGetter
 	TektonHubsGetter
@@ -45,6 +46,10 @@ func (c *OperatorV1alpha1Client) TektonAddons() TektonAddonInterface {
 	return newTektonAddons(c)
 }
 
+func (c *OperatorV1alpha1Client) TektonChainses() TektonChainsInterface {
+	return newTektonChainses(c)
+}
+
 func (c *OperatorV1alpha1Client) TektonConfigs() TektonConfigInterface {
 	return newTektonConfigs(c)
 }
diff --git a/pkg/client/clientset/versioned/typed/operator/v1alpha1/tektonchains.go b/pkg/client/clientset/versioned/typed/operator/v1alpha1/tektonchains.go
new file mode 100644
index 000000000..f89797e4a
--- /dev/null
+++ b/pkg/client/clientset/versioned/typed/operator/v1alpha1/tektonchains.go
@@ -0,0 +1,184 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"context"
+	"time"
+
+	v1alpha1 "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	scheme "github.com/tektoncd/operator/pkg/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+)
+
+// TektonChainsesGetter has a method to return a TektonChainsInterface.
+// A group's client should implement this interface.
+type TektonChainsesGetter interface {
+	TektonChainses() TektonChainsInterface
+}
+
+// TektonChainsInterface has methods to work with TektonChains resources.
+type TektonChainsInterface interface {
+	Create(ctx context.Context, tektonChains *v1alpha1.TektonChains, opts v1.CreateOptions) (*v1alpha1.TektonChains, error)
+	Update(ctx context.Context, tektonChains *v1alpha1.TektonChains, opts v1.UpdateOptions) (*v1alpha1.TektonChains, error)
+	UpdateStatus(ctx context.Context, tektonChains *v1alpha1.TektonChains, opts v1.UpdateOptions) (*v1alpha1.TektonChains, error)
+	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
+	Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.TektonChains, error)
+	List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.TektonChainsList, error)
+	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.TektonChains, err error)
+	TektonChainsExpansion
+}
+
+// tektonChainses implements TektonChainsInterface
+type tektonChainses struct {
+	client rest.Interface
+}
+
+// newTektonChainses returns a TektonChainses
+func newTektonChainses(c *OperatorV1alpha1Client) *tektonChainses {
+	return &tektonChainses{
+		client: c.RESTClient(),
+	}
+}
+
+// Get takes name of the tektonChains, and returns the corresponding tektonChains object, and an error if there is any.
+func (c *tektonChainses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.TektonChains, err error) {
+	result = &v1alpha1.TektonChains{}
+	err = c.client.Get().
+		Resource("tektonchainses").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of TektonChainses that match those selectors.
+func (c *tektonChainses) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.TektonChainsList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v1alpha1.TektonChainsList{}
+	err = c.client.Get().
+		Resource("tektonchainses").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested tektonChainses.
+func (c *tektonChainses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Resource("tektonchainses").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch(ctx)
+}
+
+// Create takes the representation of a tektonChains and creates it.  Returns the server's representation of the tektonChains, and an error, if there is any.
+func (c *tektonChainses) Create(ctx context.Context, tektonChains *v1alpha1.TektonChains, opts v1.CreateOptions) (result *v1alpha1.TektonChains, err error) {
+	result = &v1alpha1.TektonChains{}
+	err = c.client.Post().
+		Resource("tektonchainses").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(tektonChains).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Update takes the representation of a tektonChains and updates it. Returns the server's representation of the tektonChains, and an error, if there is any.
+func (c *tektonChainses) Update(ctx context.Context, tektonChains *v1alpha1.TektonChains, opts v1.UpdateOptions) (result *v1alpha1.TektonChains, err error) {
+	result = &v1alpha1.TektonChains{}
+	err = c.client.Put().
+		Resource("tektonchainses").
+		Name(tektonChains.Name).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(tektonChains).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *tektonChainses) UpdateStatus(ctx context.Context, tektonChains *v1alpha1.TektonChains, opts v1.UpdateOptions) (result *v1alpha1.TektonChains, err error) {
+	result = &v1alpha1.TektonChains{}
+	err = c.client.Put().
+		Resource("tektonchainses").
+		Name(tektonChains.Name).
+		SubResource("status").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(tektonChains).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Delete takes name of the tektonChains and deletes it. Returns an error if one occurs.
+func (c *tektonChainses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	return c.client.Delete().
+		Resource("tektonchainses").
+		Name(name).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *tektonChainses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	var timeout time.Duration
+	if listOpts.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Resource("tektonchainses").
+		VersionedParams(&listOpts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// Patch applies the patch and returns the patched tektonChains.
+func (c *tektonChainses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.TektonChains, err error) {
+	result = &v1alpha1.TektonChains{}
+	err = c.client.Patch(pt).
+		Resource("tektonchainses").
+		Name(name).
+		SubResource(subresources...).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(data).
+		Do(ctx).
+		Into(result)
+	return
+}
diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go
index 93f16eafa..faf0f30b1 100644
--- a/pkg/client/informers/externalversions/generic.go
+++ b/pkg/client/informers/externalversions/generic.go
@@ -55,6 +55,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
 	// Group=operator.tekton.dev, Version=v1alpha1
 	case v1alpha1.SchemeGroupVersion.WithResource("tektonaddons"):
 		return &genericInformer{resource: resource.GroupResource(), informer: f.Operator().V1alpha1().TektonAddons().Informer()}, nil
+	case v1alpha1.SchemeGroupVersion.WithResource("tektonchainses"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Operator().V1alpha1().TektonChainses().Informer()}, nil
 	case v1alpha1.SchemeGroupVersion.WithResource("tektonconfigs"):
 		return &genericInformer{resource: resource.GroupResource(), informer: f.Operator().V1alpha1().TektonConfigs().Informer()}, nil
 	case v1alpha1.SchemeGroupVersion.WithResource("tektondashboards"):
diff --git a/pkg/client/informers/externalversions/operator/v1alpha1/interface.go b/pkg/client/informers/externalversions/operator/v1alpha1/interface.go
index 28f8cf2c3..0c18da3ae 100644
--- a/pkg/client/informers/externalversions/operator/v1alpha1/interface.go
+++ b/pkg/client/informers/externalversions/operator/v1alpha1/interface.go
@@ -26,6 +26,8 @@ import (
 type Interface interface {
 	// TektonAddons returns a TektonAddonInformer.
 	TektonAddons() TektonAddonInformer
+	// TektonChainses returns a TektonChainsInformer.
+	TektonChainses() TektonChainsInformer
 	// TektonConfigs returns a TektonConfigInformer.
 	TektonConfigs() TektonConfigInformer
 	// TektonDashboards returns a TektonDashboardInformer.
@@ -58,6 +60,11 @@ func (v *version) TektonAddons() TektonAddonInformer {
 	return &tektonAddonInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
 }
 
+// TektonChainses returns a TektonChainsInformer.
+func (v *version) TektonChainses() TektonChainsInformer {
+	return &tektonChainsInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
+}
+
 // TektonConfigs returns a TektonConfigInformer.
 func (v *version) TektonConfigs() TektonConfigInformer {
 	return &tektonConfigInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
diff --git a/pkg/client/informers/externalversions/operator/v1alpha1/tektonchains.go b/pkg/client/informers/externalversions/operator/v1alpha1/tektonchains.go
new file mode 100644
index 000000000..1dd25b061
--- /dev/null
+++ b/pkg/client/informers/externalversions/operator/v1alpha1/tektonchains.go
@@ -0,0 +1,89 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"context"
+	time "time"
+
+	operatorv1alpha1 "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	versioned "github.com/tektoncd/operator/pkg/client/clientset/versioned"
+	internalinterfaces "github.com/tektoncd/operator/pkg/client/informers/externalversions/internalinterfaces"
+	v1alpha1 "github.com/tektoncd/operator/pkg/client/listers/operator/v1alpha1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// TektonChainsInformer provides access to a shared informer and lister for
+// TektonChainses.
+type TektonChainsInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v1alpha1.TektonChainsLister
+}
+
+type tektonChainsInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+}
+
+// NewTektonChainsInformer constructs a new informer for TektonChains type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewTektonChainsInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredTektonChainsInformer(client, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredTektonChainsInformer constructs a new informer for TektonChains type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredTektonChainsInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.OperatorV1alpha1().TektonChainses().List(context.TODO(), options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.OperatorV1alpha1().TektonChainses().Watch(context.TODO(), options)
+			},
+		},
+		&operatorv1alpha1.TektonChains{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *tektonChainsInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredTektonChainsInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *tektonChainsInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&operatorv1alpha1.TektonChains{}, f.defaultInformer)
+}
+
+func (f *tektonChainsInformer) Lister() v1alpha1.TektonChainsLister {
+	return v1alpha1.NewTektonChainsLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/client/injection/client/client.go b/pkg/client/injection/client/client.go
index 1f667cbb8..4d03a651e 100644
--- a/pkg/client/injection/client/client.go
+++ b/pkg/client/injection/client/client.go
@@ -238,6 +238,133 @@ func (w *wrapOperatorV1alpha1TektonAddonImpl) Watch(ctx context.Context, opts v1
 	return nil, errors.New("NYI: Watch")
 }
 
+func (w *wrapOperatorV1alpha1) TektonChainses() typedoperatorv1alpha1.TektonChainsInterface {
+	return &wrapOperatorV1alpha1TektonChainsImpl{
+		dyn: w.dyn.Resource(schema.GroupVersionResource{
+			Group:    "operator.tekton.dev",
+			Version:  "v1alpha1",
+			Resource: "tektonchainses",
+		}),
+	}
+}
+
+type wrapOperatorV1alpha1TektonChainsImpl struct {
+	dyn dynamic.NamespaceableResourceInterface
+}
+
+var _ typedoperatorv1alpha1.TektonChainsInterface = (*wrapOperatorV1alpha1TektonChainsImpl)(nil)
+
+func (w *wrapOperatorV1alpha1TektonChainsImpl) Create(ctx context.Context, in *v1alpha1.TektonChains, opts v1.CreateOptions) (*v1alpha1.TektonChains, error) {
+	in.SetGroupVersionKind(schema.GroupVersionKind{
+		Group:   "operator.tekton.dev",
+		Version: "v1alpha1",
+		Kind:    "TektonChains",
+	})
+	uo := &unstructured.Unstructured{}
+	if err := convert(in, uo); err != nil {
+		return nil, err
+	}
+	uo, err := w.dyn.Create(ctx, uo, opts)
+	if err != nil {
+		return nil, err
+	}
+	out := &v1alpha1.TektonChains{}
+	if err := convert(uo, out); err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (w *wrapOperatorV1alpha1TektonChainsImpl) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	return w.dyn.Delete(ctx, name, opts)
+}
+
+func (w *wrapOperatorV1alpha1TektonChainsImpl) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	return w.dyn.DeleteCollection(ctx, opts, listOpts)
+}
+
+func (w *wrapOperatorV1alpha1TektonChainsImpl) Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.TektonChains, error) {
+	uo, err := w.dyn.Get(ctx, name, opts)
+	if err != nil {
+		return nil, err
+	}
+	out := &v1alpha1.TektonChains{}
+	if err := convert(uo, out); err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (w *wrapOperatorV1alpha1TektonChainsImpl) List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.TektonChainsList, error) {
+	uo, err := w.dyn.List(ctx, opts)
+	if err != nil {
+		return nil, err
+	}
+	out := &v1alpha1.TektonChainsList{}
+	if err := convert(uo, out); err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (w *wrapOperatorV1alpha1TektonChainsImpl) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.TektonChains, err error) {
+	uo, err := w.dyn.Patch(ctx, name, pt, data, opts)
+	if err != nil {
+		return nil, err
+	}
+	out := &v1alpha1.TektonChains{}
+	if err := convert(uo, out); err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (w *wrapOperatorV1alpha1TektonChainsImpl) Update(ctx context.Context, in *v1alpha1.TektonChains, opts v1.UpdateOptions) (*v1alpha1.TektonChains, error) {
+	in.SetGroupVersionKind(schema.GroupVersionKind{
+		Group:   "operator.tekton.dev",
+		Version: "v1alpha1",
+		Kind:    "TektonChains",
+	})
+	uo := &unstructured.Unstructured{}
+	if err := convert(in, uo); err != nil {
+		return nil, err
+	}
+	uo, err := w.dyn.Update(ctx, uo, opts)
+	if err != nil {
+		return nil, err
+	}
+	out := &v1alpha1.TektonChains{}
+	if err := convert(uo, out); err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (w *wrapOperatorV1alpha1TektonChainsImpl) UpdateStatus(ctx context.Context, in *v1alpha1.TektonChains, opts v1.UpdateOptions) (*v1alpha1.TektonChains, error) {
+	in.SetGroupVersionKind(schema.GroupVersionKind{
+		Group:   "operator.tekton.dev",
+		Version: "v1alpha1",
+		Kind:    "TektonChains",
+	})
+	uo := &unstructured.Unstructured{}
+	if err := convert(in, uo); err != nil {
+		return nil, err
+	}
+	uo, err := w.dyn.UpdateStatus(ctx, uo, opts)
+	if err != nil {
+		return nil, err
+	}
+	out := &v1alpha1.TektonChains{}
+	if err := convert(uo, out); err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (w *wrapOperatorV1alpha1TektonChainsImpl) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return nil, errors.New("NYI: Watch")
+}
+
 func (w *wrapOperatorV1alpha1) TektonConfigs() typedoperatorv1alpha1.TektonConfigInterface {
 	return &wrapOperatorV1alpha1TektonConfigImpl{
 		dyn: w.dyn.Resource(schema.GroupVersionResource{
diff --git a/pkg/client/injection/informers/operator/v1alpha1/tektonchains/fake/fake.go b/pkg/client/injection/informers/operator/v1alpha1/tektonchains/fake/fake.go
new file mode 100644
index 000000000..f702a517f
--- /dev/null
+++ b/pkg/client/injection/informers/operator/v1alpha1/tektonchains/fake/fake.go
@@ -0,0 +1,40 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	context "context"
+
+	fake "github.com/tektoncd/operator/pkg/client/injection/informers/factory/fake"
+	tektonchains "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektonchains"
+	controller "knative.dev/pkg/controller"
+	injection "knative.dev/pkg/injection"
+)
+
+var Get = tektonchains.Get
+
+func init() {
+	injection.Fake.RegisterInformer(withInformer)
+}
+
+func withInformer(ctx context.Context) (context.Context, controller.Informer) {
+	f := fake.Get(ctx)
+	inf := f.Operator().V1alpha1().TektonChainses()
+	return context.WithValue(ctx, tektonchains.Key{}, inf), inf.Informer()
+}
diff --git a/pkg/client/injection/informers/operator/v1alpha1/tektonchains/filtered/fake/fake.go b/pkg/client/injection/informers/operator/v1alpha1/tektonchains/filtered/fake/fake.go
new file mode 100644
index 000000000..faea7034e
--- /dev/null
+++ b/pkg/client/injection/informers/operator/v1alpha1/tektonchains/filtered/fake/fake.go
@@ -0,0 +1,52 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	context "context"
+
+	factoryfiltered "github.com/tektoncd/operator/pkg/client/injection/informers/factory/filtered"
+	filtered "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektonchains/filtered"
+	controller "knative.dev/pkg/controller"
+	injection "knative.dev/pkg/injection"
+	logging "knative.dev/pkg/logging"
+)
+
+var Get = filtered.Get
+
+func init() {
+	injection.Fake.RegisterFilteredInformers(withInformer)
+}
+
+func withInformer(ctx context.Context) (context.Context, []controller.Informer) {
+	untyped := ctx.Value(factoryfiltered.LabelKey{})
+	if untyped == nil {
+		logging.FromContext(ctx).Panic(
+			"Unable to fetch labelkey from context.")
+	}
+	labelSelectors := untyped.([]string)
+	infs := []controller.Informer{}
+	for _, selector := range labelSelectors {
+		f := factoryfiltered.Get(ctx, selector)
+		inf := f.Operator().V1alpha1().TektonChainses()
+		ctx = context.WithValue(ctx, filtered.Key{Selector: selector}, inf)
+		infs = append(infs, inf.Informer())
+	}
+	return ctx, infs
+}
diff --git a/pkg/client/injection/informers/operator/v1alpha1/tektonchains/filtered/tektonchains.go b/pkg/client/injection/informers/operator/v1alpha1/tektonchains/filtered/tektonchains.go
new file mode 100644
index 000000000..035830de0
--- /dev/null
+++ b/pkg/client/injection/informers/operator/v1alpha1/tektonchains/filtered/tektonchains.go
@@ -0,0 +1,130 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package filtered
+
+import (
+	context "context"
+
+	apisoperatorv1alpha1 "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	versioned "github.com/tektoncd/operator/pkg/client/clientset/versioned"
+	v1alpha1 "github.com/tektoncd/operator/pkg/client/informers/externalversions/operator/v1alpha1"
+	client "github.com/tektoncd/operator/pkg/client/injection/client"
+	filtered "github.com/tektoncd/operator/pkg/client/injection/informers/factory/filtered"
+	operatorv1alpha1 "github.com/tektoncd/operator/pkg/client/listers/operator/v1alpha1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	cache "k8s.io/client-go/tools/cache"
+	controller "knative.dev/pkg/controller"
+	injection "knative.dev/pkg/injection"
+	logging "knative.dev/pkg/logging"
+)
+
+func init() {
+	injection.Default.RegisterFilteredInformers(withInformer)
+	injection.Dynamic.RegisterDynamicInformer(withDynamicInformer)
+}
+
+// Key is used for associating the Informer inside the context.Context.
+type Key struct {
+	Selector string
+}
+
+func withInformer(ctx context.Context) (context.Context, []controller.Informer) {
+	untyped := ctx.Value(filtered.LabelKey{})
+	if untyped == nil {
+		logging.FromContext(ctx).Panic(
+			"Unable to fetch labelkey from context.")
+	}
+	labelSelectors := untyped.([]string)
+	infs := []controller.Informer{}
+	for _, selector := range labelSelectors {
+		f := filtered.Get(ctx, selector)
+		inf := f.Operator().V1alpha1().TektonChainses()
+		ctx = context.WithValue(ctx, Key{Selector: selector}, inf)
+		infs = append(infs, inf.Informer())
+	}
+	return ctx, infs
+}
+
+func withDynamicInformer(ctx context.Context) context.Context {
+	untyped := ctx.Value(filtered.LabelKey{})
+	if untyped == nil {
+		logging.FromContext(ctx).Panic(
+			"Unable to fetch labelkey from context.")
+	}
+	labelSelectors := untyped.([]string)
+	for _, selector := range labelSelectors {
+		inf := &wrapper{client: client.Get(ctx), selector: selector}
+		ctx = context.WithValue(ctx, Key{Selector: selector}, inf)
+	}
+	return ctx
+}
+
+// Get extracts the typed informer from the context.
+func Get(ctx context.Context, selector string) v1alpha1.TektonChainsInformer {
+	untyped := ctx.Value(Key{Selector: selector})
+	if untyped == nil {
+		logging.FromContext(ctx).Panicf(
+			"Unable to fetch github.com/tektoncd/operator/pkg/client/informers/externalversions/operator/v1alpha1.TektonChainsInformer with selector %s from context.", selector)
+	}
+	return untyped.(v1alpha1.TektonChainsInformer)
+}
+
+type wrapper struct {
+	client versioned.Interface
+
+	selector string
+}
+
+var _ v1alpha1.TektonChainsInformer = (*wrapper)(nil)
+var _ operatorv1alpha1.TektonChainsLister = (*wrapper)(nil)
+
+func (w *wrapper) Informer() cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(nil, &apisoperatorv1alpha1.TektonChains{}, 0, nil)
+}
+
+func (w *wrapper) Lister() operatorv1alpha1.TektonChainsLister {
+	return w
+}
+
+func (w *wrapper) List(selector labels.Selector) (ret []*apisoperatorv1alpha1.TektonChains, err error) {
+	reqs, err := labels.ParseToRequirements(w.selector)
+	if err != nil {
+		return nil, err
+	}
+	selector = selector.Add(reqs...)
+	lo, err := w.client.OperatorV1alpha1().TektonChainses().List(context.TODO(), v1.ListOptions{
+		LabelSelector: selector.String(),
+		// TODO(mattmoor): Incorporate resourceVersion bounds based on staleness criteria.
+	})
+	if err != nil {
+		return nil, err
+	}
+	for idx := range lo.Items {
+		ret = append(ret, &lo.Items[idx])
+	}
+	return ret, nil
+}
+
+func (w *wrapper) Get(name string) (*apisoperatorv1alpha1.TektonChains, error) {
+	// TODO(mattmoor): Check that the fetched object matches the selector.
+	return w.client.OperatorV1alpha1().TektonChainses().Get(context.TODO(), name, v1.GetOptions{
+		// TODO(mattmoor): Incorporate resourceVersion bounds based on staleness criteria.
+	})
+}
diff --git a/pkg/client/injection/informers/operator/v1alpha1/tektonchains/tektonchains.go b/pkg/client/injection/informers/operator/v1alpha1/tektonchains/tektonchains.go
new file mode 100644
index 000000000..0c0ab53ba
--- /dev/null
+++ b/pkg/client/injection/informers/operator/v1alpha1/tektonchains/tektonchains.go
@@ -0,0 +1,110 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package tektonchains
+
+import (
+	context "context"
+
+	apisoperatorv1alpha1 "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	versioned "github.com/tektoncd/operator/pkg/client/clientset/versioned"
+	v1alpha1 "github.com/tektoncd/operator/pkg/client/informers/externalversions/operator/v1alpha1"
+	client "github.com/tektoncd/operator/pkg/client/injection/client"
+	factory "github.com/tektoncd/operator/pkg/client/injection/informers/factory"
+	operatorv1alpha1 "github.com/tektoncd/operator/pkg/client/listers/operator/v1alpha1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	cache "k8s.io/client-go/tools/cache"
+	controller "knative.dev/pkg/controller"
+	injection "knative.dev/pkg/injection"
+	logging "knative.dev/pkg/logging"
+)
+
+func init() {
+	injection.Default.RegisterInformer(withInformer)
+	injection.Dynamic.RegisterDynamicInformer(withDynamicInformer)
+}
+
+// Key is used for associating the Informer inside the context.Context.
+type Key struct{}
+
+func withInformer(ctx context.Context) (context.Context, controller.Informer) {
+	f := factory.Get(ctx)
+	inf := f.Operator().V1alpha1().TektonChainses()
+	return context.WithValue(ctx, Key{}, inf), inf.Informer()
+}
+
+func withDynamicInformer(ctx context.Context) context.Context {
+	inf := &wrapper{client: client.Get(ctx), resourceVersion: injection.GetResourceVersion(ctx)}
+	return context.WithValue(ctx, Key{}, inf)
+}
+
+// Get extracts the typed informer from the context.
+func Get(ctx context.Context) v1alpha1.TektonChainsInformer {
+	untyped := ctx.Value(Key{})
+	if untyped == nil {
+		logging.FromContext(ctx).Panic(
+			"Unable to fetch github.com/tektoncd/operator/pkg/client/informers/externalversions/operator/v1alpha1.TektonChainsInformer from context.")
+	}
+	return untyped.(v1alpha1.TektonChainsInformer)
+}
+
+type wrapper struct {
+	client versioned.Interface
+
+	resourceVersion string
+}
+
+var _ v1alpha1.TektonChainsInformer = (*wrapper)(nil)
+var _ operatorv1alpha1.TektonChainsLister = (*wrapper)(nil)
+
+func (w *wrapper) Informer() cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(nil, &apisoperatorv1alpha1.TektonChains{}, 0, nil)
+}
+
+func (w *wrapper) Lister() operatorv1alpha1.TektonChainsLister {
+	return w
+}
+
+// SetResourceVersion allows consumers to adjust the minimum resourceVersion
+// used by the underlying client.  It is not accessible via the standard
+// lister interface, but can be accessed through a user-defined interface and
+// an implementation check e.g. rvs, ok := foo.(ResourceVersionSetter)
+func (w *wrapper) SetResourceVersion(resourceVersion string) {
+	w.resourceVersion = resourceVersion
+}
+
+func (w *wrapper) List(selector labels.Selector) (ret []*apisoperatorv1alpha1.TektonChains, err error) {
+	lo, err := w.client.OperatorV1alpha1().TektonChainses().List(context.TODO(), v1.ListOptions{
+		LabelSelector:   selector.String(),
+		ResourceVersion: w.resourceVersion,
+	})
+	if err != nil {
+		return nil, err
+	}
+	for idx := range lo.Items {
+		ret = append(ret, &lo.Items[idx])
+	}
+	return ret, nil
+}
+
+func (w *wrapper) Get(name string) (*apisoperatorv1alpha1.TektonChains, error) {
+	return w.client.OperatorV1alpha1().TektonChainses().Get(context.TODO(), name, v1.GetOptions{
+		ResourceVersion: w.resourceVersion,
+	})
+}
diff --git a/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains/controller.go b/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains/controller.go
new file mode 100644
index 000000000..76cf35f23
--- /dev/null
+++ b/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains/controller.go
@@ -0,0 +1,162 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package tektonchains
+
+import (
+	context "context"
+	fmt "fmt"
+	reflect "reflect"
+	strings "strings"
+
+	versionedscheme "github.com/tektoncd/operator/pkg/client/clientset/versioned/scheme"
+	client "github.com/tektoncd/operator/pkg/client/injection/client"
+	tektonchains "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektonchains"
+	zap "go.uber.org/zap"
+	corev1 "k8s.io/api/core/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	scheme "k8s.io/client-go/kubernetes/scheme"
+	v1 "k8s.io/client-go/kubernetes/typed/core/v1"
+	record "k8s.io/client-go/tools/record"
+	kubeclient "knative.dev/pkg/client/injection/kube/client"
+	controller "knative.dev/pkg/controller"
+	logging "knative.dev/pkg/logging"
+	logkey "knative.dev/pkg/logging/logkey"
+	reconciler "knative.dev/pkg/reconciler"
+)
+
+const (
+	defaultControllerAgentName = "tektonchains-controller"
+	defaultFinalizerName       = "tektonchainses.operator.tekton.dev"
+)
+
+// NewImpl returns a controller.Impl that handles queuing and feeding work from
+// the queue through an implementation of controller.Reconciler, delegating to
+// the provided Interface and optional Finalizer methods. OptionsFn is used to return
+// controller.ControllerOptions to be used by the internal reconciler.
+func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl {
+	logger := logging.FromContext(ctx)
+
+	// Check the options function input. It should be 0 or 1.
+	if len(optionsFns) > 1 {
+		logger.Fatal("Up to one options function is supported, found: ", len(optionsFns))
+	}
+
+	tektonchainsInformer := tektonchains.Get(ctx)
+
+	lister := tektonchainsInformer.Lister()
+
+	var promoteFilterFunc func(obj interface{}) bool
+
+	rec := &reconcilerImpl{
+		LeaderAwareFuncs: reconciler.LeaderAwareFuncs{
+			PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error {
+				all, err := lister.List(labels.Everything())
+				if err != nil {
+					return err
+				}
+				for _, elt := range all {
+					if promoteFilterFunc != nil {
+						if ok := promoteFilterFunc(elt); !ok {
+							continue
+						}
+					}
+					enq(bkt, types.NamespacedName{
+						Namespace: elt.GetNamespace(),
+						Name:      elt.GetName(),
+					})
+				}
+				return nil
+			},
+		},
+		Client:        client.Get(ctx),
+		Lister:        lister,
+		reconciler:    r,
+		finalizerName: defaultFinalizerName,
+	}
+
+	ctrType := reflect.TypeOf(r).Elem()
+	ctrTypeName := fmt.Sprintf("%s.%s", ctrType.PkgPath(), ctrType.Name())
+	ctrTypeName = strings.ReplaceAll(ctrTypeName, "/", ".")
+
+	logger = logger.With(
+		zap.String(logkey.ControllerType, ctrTypeName),
+		zap.String(logkey.Kind, "operator.tekton.dev.TektonChains"),
+	)
+
+	impl := controller.NewContext(ctx, rec, controller.ControllerOptions{WorkQueueName: ctrTypeName, Logger: logger})
+	agentName := defaultControllerAgentName
+
+	// Pass impl to the options. Save any optional results.
+	for _, fn := range optionsFns {
+		opts := fn(impl)
+		if opts.ConfigStore != nil {
+			rec.configStore = opts.ConfigStore
+		}
+		if opts.FinalizerName != "" {
+			rec.finalizerName = opts.FinalizerName
+		}
+		if opts.AgentName != "" {
+			agentName = opts.AgentName
+		}
+		if opts.SkipStatusUpdates {
+			rec.skipStatusUpdates = true
+		}
+		if opts.DemoteFunc != nil {
+			rec.DemoteFunc = opts.DemoteFunc
+		}
+		if opts.PromoteFilterFunc != nil {
+			promoteFilterFunc = opts.PromoteFilterFunc
+		}
+	}
+
+	rec.Recorder = createRecorder(ctx, agentName)
+
+	return impl
+}
+
+func createRecorder(ctx context.Context, agentName string) record.EventRecorder {
+	logger := logging.FromContext(ctx)
+
+	recorder := controller.GetEventRecorder(ctx)
+	if recorder == nil {
+		// Create event broadcaster
+		logger.Debug("Creating event broadcaster")
+		eventBroadcaster := record.NewBroadcaster()
+		watches := []watch.Interface{
+			eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof),
+			eventBroadcaster.StartRecordingToSink(
+				&v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}),
+		}
+		recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName})
+		go func() {
+			<-ctx.Done()
+			for _, w := range watches {
+				w.Stop()
+			}
+		}()
+	}
+
+	return recorder
+}
+
+func init() {
+	versionedscheme.AddToScheme(scheme.Scheme)
+}
diff --git a/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains/reconciler.go b/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains/reconciler.go
new file mode 100644
index 000000000..4a3977a0b
--- /dev/null
+++ b/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains/reconciler.go
@@ -0,0 +1,442 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package tektonchains
+
+import (
+	context "context"
+	json "encoding/json"
+	fmt "fmt"
+
+	v1alpha1 "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	versioned "github.com/tektoncd/operator/pkg/client/clientset/versioned"
+	operatorv1alpha1 "github.com/tektoncd/operator/pkg/client/listers/operator/v1alpha1"
+	zap "go.uber.org/zap"
+	v1 "k8s.io/api/core/v1"
+	equality "k8s.io/apimachinery/pkg/api/equality"
+	errors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	types "k8s.io/apimachinery/pkg/types"
+	sets "k8s.io/apimachinery/pkg/util/sets"
+	record "k8s.io/client-go/tools/record"
+	controller "knative.dev/pkg/controller"
+	kmp "knative.dev/pkg/kmp"
+	logging "knative.dev/pkg/logging"
+	reconciler "knative.dev/pkg/reconciler"
+)
+
+// Interface defines the strongly typed interfaces to be implemented by a
+// controller reconciling v1alpha1.TektonChains.
+type Interface interface {
+	// ReconcileKind implements custom logic to reconcile v1alpha1.TektonChains. Any changes
+	// to the objects .Status or .Finalizers will be propagated to the stored
+	// object. It is recommended that implementors do not call any update calls
+	// for the Kind inside of ReconcileKind, it is the responsibility of the calling
+	// controller to propagate those properties. The resource passed to ReconcileKind
+	// will always have an empty deletion timestamp.
+	ReconcileKind(ctx context.Context, o *v1alpha1.TektonChains) reconciler.Event
+}
+
+// Finalizer defines the strongly typed interfaces to be implemented by a
+// controller finalizing v1alpha1.TektonChains.
+type Finalizer interface {
+	// FinalizeKind implements custom logic to finalize v1alpha1.TektonChains. Any changes
+	// to the objects .Status or .Finalizers will be ignored. Returning a nil or
+	// Normal type reconciler.Event will allow the finalizer to be deleted on
+	// the resource. The resource passed to FinalizeKind will always have a set
+	// deletion timestamp.
+	FinalizeKind(ctx context.Context, o *v1alpha1.TektonChains) reconciler.Event
+}
+
+// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a
+// controller reconciling v1alpha1.TektonChains if they want to process resources for which
+// they are not the leader.
+type ReadOnlyInterface interface {
+	// ObserveKind implements logic to observe v1alpha1.TektonChains.
+	// This method should not write to the API.
+	ObserveKind(ctx context.Context, o *v1alpha1.TektonChains) reconciler.Event
+}
+
+type doReconcile func(ctx context.Context, o *v1alpha1.TektonChains) reconciler.Event
+
+// reconcilerImpl implements controller.Reconciler for v1alpha1.TektonChains resources.
+type reconcilerImpl struct {
+	// LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware.
+	reconciler.LeaderAwareFuncs
+
+	// Client is used to write back status updates.
+	Client versioned.Interface
+
+	// Listers index properties about resources.
+	Lister operatorv1alpha1.TektonChainsLister
+
+	// Recorder is an event recorder for recording Event resources to the
+	// Kubernetes API.
+	Recorder record.EventRecorder
+
+	// configStore allows for decorating a context with config maps.
+	// +optional
+	configStore reconciler.ConfigStore
+
+	// reconciler is the implementation of the business logic of the resource.
+	reconciler Interface
+
+	// finalizerName is the name of the finalizer to reconcile.
+	finalizerName string
+
+	// skipStatusUpdates configures whether or not this reconciler automatically updates
+	// the status of the reconciled resource.
+	skipStatusUpdates bool
+}
+
+// Check that our Reconciler implements controller.Reconciler.
+var _ controller.Reconciler = (*reconcilerImpl)(nil)
+
+// Check that our generated Reconciler is always LeaderAware.
+var _ reconciler.LeaderAware = (*reconcilerImpl)(nil)
+
+func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister operatorv1alpha1.TektonChainsLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler {
+	// Check the options function input. It should be 0 or 1.
+	if len(options) > 1 {
+		logger.Fatal("Up to one options struct is supported, found: ", len(options))
+	}
+
+	// Fail fast when users inadvertently implement the other LeaderAware interface.
+	// For the typed reconcilers, Promote shouldn't take any arguments.
+	if _, ok := r.(reconciler.LeaderAware); ok {
+		logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r)
+	}
+
+	rec := &reconcilerImpl{
+		LeaderAwareFuncs: reconciler.LeaderAwareFuncs{
+			PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error {
+				all, err := lister.List(labels.Everything())
+				if err != nil {
+					return err
+				}
+				for _, elt := range all {
+					// TODO: Consider letting users specify a filter in options.
+					enq(bkt, types.NamespacedName{
+						Namespace: elt.GetNamespace(),
+						Name:      elt.GetName(),
+					})
+				}
+				return nil
+			},
+		},
+		Client:        client,
+		Lister:        lister,
+		Recorder:      recorder,
+		reconciler:    r,
+		finalizerName: defaultFinalizerName,
+	}
+
+	for _, opts := range options {
+		if opts.ConfigStore != nil {
+			rec.configStore = opts.ConfigStore
+		}
+		if opts.FinalizerName != "" {
+			rec.finalizerName = opts.FinalizerName
+		}
+		if opts.SkipStatusUpdates {
+			rec.skipStatusUpdates = true
+		}
+		if opts.DemoteFunc != nil {
+			rec.DemoteFunc = opts.DemoteFunc
+		}
+	}
+
+	return rec
+}
+
+// Reconcile implements controller.Reconciler
+func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
+	logger := logging.FromContext(ctx)
+
+	// Initialize the reconciler state. This will convert the namespace/name
+	// string into a distinct namespace and name, determine if this instance of
+	// the reconciler is the leader, and any additional interfaces implemented
+	// by the reconciler. Returns an error is the resource key is invalid.
+	s, err := newState(key, r)
+	if err != nil {
+		logger.Error("Invalid resource key: ", key)
+		return nil
+	}
+
+	// If we are not the leader, and we don't implement either ReadOnly
+	// observer interfaces, then take a fast-path out.
+	if s.isNotLeaderNorObserver() {
+		return controller.NewSkipKey(key)
+	}
+
+	// If configStore is set, attach the frozen configuration to the context.
+	if r.configStore != nil {
+		ctx = r.configStore.ToContext(ctx)
+	}
+
+	// Add the recorder to context.
+	ctx = controller.WithEventRecorder(ctx, r.Recorder)
+
+	// Get the resource with this namespace/name.
+
+	getter := r.Lister
+
+	original, err := getter.Get(s.name)
+
+	if errors.IsNotFound(err) {
+		// The resource may no longer exist, in which case we stop processing and call
+		// the ObserveDeletion handler if appropriate.
+		logger.Debugf("Resource %q no longer exists", key)
+		if del, ok := r.reconciler.(reconciler.OnDeletionInterface); ok {
+			return del.ObserveDeletion(ctx, types.NamespacedName{
+				Namespace: s.namespace,
+				Name:      s.name,
+			})
+		}
+		return nil
+	} else if err != nil {
+		return err
+	}
+
+	// Don't modify the informers copy.
+	resource := original.DeepCopy()
+
+	var reconcileEvent reconciler.Event
+
+	name, do := s.reconcileMethodFor(resource)
+	// Append the target method to the logger.
+	logger = logger.With(zap.String("targetMethod", name))
+	switch name {
+	case reconciler.DoReconcileKind:
+		// Set and update the finalizer on resource if r.reconciler
+		// implements Finalizer.
+		if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil {
+			return fmt.Errorf("failed to set finalizers: %w", err)
+		}
+
+		// Reconcile this copy of the resource and then write back any status
+		// updates regardless of whether the reconciliation errored out.
+		reconcileEvent = do(ctx, resource)
+
+	case reconciler.DoFinalizeKind:
+		// For finalizing reconcilers, if this resource being marked for deletion
+		// and reconciled cleanly (nil or normal event), remove the finalizer.
+		reconcileEvent = do(ctx, resource)
+
+		if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil {
+			return fmt.Errorf("failed to clear finalizers: %w", err)
+		}
+
+	case reconciler.DoObserveKind:
+		// Observe any changes to this resource, since we are not the leader.
+		reconcileEvent = do(ctx, resource)
+
+	}
+
+	// Synchronize the status.
+	switch {
+	case r.skipStatusUpdates:
+		// This reconciler implementation is configured to skip resource updates.
+		// This may mean this reconciler does not observe spec, but reconciles external changes.
+	case equality.Semantic.DeepEqual(original.Status, resource.Status):
+		// If we didn't change anything then don't call updateStatus.
+		// This is important because the copy we loaded from the injectionInformer's
+		// cache may be stale and we don't want to overwrite a prior update
+		// to status with this stale state.
+	case !s.isLeader:
+		// High-availability reconcilers may have many replicas watching the resource, but only
+		// the elected leader is expected to write modifications.
+		logger.Warn("Saw status changes when we aren't the leader!")
+	default:
+		if err = r.updateStatus(ctx, original, resource); err != nil {
+			logger.Warnw("Failed to update resource status", zap.Error(err))
+			r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed",
+				"Failed to update status for %q: %v", resource.Name, err)
+			return err
+		}
+	}
+
+	// Report the reconciler event, if any.
+	if reconcileEvent != nil {
+		var event *reconciler.ReconcilerEvent
+		if reconciler.EventAs(reconcileEvent, &event) {
+			logger.Infow("Returned an event", zap.Any("event", reconcileEvent))
+			r.Recorder.Event(resource, event.EventType, event.Reason, event.Error())
+
+			// the event was wrapped inside an error, consider the reconciliation as failed
+			if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent {
+				return reconcileEvent
+			}
+			return nil
+		}
+
+		if controller.IsSkipKey(reconcileEvent) {
+			// This is a wrapped error, don't emit an event.
+		} else if ok, _ := controller.IsRequeueKey(reconcileEvent); ok {
+			// This is a wrapped error, don't emit an event.
+		} else {
+			logger.Errorw("Returned an error", zap.Error(reconcileEvent))
+			r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error())
+		}
+		return reconcileEvent
+	}
+
+	return nil
+}
+
+func (r *reconcilerImpl) updateStatus(ctx context.Context, existing *v1alpha1.TektonChains, desired *v1alpha1.TektonChains) error {
+	existing = existing.DeepCopy()
+	return reconciler.RetryUpdateConflicts(func(attempts int) (err error) {
+		// The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API.
+		if attempts > 0 {
+
+			getter := r.Client.OperatorV1alpha1().TektonChainses()
+
+			existing, err = getter.Get(ctx, desired.Name, metav1.GetOptions{})
+			if err != nil {
+				return err
+			}
+		}
+
+		// If there's nothing to update, just return.
+		if equality.Semantic.DeepEqual(existing.Status, desired.Status) {
+			return nil
+		}
+
+		if diff, err := kmp.SafeDiff(existing.Status, desired.Status); err == nil && diff != "" {
+			logging.FromContext(ctx).Debug("Updating status with: ", diff)
+		}
+
+		existing.Status = desired.Status
+
+		updater := r.Client.OperatorV1alpha1().TektonChainses()
+
+		_, err = updater.UpdateStatus(ctx, existing, metav1.UpdateOptions{})
+		return err
+	})
+}
+
+// updateFinalizersFiltered will update the Finalizers of the resource.
+// TODO: this method could be generic and sync all finalizers. For now it only
+// updates defaultFinalizerName or its override.
+func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.TektonChains) (*v1alpha1.TektonChains, error) {
+
+	getter := r.Lister
+
+	actual, err := getter.Get(resource.Name)
+	if err != nil {
+		return resource, err
+	}
+
+	// Don't modify the informers copy.
+	existing := actual.DeepCopy()
+
+	var finalizers []string
+
+	// If there's nothing to update, just return.
+	existingFinalizers := sets.NewString(existing.Finalizers...)
+	desiredFinalizers := sets.NewString(resource.Finalizers...)
+
+	if desiredFinalizers.Has(r.finalizerName) {
+		if existingFinalizers.Has(r.finalizerName) {
+			// Nothing to do.
+			return resource, nil
+		}
+		// Add the finalizer.
+		finalizers = append(existing.Finalizers, r.finalizerName)
+	} else {
+		if !existingFinalizers.Has(r.finalizerName) {
+			// Nothing to do.
+			return resource, nil
+		}
+		// Remove the finalizer.
+		existingFinalizers.Delete(r.finalizerName)
+		finalizers = existingFinalizers.List()
+	}
+
+	mergePatch := map[string]interface{}{
+		"metadata": map[string]interface{}{
+			"finalizers":      finalizers,
+			"resourceVersion": existing.ResourceVersion,
+		},
+	}
+
+	patch, err := json.Marshal(mergePatch)
+	if err != nil {
+		return resource, err
+	}
+
+	patcher := r.Client.OperatorV1alpha1().TektonChainses()
+
+	resourceName := resource.Name
+	updated, err := patcher.Patch(ctx, resourceName, types.MergePatchType, patch, metav1.PatchOptions{})
+	if err != nil {
+		r.Recorder.Eventf(existing, v1.EventTypeWarning, "FinalizerUpdateFailed",
+			"Failed to update finalizers for %q: %v", resourceName, err)
+	} else {
+		r.Recorder.Eventf(updated, v1.EventTypeNormal, "FinalizerUpdate",
+			"Updated %q finalizers", resource.GetName())
+	}
+	return updated, err
+}
+
+func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.TektonChains) (*v1alpha1.TektonChains, error) {
+	if _, ok := r.reconciler.(Finalizer); !ok {
+		return resource, nil
+	}
+
+	finalizers := sets.NewString(resource.Finalizers...)
+
+	// If this resource is not being deleted, mark the finalizer.
+	if resource.GetDeletionTimestamp().IsZero() {
+		finalizers.Insert(r.finalizerName)
+	}
+
+	resource.Finalizers = finalizers.List()
+
+	// Synchronize the finalizers filtered by r.finalizerName.
+	return r.updateFinalizersFiltered(ctx, resource)
+}
+
+func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.TektonChains, reconcileEvent reconciler.Event) (*v1alpha1.TektonChains, error) {
+	if _, ok := r.reconciler.(Finalizer); !ok {
+		return resource, nil
+	}
+	if resource.GetDeletionTimestamp().IsZero() {
+		return resource, nil
+	}
+
+	finalizers := sets.NewString(resource.Finalizers...)
+
+	if reconcileEvent != nil {
+		var event *reconciler.ReconcilerEvent
+		if reconciler.EventAs(reconcileEvent, &event) {
+			if event.EventType == v1.EventTypeNormal {
+				finalizers.Delete(r.finalizerName)
+			}
+		}
+	} else {
+		finalizers.Delete(r.finalizerName)
+	}
+
+	resource.Finalizers = finalizers.List()
+
+	// Synchronize the finalizers filtered by r.finalizerName.
+	return r.updateFinalizersFiltered(ctx, resource)
+}
diff --git a/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains/state.go b/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains/state.go
new file mode 100644
index 000000000..cdfe58f49
--- /dev/null
+++ b/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains/state.go
@@ -0,0 +1,97 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package tektonchains
+
+import (
+	fmt "fmt"
+
+	v1alpha1 "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	types "k8s.io/apimachinery/pkg/types"
+	cache "k8s.io/client-go/tools/cache"
+	reconciler "knative.dev/pkg/reconciler"
+)
+
+// state is used to track the state of a reconciler in a single run.
+type state struct {
+	// key is the original reconciliation key from the queue.
+	key string
+	// namespace is the namespace split from the reconciliation key.
+	namespace string
+	// name is the name split from the reconciliation key.
+	name string
+	// reconciler is the reconciler.
+	reconciler Interface
+	// roi is the read only interface cast of the reconciler.
+	roi ReadOnlyInterface
+	// isROI (Read Only Interface) the reconciler only observes reconciliation.
+	isROI bool
+	// isLeader the instance of the reconciler is the elected leader.
+	isLeader bool
+}
+
+func newState(key string, r *reconcilerImpl) (*state, error) {
+	// Convert the namespace/name string into a distinct namespace and name.
+	namespace, name, err := cache.SplitMetaNamespaceKey(key)
+	if err != nil {
+		return nil, fmt.Errorf("invalid resource key: %s", key)
+	}
+
+	roi, isROI := r.reconciler.(ReadOnlyInterface)
+
+	isLeader := r.IsLeaderFor(types.NamespacedName{
+		Namespace: namespace,
+		Name:      name,
+	})
+
+	return &state{
+		key:        key,
+		namespace:  namespace,
+		name:       name,
+		reconciler: r.reconciler,
+		roi:        roi,
+		isROI:      isROI,
+		isLeader:   isLeader,
+	}, nil
+}
+
+// isNotLeaderNorObserver checks to see if this reconciler with the current
+// state is enabled to do any work or not.
+// isNotLeaderNorObserver returns true when there is no work possible for the
+// reconciler.
+func (s *state) isNotLeaderNorObserver() bool {
+	if !s.isLeader && !s.isROI {
+		// If we are not the leader, and we don't implement the ReadOnly
+		// interface, then take a fast-path out.
+		return true
+	}
+	return false
+}
+
+func (s *state) reconcileMethodFor(o *v1alpha1.TektonChains) (string, doReconcile) {
+	if o.GetDeletionTimestamp().IsZero() {
+		if s.isLeader {
+			return reconciler.DoReconcileKind, s.reconciler.ReconcileKind
+		} else if s.isROI {
+			return reconciler.DoObserveKind, s.roi.ObserveKind
+		}
+	} else if fin, ok := s.reconciler.(Finalizer); s.isLeader && ok {
+		return reconciler.DoFinalizeKind, fin.FinalizeKind
+	}
+	return "unknown", nil
+}
diff --git a/pkg/client/listers/operator/v1alpha1/expansion_generated.go b/pkg/client/listers/operator/v1alpha1/expansion_generated.go
index b46daa536..4d96ff707 100644
--- a/pkg/client/listers/operator/v1alpha1/expansion_generated.go
+++ b/pkg/client/listers/operator/v1alpha1/expansion_generated.go
@@ -22,6 +22,10 @@ package v1alpha1
 // TektonAddonLister.
 type TektonAddonListerExpansion interface{}
 
+// TektonChainsListerExpansion allows custom methods to be added to
+// TektonChainsLister.
+type TektonChainsListerExpansion interface{}
+
 // TektonConfigListerExpansion allows custom methods to be added to
 // TektonConfigLister.
 type TektonConfigListerExpansion interface{}
diff --git a/pkg/client/listers/operator/v1alpha1/tektonchains.go b/pkg/client/listers/operator/v1alpha1/tektonchains.go
new file mode 100644
index 000000000..86f1c3573
--- /dev/null
+++ b/pkg/client/listers/operator/v1alpha1/tektonchains.go
@@ -0,0 +1,68 @@
+/*
+Copyright 2020 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	v1alpha1 "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+)
+
+// TektonChainsLister helps list TektonChainses.
+// All objects returned here must be treated as read-only.
+type TektonChainsLister interface {
+	// List lists all TektonChainses in the indexer.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v1alpha1.TektonChains, err error)
+	// Get retrieves the TektonChains from the index for a given name.
+	// Objects returned here must be treated as read-only.
+	Get(name string) (*v1alpha1.TektonChains, error)
+	TektonChainsListerExpansion
+}
+
+// tektonChainsLister implements the TektonChainsLister interface.
+type tektonChainsLister struct {
+	indexer cache.Indexer
+}
+
+// NewTektonChainsLister returns a new TektonChainsLister.
+func NewTektonChainsLister(indexer cache.Indexer) TektonChainsLister {
+	return &tektonChainsLister{indexer: indexer}
+}
+
+// List lists all TektonChainses in the indexer.
+func (s *tektonChainsLister) List(selector labels.Selector) (ret []*v1alpha1.TektonChains, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v1alpha1.TektonChains))
+	})
+	return ret, err
+}
+
+// Get retrieves the TektonChains from the index for a given name.
+func (s *tektonChainsLister) Get(name string) (*v1alpha1.TektonChains, error) {
+	obj, exists, err := s.indexer.GetByKey(name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v1alpha1.Resource("tektonchains"), name)
+	}
+	return obj.(*v1alpha1.TektonChains), nil
+}
diff --git a/pkg/reconciler/common/common.go b/pkg/reconciler/common/common.go
index 60a8a1a36..d645165b1 100644
--- a/pkg/reconciler/common/common.go
+++ b/pkg/reconciler/common/common.go
@@ -62,6 +62,17 @@ func PipelineReady(informer informer.TektonPipelineInformer) (*v1alpha1.TektonPi
 	return ppln, nil
 }
 
+func PipelineTargetNamspace(informer informer.TektonPipelineInformer) (string, error) {
+	ppln, err := getPipelineRes(informer)
+	if err != nil {
+		if apierrors.IsNotFound(err) {
+			return "", nil
+		}
+		return "", err
+	}
+	return ppln.Spec.TargetNamespace, nil
+}
+
 func getPipelineRes(informer informer.TektonPipelineInformer) (*v1alpha1.TektonPipeline, error) {
 	res, err := informer.Lister().Get(v1alpha1.PipelineResourceName)
 	return res, err
diff --git a/pkg/reconciler/common/initcontroller.go b/pkg/reconciler/common/initcontroller.go
index 7eb8217c8..c97ba5f9b 100644
--- a/pkg/reconciler/common/initcontroller.go
+++ b/pkg/reconciler/common/initcontroller.go
@@ -31,6 +31,8 @@ import (
 	"knative.dev/pkg/logging"
 )
 
+const ReleaseVersionUnknown = "Unknown"
+
 type Controller struct {
 	Manifest         *mf.Manifest
 	Logger           *zap.SugaredLogger
@@ -75,7 +77,7 @@ func (ctrl Controller) InitController(ctx context.Context, opts PayloadOptions)
 	if err != nil {
 		if IsFetchVersionError(err) {
 			ctrl.Logger.Warnf("failed to read version information from ConfigMap %s", ctrl.VersionConfigMap, err)
-			releaseVersion = "Unknown"
+			releaseVersion = ReleaseVersionUnknown
 		} else {
 			ctrl.Logger.Fatalw("Error while reading ConfigMap", zap.Error(err))
 		}
@@ -106,6 +108,9 @@ func (ctrl Controller) fetchSourceManifests(ctx context.Context, opts PayloadOpt
 		var dashboard v1alpha1.TektonDashboard
 		dashboard.Spec.Readonly = false
 		return AppendTarget(ctx, ctrl.Manifest, &dashboard)
+	case strings.Contains(ctrl.VersionConfigMap, "chains"):
+		var chains v1alpha1.TektonChains
+		return AppendTarget(ctx, ctrl.Manifest, &chains)
 	}
 
 	return nil
diff --git a/pkg/reconciler/common/releases.go b/pkg/reconciler/common/releases.go
index 2152faacf..7e7dd1538 100644
--- a/pkg/reconciler/common/releases.go
+++ b/pkg/reconciler/common/releases.go
@@ -94,6 +94,8 @@ func ComponentDir(instance v1alpha1.TektonComponent) string {
 		return filepath.Join(koDataDir, "tekton-results")
 	case *v1alpha1.TektonHub:
 		return filepath.Join(koDataDir, "tekton-hub")
+	case *v1alpha1.TektonChains:
+		return filepath.Join(koDataDir, "tekton-chains")
 	}
 	return ""
 }
diff --git a/pkg/reconciler/common/transformers.go b/pkg/reconciler/common/transformers.go
index b62f645f6..b7bb2cfe1 100644
--- a/pkg/reconciler/common/transformers.go
+++ b/pkg/reconciler/common/transformers.go
@@ -40,6 +40,7 @@ const (
 	PipelinesImagePrefix          = "IMAGE_PIPELINES_"
 	TriggersImagePrefix           = "IMAGE_TRIGGERS_"
 	AddonsImagePrefix             = "IMAGE_ADDONS_"
+	ChainsImagePrefix             = "IMAGE_CHAINS_"
 
 	ArgPrefix   = "arg_"
 	ParamPrefix = "param_"
diff --git a/pkg/reconciler/kubernetes/tektonchains/controller.go b/pkg/reconciler/kubernetes/tektonchains/controller.go
new file mode 100644
index 000000000..f5a4453f2
--- /dev/null
+++ b/pkg/reconciler/kubernetes/tektonchains/controller.go
@@ -0,0 +1,90 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package tektonchains
+
+import (
+	"context"
+
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	operatorclient "github.com/tektoncd/operator/pkg/client/injection/client"
+	tektonChainsinformer "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektonchains"
+	tektonInstallerinformer "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektoninstallerset"
+	tektonPipelineinformer "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektonpipeline"
+	tektonChainsreconciler "github.com/tektoncd/operator/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
+	"k8s.io/client-go/tools/cache"
+	//kubeclient "knative.dev/pkg/client/injection/kube/client"
+	"knative.dev/pkg/configmap"
+	"knative.dev/pkg/controller"
+	"knative.dev/pkg/injection"
+	"knative.dev/pkg/logging"
+)
+
+// chains-info stores the version of Chains installed in the cluster
+const versionConfigMap = "chains-info"
+
+// NewController initializes the controller and is called by the generated code
+// Registers eventhandlers to enqueue events
+func NewController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
+	return NewExtendedController(common.NoExtension)(ctx, cmw)
+}
+
+// NewExtendedController returns a controller extended to a specific platform
+func NewExtendedController(generator common.ExtensionGenerator) injection.ControllerConstructor {
+	return func(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
+		logger := logging.FromContext(ctx)
+
+		ctrl := common.Controller{
+			Logger:           logger,
+			VersionConfigMap: versionConfigMap,
+		}
+
+		manifest, chainsVer := ctrl.InitController(ctx, common.PayloadOptions{})
+		if chainsVer == common.ReleaseVersionUnknown {
+			chainsVer = "devel"
+		}
+
+		operatorVer, err := common.OperatorVersion(ctx)
+		if err != nil {
+			logger.Fatal(err)
+		}
+
+		c := &Reconciler{
+			operatorClientSet: operatorclient.Get(ctx),
+			extension:         generator(ctx),
+			manifest:          manifest,
+			pipelineInformer:  tektonPipelineinformer.Get(ctx),
+			operatorVersion:   operatorVer,
+			chainsVersion:     chainsVer,
+		}
+		impl := tektonChainsreconciler.NewImpl(ctx, c)
+
+		// Add enqueue func in reconciler
+		c.enqueueAfter = impl.EnqueueAfter
+
+		logger.Info("Setting up event handlers for Tekton Chains")
+
+		tektonChainsinformer.Get(ctx).Informer().AddEventHandler(controller.HandleAll(impl.Enqueue))
+
+		tektonInstallerinformer.Get(ctx).Informer().AddEventHandler(cache.FilteringResourceEventHandler{
+			FilterFunc: controller.FilterController(&v1alpha1.TektonChains{}),
+			Handler:    controller.HandleAll(impl.EnqueueControllerOf),
+		})
+
+		return impl
+	}
+}
diff --git a/pkg/reconciler/kubernetes/tektonchains/tektonchains.go b/pkg/reconciler/kubernetes/tektonchains/tektonchains.go
new file mode 100644
index 000000000..420f85c6d
--- /dev/null
+++ b/pkg/reconciler/kubernetes/tektonchains/tektonchains.go
@@ -0,0 +1,415 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package tektonchains
+
+import (
+	"context"
+	"fmt"
+	"time"
+
+	mf "github.com/manifestival/manifestival"
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	clientset "github.com/tektoncd/operator/pkg/client/clientset/versioned"
+	pipelineinformer "github.com/tektoncd/operator/pkg/client/informers/externalversions/operator/v1alpha1"
+	tektonchainsreconciler "github.com/tektoncd/operator/pkg/client/injection/reconciler/operator/v1alpha1/tektonchains"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
+	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset"
+	"github.com/tektoncd/operator/pkg/reconciler/shared/hash"
+	corev1 "k8s.io/api/core/v1"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"knative.dev/pkg/apis"
+	"knative.dev/pkg/logging"
+	pkgreconciler "knative.dev/pkg/reconciler"
+)
+
+// Reconciler implements controller.Reconciler for TektonChains resources.
+type Reconciler struct {
+	// operatorClientSet allows us to configure operator objects
+	operatorClientSet clientset.Interface
+	// manifest has the source manifest of Tekton Triggers for a
+	// particular version
+	manifest mf.Manifest
+	// Platform-specific behavior to affect the transform
+	// enqueueAfter enqueues a obj after a duration
+	enqueueAfter func(obj interface{}, after time.Duration)
+	extension    common.Extension
+	// chainsVersion describes the current chains version
+	chainsVersion   string
+	operatorVersion string
+	// pipelineInformer provides access to a shared informer and lister for
+	// TektonPipelines
+	pipelineInformer pipelineinformer.TektonPipelineInformer
+}
+
+// Check that our Reconciler implements controller.Reconciler
+var _ tektonchainsreconciler.Interface = (*Reconciler)(nil)
+var _ tektonchainsreconciler.Finalizer = (*Reconciler)(nil)
+
+const createdByValue = "TektonChains"
+
+var (
+	ls = metav1.LabelSelector{
+		MatchLabels: map[string]string{
+			v1alpha1.CreatedByKey:     createdByValue,
+			v1alpha1.InstallerSetType: v1alpha1.ChainsResourceName,
+		},
+	}
+)
+
+// ReconcileKind compares the actual state with the desired, and attempts to
+// converge the two.
+func (r *Reconciler) ReconcileKind(ctx context.Context, tc *v1alpha1.TektonChains) pkgreconciler.Event {
+	logger := logging.FromContext(ctx)
+	tc.Status.InitializeConditions()
+	tc.Status.ObservedGeneration = tc.Generation
+
+	logger.Infow("Reconciling TektonChains", "status", tc.Status)
+
+	if tc.GetName() != v1alpha1.ChainsResourceName {
+		msg := fmt.Sprintf("Resource ignored, Expected Name: %s, Got Name: %s",
+			v1alpha1.ChainsResourceName,
+			tc.GetName(),
+		)
+		logger.Error(msg)
+		tc.Status.MarkNotReady(msg)
+		return nil
+	}
+
+	// find a valid TektonPipeline installation
+	if _, err := common.PipelineReady(r.pipelineInformer); err != nil {
+		if err.Error() == common.PipelineNotReady {
+			tc.Status.MarkDependencyInstalling("TektonPipeline is still installing")
+			// wait for TektonPipeline status to change
+			return fmt.Errorf(common.PipelineNotReady)
+		}
+		// (tektonpipeline.operator.tekton.dev instance not available yet)
+		tc.Status.MarkDependencyMissing("TektonPipeline does not exist")
+		return err
+	}
+	tc.Status.MarkDependenciesInstalled()
+
+	// Pass the object through defaulting
+	tc.SetDefaults(ctx)
+
+	// Mark TektonChains Instance as Not Ready if an upgrade is needed
+	if err := r.markUpgrade(ctx, tc); err != nil {
+		return err
+	}
+
+	if err := r.extension.PreReconcile(ctx, tc); err != nil {
+		tc.Status.MarkPreReconcilerFailed(fmt.Sprintf("PreReconciliation failed: %s", err.Error()))
+		return err
+	}
+
+	// Mark PreReconcile Complete
+	tc.Status.MarkPreReconcilerComplete()
+
+	// Check if a Tekton InstallerSet already exists, if not then create one
+	labelSelector, err := common.LabelSelector(ls)
+	if err != nil {
+		return err
+	}
+	existingInstallerSet, err := tektoninstallerset.CurrentInstallerSetName(ctx, r.operatorClientSet, labelSelector)
+	if err != nil {
+		return err
+	}
+	if existingInstallerSet == "" {
+		tc.Status.MarkInstallerSetNotAvailable("Chains InstallerSet not available")
+
+		createdIs, err := r.createInstallerSet(ctx, tc)
+		if err != nil {
+			return err
+		}
+
+		return r.updateTektonChainsStatus(ctx, tc, createdIs)
+	}
+
+	// If exists, then fetch the InstallerSet
+	installedTIS, err := r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
+		Get(ctx, existingInstallerSet, metav1.GetOptions{})
+	if err != nil {
+		if apierrors.IsNotFound(err) {
+			createdIs, err := r.createInstallerSet(ctx, tc)
+			if err != nil {
+				return err
+			}
+			return r.updateTektonChainsStatus(ctx, tc, createdIs)
+		}
+		logger.Error("failed to get InstallerSet: %s", err)
+		return err
+	}
+
+	installerSetTargetNamespace := installedTIS.Annotations[v1alpha1.TargetNamespaceKey]
+	installerSetReleaseVersion := installedTIS.Labels[v1alpha1.ReleaseVersionKey]
+
+	// Check if TargetNamespace of existing TektonInstallerSet is same as expected
+	// Check if Release Version in TektonInstallerSet is same as expected
+	// If any of the above things is not same then delete the existing TektonInstallerSet
+	// and create a new with expected properties
+
+	if installerSetTargetNamespace != tc.Spec.TargetNamespace || installerSetReleaseVersion != r.operatorVersion {
+		// Delete the existing TektonInstallerSet
+		err := r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
+			Delete(ctx, existingInstallerSet, metav1.DeleteOptions{})
+		if err != nil {
+			logger.Error("failed to delete InstallerSet: %s", err)
+			return err
+		}
+
+		// Make sure the TektonInstallerSet is deleted
+		_, err = r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
+			Get(ctx, existingInstallerSet, metav1.GetOptions{})
+		if err == nil {
+			tc.Status.MarkNotReady("Waiting for previous installer set to get deleted")
+			r.enqueueAfter(tc, 10*time.Second)
+			return nil
+		}
+		if !apierrors.IsNotFound(err) {
+			logger.Error("failed to get InstallerSet: %s", err)
+			return err
+		}
+		return nil
+
+	} else {
+		// If target namespace and version are not changed then check if Chains
+		// spec is changed by checking hash stored as annotation on
+		// TektonInstallerSet with computing new hash of TektonChains Spec
+
+		// Hash of TektonChains Spec
+		expectedSpecHash, err := hash.Compute(tc.Spec)
+		if err != nil {
+			return err
+		}
+
+		// spec hash stored on installerSet
+		lastAppliedHash := installedTIS.GetAnnotations()[v1alpha1.LastAppliedHashKey]
+
+		if lastAppliedHash != expectedSpecHash {
+
+			manifest := r.manifest
+			// installerSet adds it's owner as namespace's owner
+			// so deleting tekton chain deletes target namespace too
+			// to skip it we filter out namespace if pipeline have same namespace
+			pipelineNamespace, err := common.PipelineTargetNamspace(r.pipelineInformer)
+			if err != nil {
+				logger.Error("unable to fetch pipeline namespace:  ", err)
+				return err
+			}
+			if tc.Spec.GetTargetNamespace() == pipelineNamespace {
+				manifest = manifest.Filter(mf.Not(mf.ByKind("Namespace")))
+			}
+			if err := r.transform(ctx, &manifest, tc); err != nil {
+				logger.Error("manifest transformation failed:  ", err)
+				return err
+			}
+
+			// Update the spec hash
+			current := installedTIS.GetAnnotations()
+			current[v1alpha1.LastAppliedHashKey] = expectedSpecHash
+			installedTIS.SetAnnotations(current)
+
+			// Update the manifests
+			installedTIS.Spec.Manifests = manifest.Resources()
+
+			if _, err = r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
+				Update(ctx, installedTIS, metav1.UpdateOptions{}); err != nil {
+				return err
+			}
+
+			// after updating installer set enqueue after a duration
+			// to allow changes to get deployed
+			r.enqueueAfter(tc, 20*time.Second)
+			return nil
+		}
+	}
+
+	// Mark InstallerSetAvailable
+	tc.Status.MarkInstallerSetAvailable()
+
+	ready := installedTIS.Status.GetCondition(apis.ConditionReady)
+	if ready == nil {
+		tc.Status.MarkInstallerSetNotReady("Waiting for installation")
+		r.enqueueAfter(tc, 10*time.Second)
+		return nil
+	}
+
+	if ready.Status == corev1.ConditionUnknown {
+		tc.Status.MarkInstallerSetNotReady("Waiting for installation")
+		r.enqueueAfter(tc, 10*time.Second)
+		return nil
+	} else if ready.Status == corev1.ConditionFalse {
+		tc.Status.MarkInstallerSetNotReady(ready.Message)
+		r.enqueueAfter(tc, 10*time.Second)
+		return nil
+	}
+
+	// Mark InstallerSet Ready
+	tc.Status.MarkInstallerSetReady()
+
+	if err := r.extension.PostReconcile(ctx, tc); err != nil {
+		tc.Status.MarkPostReconcilerFailed(fmt.Sprintf("PostReconciliation failed: %s", err.Error()))
+		return err
+	}
+
+	// Mark PostReconcile Complete
+	tc.Status.MarkPostReconcilerComplete()
+
+	// Update the object for any spec changes
+	if _, err := r.operatorClientSet.OperatorV1alpha1().TektonChainses().Update(ctx, tc, metav1.UpdateOptions{}); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// FinalizeKind removes all resources after deletion of a TektonChains.
+func (r *Reconciler) FinalizeKind(ctx context.Context, original *v1alpha1.TektonChains) pkgreconciler.Event {
+	logger := logging.FromContext(ctx)
+
+	// Delete CRDs before deleting rest of resources so that any instance
+	// of CRDs which has finalizer set will get deleted before we remove
+	// the controller's deployment for it
+	if err := r.manifest.Filter(mf.CRDs).Delete(); err != nil {
+		logger.Error("Failed to deleted CRDs for TektonChains")
+		return err
+	}
+
+	labelSelector, err := common.LabelSelector(ls)
+	if err != nil {
+		return err
+	}
+	if err := r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
+		DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{
+			LabelSelector: labelSelector,
+		}); err != nil {
+		logger.Error("Failed to delete installer set created by TektonChains", err)
+		return err
+	}
+
+	if err := r.extension.Finalize(ctx, original); err != nil {
+		logger.Error("Failed to finalize platform resources", err)
+	}
+
+	return nil
+}
+
+func (r *Reconciler) updateTektonChainsStatus(ctx context.Context, tc *v1alpha1.TektonChains, createdIs *v1alpha1.TektonInstallerSet) error {
+	// update the tc with TektonInstallerSet and releaseVersion
+	tc.Status.SetTektonInstallerSet(createdIs.Name)
+	tc.Status.SetVersion(r.chainsVersion)
+
+	return v1alpha1.RECONCILE_AGAIN_ERR
+}
+
+// transform mutates the passed manifest to one with common, component
+// and platform transformations applied
+func (r *Reconciler) transform(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) error {
+	instance := comp.(*v1alpha1.TektonChains)
+	chainsImages := common.ToLowerCaseKeys(common.ImagesFromEnv(common.ChainsImagePrefix))
+	extra := []mf.Transformer{
+		common.ApplyProxySettings,
+		common.DeploymentImages(chainsImages),
+		common.AddConfiguration(instance.Spec.Config),
+	}
+	extra = append(extra, r.extension.Transformers(instance)...)
+	return common.Transform(ctx, manifest, instance, extra...)
+}
+
+func (r *Reconciler) createInstallerSet(ctx context.Context, tc *v1alpha1.TektonChains) (*v1alpha1.TektonInstallerSet, error) {
+
+	manifest := r.manifest
+	// installerSet adds it's owner as namespace's owner
+	// so deleting tekton chain deletes target namespace too
+	// to skip it we filter out namespace if pipeline have same namespace
+	pipelineNamespace, err := common.PipelineTargetNamspace(r.pipelineInformer)
+	if err != nil {
+		return nil, err
+	}
+	if tc.Spec.GetTargetNamespace() == pipelineNamespace {
+		manifest = manifest.Filter(mf.Not(mf.ByKind("Namespace")))
+	}
+	if err := r.transform(ctx, &manifest, tc); err != nil {
+		tc.Status.MarkNotReady("transformation failed: " + err.Error())
+		return nil, err
+	}
+
+	// compute the hash of tektonchains spec and store as an annotation
+	// in further reconciliation we compute hash of tc spec and check with
+	// annotation, if they are same then we skip updating the object
+	// otherwise we update the manifest
+	specHash, err := hash.Compute(tc.Spec)
+	if err != nil {
+		return nil, err
+	}
+
+	// create installer set
+	tis := makeInstallerSet(tc, manifest, specHash, r.operatorVersion)
+	createdIs, err := r.operatorClientSet.OperatorV1alpha1().TektonInstallerSets().
+		Create(ctx, tis, metav1.CreateOptions{})
+	if err != nil {
+		return nil, err
+	}
+	return createdIs, nil
+}
+
+func makeInstallerSet(tc *v1alpha1.TektonChains, manifest mf.Manifest, tdSpecHash, releaseVersion string) *v1alpha1.TektonInstallerSet {
+	ownerRef := *metav1.NewControllerRef(tc, tc.GetGroupVersionKind())
+	return &v1alpha1.TektonInstallerSet{
+		ObjectMeta: metav1.ObjectMeta{
+			GenerateName: fmt.Sprintf("%s-", v1alpha1.ChainsResourceName),
+			Labels: map[string]string{
+				v1alpha1.CreatedByKey:      createdByValue,
+				v1alpha1.ReleaseVersionKey: releaseVersion,
+				v1alpha1.InstallerSetType:  v1alpha1.ChainsResourceName,
+			},
+			Annotations: map[string]string{
+				v1alpha1.TargetNamespaceKey: tc.Spec.TargetNamespace,
+				v1alpha1.LastAppliedHashKey: tdSpecHash,
+			},
+			OwnerReferences: []metav1.OwnerReference{ownerRef},
+		},
+		Spec: v1alpha1.TektonInstallerSetSpec{
+			Manifests: manifest.Resources(),
+		},
+	}
+}
+
+func (r *Reconciler) markUpgrade(ctx context.Context, tc *v1alpha1.TektonChains) error {
+	labels := tc.GetLabels()
+	ver, ok := labels[v1alpha1.ReleaseVersionKey]
+	if ok && ver == r.operatorVersion {
+		return nil
+	}
+	if ok && ver != r.operatorVersion {
+		tc.Status.MarkInstallerSetNotReady(v1alpha1.UpgradePending)
+		tc.Status.MarkPreReconcilerFailed(v1alpha1.UpgradePending)
+		tc.Status.MarkPostReconcilerFailed(v1alpha1.UpgradePending)
+		tc.Status.MarkNotReady(v1alpha1.UpgradePending)
+	}
+	if labels == nil {
+		labels = map[string]string{}
+	}
+	labels[v1alpha1.ReleaseVersionKey] = r.operatorVersion
+	tc.SetLabels(labels)
+
+	if _, err := r.operatorClientSet.OperatorV1alpha1().TektonChainses().Update(ctx,
+		tc, metav1.UpdateOptions{}); err != nil {
+		return err
+	}
+	return v1alpha1.RECONCILE_AGAIN_ERR
+}
diff --git a/pkg/reconciler/kubernetes/tektonhub/tektonhub.go b/pkg/reconciler/kubernetes/tektonhub/tektonhub.go
index 4970b39e9..0c970c33e 100644
--- a/pkg/reconciler/kubernetes/tektonhub/tektonhub.go
+++ b/pkg/reconciler/kubernetes/tektonhub/tektonhub.go
@@ -56,9 +56,11 @@ type Reconciler struct {
 }
 
 var (
-	apiConfigMapName string = "api"
-	errKeyMissing    error  = fmt.Errorf("secret doesn't contains all the keys")
-	namespace        string
+	apiConfigMapName       string = "api"
+	errKeyMissing          error  = fmt.Errorf("secret doesn't contains all the keys")
+	namespace              string
+	uiConfigMapName        string = "ui"
+	errconfigMapKeyMissing error  = fmt.Errorf("configMap doesn't contains all the keys")
 	// Check that our Reconciler implements controller.Reconciler
 	_ tektonhubconciler.Interface = (*Reconciler)(nil)
 	_ tektonhubconciler.Finalizer = (*Reconciler)(nil)
@@ -75,8 +77,10 @@ const (
 	dbInstallerSet          = "DbInstallerSet"
 	dbMigrationInstallerSet = "DbMigrationInstallerSet"
 	apiInstallerSet         = "ApiInstallerSet"
+	uiInstallerSet          = "UiInstallerSet"
 	dbComponent             = "tekton-hub-db"
 	apiComponent            = "tekton-hub-api"
+	uiComponent             = "tekton-hub-ui"
 	dbMigrationComponent    = "tekton-hub-db-migration"
 	createdByValue          = "TektonHub"
 )
@@ -155,6 +159,12 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, th *v1alpha1.TektonHub)
 	}
 	th.Status.MarkApiInstallerSetAvailable()
 
+	// Manage UI
+	if err := r.manageUiComponent(ctx, th, hubDir, version); err != nil {
+		return r.handleError(err, th)
+	}
+	th.Status.MarkUiInstallerSetAvailable()
+
 	if err := r.extension.PostReconcile(ctx, th); err != nil {
 		return err
 	}
@@ -172,6 +182,38 @@ func (r *Reconciler) handleError(err error, th *v1alpha1.TektonHub) error {
 	return err
 }
 
+func (r *Reconciler) manageUiComponent(ctx context.Context, th *v1alpha1.TektonHub, hubDir, version string) error {
+	if err := r.validateUiConfigMap(ctx, th); err != nil {
+		th.Status.MarkUiDependencyMissing(fmt.Sprintf("UI config map not present: %v", err.Error()))
+		r.enqueueAfter(th, 10*time.Second)
+		return nil
+	}
+
+	th.Status.MarkUiDependenciesInstalled()
+
+	exist, err := checkIfInstallerSetExist(ctx, r.operatorClientSet, version, th, uiInstallerSet)
+	if err != nil {
+		return err
+	}
+
+	if !exist {
+		th.Status.MarkUiInstallerSetNotAvailable("UI installer set not available")
+		uiLocation := filepath.Join(hubDir, "ui")
+		err := r.setupAndCreateInstallerSet(ctx, uiLocation, th, uiInstallerSet, version, uiComponent)
+		if err != nil {
+			return err
+		}
+	}
+
+	err = r.checkComponentStatus(ctx, th, uiInstallerSet)
+	if err != nil {
+		th.Status.MarkUiInstallerSetNotAvailable(err.Error())
+		return v1alpha1.RECONCILE_AGAIN_ERR
+	}
+
+	return nil
+}
+
 func (r *Reconciler) manageApiComponent(ctx context.Context, th *v1alpha1.TektonHub, hubDir, version string) error {
 	// Validate whether the secrets and configmap are created for API
 	if err := r.validateApiDependencies(ctx, th); err != nil {
@@ -343,6 +385,52 @@ func (r *Reconciler) validateApiDependencies(ctx context.Context, th *v1alpha1.T
 	return nil
 }
 
+func (r *Reconciler) validateUiConfigMap(ctx context.Context, th *v1alpha1.TektonHub) error {
+	logger := logging.FromContext(ctx)
+
+	uiConfigMapKeys := []string{"API_URL", "AUTH_BASE_URL", "API_VERSION", "REDIRECT_URI"}
+	_, err := r.getConfigMap(ctx, uiConfigMapName, namespace, uiConfigMapKeys)
+	if err != nil {
+		if apierrors.IsNotFound(err) {
+			configMap := createUiConfigMap(uiConfigMapName, namespace, th)
+			_, err = r.kubeClientSet.CoreV1().ConfigMaps(namespace).Create(ctx, configMap, metav1.CreateOptions{})
+			if err != nil {
+				logger.Error(err)
+				th.Status.MarkUiDependencyMissing(fmt.Sprintf("%s configMap is missing", uiConfigMapName))
+				return err
+			}
+			return nil
+		}
+		if err == errconfigMapKeyMissing {
+			th.Status.MarkUiDependencyMissing(fmt.Sprintf("%s configMap is missing the keys", uiConfigMapName))
+			return err
+		} else {
+			logger.Error(err)
+			return err
+		}
+	}
+
+	return nil
+}
+
+func createUiConfigMap(name, namespace string, th *v1alpha1.TektonHub) *corev1.ConfigMap {
+	return &corev1.ConfigMap{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      name,
+			Namespace: namespace,
+			Labels: map[string]string{
+				"ui": "tektonhub-ui",
+			},
+		},
+		Data: map[string]string{
+			"API_URL":       th.Status.ApiRouteUrl,
+			"AUTH_BASE_URL": th.Status.AuthRouteUrl,
+			"API_VERSION":   "v1",
+			"REDIRECT_URI":  "https://" + th.Status.UiRouteUrl,
+		},
+	}
+}
+
 func (r *Reconciler) setupAndCreateInstallerSet(ctx context.Context, manifestLocation string, th *v1alpha1.TektonHub, installerSetName, version, prefixName string) error {
 	manifest := r.manifest.Append()
 	logger := logging.FromContext(ctx)
diff --git a/pkg/reconciler/openshift/common/transformer.go b/pkg/reconciler/openshift/common/transformer.go
index f0a8d794f..c975b5a52 100644
--- a/pkg/reconciler/openshift/common/transformer.go
+++ b/pkg/reconciler/openshift/common/transformer.go
@@ -38,8 +38,10 @@ func RemoveRunAsUser() mf.Transformer {
 
 		for i := range d.Spec.Template.Spec.Containers {
 			c := &d.Spec.Template.Spec.Containers[i]
-			// Remove runAsUser
-			c.SecurityContext.RunAsUser = nil
+			if c.SecurityContext != nil {
+				// Remove runAsUser
+				c.SecurityContext.RunAsUser = nil
+			}
 		}
 
 		unstrObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(d)
@@ -67,8 +69,10 @@ func RemoveRunAsGroup() mf.Transformer {
 
 		for i := range d.Spec.Template.Spec.Containers {
 			c := &d.Spec.Template.Spec.Containers[i]
-			// Remove runAsGroup
-			c.SecurityContext.RunAsGroup = nil
+			if c.SecurityContext != nil {
+				// Remove runAsGroup
+				c.SecurityContext.RunAsGroup = nil
+			}
 		}
 
 		unstrObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(d)
diff --git a/pkg/reconciler/openshift/tektonchains/controller.go b/pkg/reconciler/openshift/tektonchains/controller.go
new file mode 100644
index 000000000..df48ab816
--- /dev/null
+++ b/pkg/reconciler/openshift/tektonchains/controller.go
@@ -0,0 +1,31 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package tektonchains
+
+import (
+	"context"
+
+	k8s_ctrl "github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektonchains"
+	"knative.dev/pkg/configmap"
+	"knative.dev/pkg/controller"
+)
+
+// NewController initializes the controller and is called by the generated code
+// Registers eventhandlers to enqueue events
+func NewController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
+	return k8s_ctrl.NewExtendedController(OpenShiftExtension)(ctx, cmw)
+}
diff --git a/pkg/reconciler/openshift/tektonchains/extension.go b/pkg/reconciler/openshift/tektonchains/extension.go
new file mode 100644
index 000000000..b9ac87409
--- /dev/null
+++ b/pkg/reconciler/openshift/tektonchains/extension.go
@@ -0,0 +1,56 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package tektonchains
+
+import (
+	"context"
+
+	mf "github.com/manifestival/manifestival"
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	"github.com/tektoncd/operator/pkg/client/clientset/versioned"
+	operatorclient "github.com/tektoncd/operator/pkg/client/injection/client"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
+	occommon "github.com/tektoncd/operator/pkg/reconciler/openshift/common"
+)
+
+func OpenShiftExtension(ctx context.Context) common.Extension {
+	ext := openshiftExtension{
+		operatorClientSet: operatorclient.Get(ctx),
+	}
+	return ext
+}
+
+type openshiftExtension struct {
+	operatorClientSet versioned.Interface
+}
+
+func (oe openshiftExtension) Transformers(comp v1alpha1.TektonComponent) []mf.Transformer {
+	return []mf.Transformer{
+		occommon.RemoveRunAsUser(),
+		occommon.RemoveRunAsGroup(),
+		occommon.ApplyCABundles,
+	}
+}
+func (oe openshiftExtension) PreReconcile(ctx context.Context, tc v1alpha1.TektonComponent) error {
+	return nil
+}
+func (oe openshiftExtension) PostReconcile(context.Context, v1alpha1.TektonComponent) error {
+	return nil
+}
+func (oe openshiftExtension) Finalize(context.Context, v1alpha1.TektonComponent) error {
+	return nil
+}
diff --git a/pkg/reconciler/openshift/tektonhub/extension.go b/pkg/reconciler/openshift/tektonhub/extension.go
index 01b25d096..1b926e875 100644
--- a/pkg/reconciler/openshift/tektonhub/extension.go
+++ b/pkg/reconciler/openshift/tektonhub/extension.go
@@ -41,6 +41,7 @@ import (
 const (
 	tektonHubAPIResourceKey  string = "api"
 	tektonHubAuthResourceKey string = "auth"
+	tektonHubUiResourceKey   string = "ui"
 )
 
 func OpenShiftExtension(ctx context.Context) common.Extension {
@@ -83,7 +84,9 @@ func (oe openshiftExtension) PreReconcile(ctx context.Context, tc v1alpha1.Tekto
 	if err := common.AppendManifest(&manifest, hubDir); err != nil {
 		return err
 	}
-	manifest, err := manifest.Transform(
+
+	apiRouteManifest := manifest.Filter(mf.ByKind("Route"))
+	apiRouteManifest, err := apiRouteManifest.Transform(
 		mf.InjectOwner(th),
 		mf.InjectNamespace(targetNs),
 	)
@@ -91,21 +94,19 @@ func (oe openshiftExtension) PreReconcile(ctx context.Context, tc v1alpha1.Tekto
 		logger.Error("failed to transform manifest")
 		return err
 	}
-
-	// Just apply the routes and nothing else
-	if err := manifest.Filter(mf.ByKind("Route")).Apply(); err != nil {
+	if err := apiRouteManifest.Apply(); err != nil {
 		return err
 	}
 
 	// Get the host of API route
-	apiRoute, err := getRouteHost(&manifest, tektonHubAPIResourceKey)
+	apiRoute, err := getRouteHost(&apiRouteManifest, tektonHubAPIResourceKey)
 	if err != nil {
 		return err
 	}
 	th.Status.SetApiRoute(fmt.Sprintf("https://%s", apiRoute))
 
 	// Get the host of Auth route
-	authRoute, err := getRouteHost(&manifest, tektonHubAuthResourceKey)
+	authRoute, err := getRouteHost(&apiRouteManifest, tektonHubAuthResourceKey)
 	if err != nil {
 		return err
 	}
@@ -116,6 +117,35 @@ func (oe openshiftExtension) PreReconcile(ctx context.Context, tc v1alpha1.Tekto
 		return err
 	}
 
+	// Create UI route based on the value of ui i.e. false/true
+
+	uiHubDir := filepath.Join(common.ComponentDir(th), common.TargetVersion(th), tektonHubUiResourceKey)
+	uiManifest := oe.manifest.Append()
+
+	if err := common.AppendManifest(&uiManifest, uiHubDir); err != nil {
+		return err
+	}
+
+	uiRouteManifest := uiManifest.Filter(mf.ByKind("Route"))
+	uiRouteManifest, err = uiRouteManifest.Transform(
+		mf.InjectOwner(th),
+		mf.InjectNamespace(targetNs),
+	)
+	if err != nil {
+		logger.Error("failed to transform manifest")
+		return err
+	}
+	if err := uiRouteManifest.Apply(); err != nil {
+		return err
+	}
+
+	uiRoute, err := getRouteHost(&uiRouteManifest, "ui")
+	if err != nil {
+		return err
+	}
+
+	th.Status.SetUiRoute(fmt.Sprintf("https://%s", uiRoute))
+
 	return nil
 }
 
diff --git a/pkg/reconciler/shared/tektonconfig/chains/chains.go b/pkg/reconciler/shared/tektonconfig/chains/chains.go
new file mode 100644
index 000000000..ee94a46dc
--- /dev/null
+++ b/pkg/reconciler/shared/tektonconfig/chains/chains.go
@@ -0,0 +1,180 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package chains
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"reflect"
+
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	op "github.com/tektoncd/operator/pkg/client/clientset/versioned/typed/operator/v1alpha1"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
+	apierrs "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/util/wait"
+)
+
+func EnsureTektonChainsExists(ctx context.Context, clients op.TektonChainsInterface, config *v1alpha1.TektonConfig) (*v1alpha1.TektonChains, error) {
+	tcCR, err := GetChains(ctx, clients, v1alpha1.ChainsResourceName)
+	if err != nil {
+		if !apierrs.IsNotFound(err) {
+			return nil, err
+		}
+		// if TektonChains CR is not found in the cluster, then create one
+		_, err = CreateChains(ctx, clients, config)
+		if err != nil {
+			return nil, err
+		}
+		return nil, v1alpha1.RECONCILE_AGAIN_ERR
+	}
+
+	// so TektonChains CR does exist in the cluster, checking if any updates are required.
+	// if the chains spec is changed then update the instance
+	tcCR, err = UpdateChains(ctx, tcCR, config, clients)
+	if err != nil {
+		return nil, err
+	}
+
+	ok, err := isTektonChainsReady(tcCR, err)
+	if err != nil {
+		return nil, err
+	}
+	if !ok {
+		return nil, v1alpha1.RECONCILE_AGAIN_ERR
+	}
+
+	return tcCR, err
+}
+
+func GetChains(ctx context.Context, clients op.TektonChainsInterface, name string) (*v1alpha1.TektonChains, error) {
+	return clients.Get(ctx, name, metav1.GetOptions{})
+}
+
+func CreateChains(ctx context.Context, clients op.TektonChainsInterface, config *v1alpha1.TektonConfig) (*v1alpha1.TektonChains, error) {
+	ownerRef := *metav1.NewControllerRef(config, config.GroupVersionKind())
+	tcCR := &v1alpha1.TektonChains{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:            v1alpha1.ChainsResourceName,
+			OwnerReferences: []metav1.OwnerReference{ownerRef},
+		},
+		Spec: v1alpha1.TektonChainsSpec{
+			CommonSpec: v1alpha1.CommonSpec{
+				TargetNamespace: config.Spec.TargetNamespace,
+			},
+			Config: config.Spec.Config,
+		},
+	}
+	_, err := clients.Create(ctx, tcCR, metav1.CreateOptions{})
+	if err != nil {
+		return nil, err
+	}
+	return tcCR, err
+}
+
+func UpdateChains(ctx context.Context, tcCR *v1alpha1.TektonChains, config *v1alpha1.TektonConfig, clients op.TektonChainsInterface) (*v1alpha1.TektonChains, error) {
+	// if the chains spec is changed then update the instance
+	updated := false
+
+	if config.Spec.TargetNamespace != tcCR.Spec.TargetNamespace {
+		tcCR.Spec.TargetNamespace = config.Spec.TargetNamespace
+		updated = true
+	}
+
+	if !reflect.DeepEqual(tcCR.Spec.Config, config.Spec.Config) {
+		tcCR.Spec.Config = config.Spec.Config
+		updated = true
+	}
+
+	if tcCR.ObjectMeta.OwnerReferences == nil {
+		ownerRef := *metav1.NewControllerRef(config, config.GroupVersionKind())
+		tcCR.ObjectMeta.OwnerReferences = []metav1.OwnerReference{ownerRef}
+		updated = true
+	}
+
+	if updated {
+		_, err := clients.Update(ctx, tcCR, metav1.UpdateOptions{})
+		if err != nil {
+			return nil, err
+		}
+		return nil, v1alpha1.RECONCILE_AGAIN_ERR
+	}
+	return tcCR, nil
+}
+
+// isTektonChainsReady will check the status conditions of the TektonChains and return true if the TektonChains is ready.
+func isTektonChainsReady(s *v1alpha1.TektonChains, err error) (bool, error) {
+	upgradePending, errInternal := common.CheckUpgradePending(s)
+	if err != nil {
+		return false, errInternal
+	}
+	if upgradePending {
+		return false, v1alpha1.DEPENDENCY_UPGRADE_PENDING_ERR
+	}
+	return s.Status.IsReady(), err
+}
+
+// TektonChainsCRDelete deletes TektonChains CR to see if all resources will be deleted
+func TektonChainsCRDelete(ctx context.Context, clients op.TektonChainsInterface, name string) error {
+	if _, err := GetChains(ctx, clients, v1alpha1.ChainsResourceName); err != nil {
+		// nothing to delete if CR does not exist in the cluster
+		if apierrs.IsNotFound(err) {
+			return nil
+		}
+		return err
+	}
+	if err := clients.Delete(ctx, name, metav1.DeleteOptions{}); err != nil {
+		return fmt.Errorf("TektonChains %q failed to delete: %v", name, err)
+	}
+	err := wait.PollImmediate(common.Interval, common.Timeout, func() (bool, error) {
+		_, err := clients.Get(ctx, name, metav1.GetOptions{})
+		if apierrs.IsNotFound(err) {
+			return true, nil
+		}
+		return false, err
+	})
+	if err != nil {
+		return fmt.Errorf("Timed out waiting on TektonChains to delete %v", err)
+	}
+	return verifyNoTektonChainsCR(ctx, clients)
+}
+
+func verifyNoTektonChainsCR(ctx context.Context, clients op.TektonChainsInterface) error {
+	chainses, err := clients.List(ctx, metav1.ListOptions{})
+	if err != nil {
+		return err
+	}
+	if len(chainses.Items) > 0 {
+		return errors.New("Unable to verify cluster-scoped resources are deleted if any TektonChains exists")
+	}
+	return nil
+}
+
+func GetTektonConfig() *v1alpha1.TektonConfig {
+	return &v1alpha1.TektonConfig{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: v1alpha1.ConfigResourceName,
+		},
+		Spec: v1alpha1.TektonConfigSpec{
+			Profile: "all",
+			CommonSpec: v1alpha1.CommonSpec{
+				TargetNamespace: "tekton-pipelines",
+			},
+		},
+	}
+}
diff --git a/pkg/reconciler/shared/tektonconfig/controller.go b/pkg/reconciler/shared/tektonconfig/controller.go
index b8437c90d..1a1b29912 100644
--- a/pkg/reconciler/shared/tektonconfig/controller.go
+++ b/pkg/reconciler/shared/tektonconfig/controller.go
@@ -33,6 +33,7 @@ import (
 	mfc "github.com/manifestival/client-go-client"
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
 	operatorclient "github.com/tektoncd/operator/pkg/client/injection/client"
+	tektonChainsinformer "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektonchains"
 	tektonConfiginformer "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektonconfig"
 	tektonPipelineinformer "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektonpipeline"
 	tektonTriggerinformer "github.com/tektoncd/operator/pkg/client/injection/informers/operator/v1alpha1/tektontrigger"
@@ -93,6 +94,11 @@ func NewExtensibleController(generator common.ExtensionGenerator) injection.Cont
 			Handler:    controller.HandleAll(impl.EnqueueControllerOf),
 		})
 
+		tektonChainsinformer.Get(ctx).Informer().AddEventHandler(cache.FilteringResourceEventHandler{
+			FilterFunc: controller.FilterController(&v1alpha1.TektonConfig{}),
+			Handler:    controller.HandleAll(impl.EnqueueControllerOf),
+		})
+
 		namespaceinformer.Get(ctx).Informer().AddEventHandler(controller.HandleAll(enqueueCustomName(impl, v1alpha1.ConfigResourceName)))
 
 		if os.Getenv("AUTOINSTALL_COMPONENTS") == "true" {
diff --git a/pkg/reconciler/shared/tektonconfig/tektonconfig.go b/pkg/reconciler/shared/tektonconfig/tektonconfig.go
index 3fa2fc518..25ac5402f 100644
--- a/pkg/reconciler/shared/tektonconfig/tektonconfig.go
+++ b/pkg/reconciler/shared/tektonconfig/tektonconfig.go
@@ -26,6 +26,7 @@ import (
 	clientset "github.com/tektoncd/operator/pkg/client/clientset/versioned"
 	tektonConfigreconciler "github.com/tektoncd/operator/pkg/client/injection/reconciler/operator/v1alpha1/tektonconfig"
 	"github.com/tektoncd/operator/pkg/reconciler/common"
+	"github.com/tektoncd/operator/pkg/reconciler/shared/tektonconfig/chains"
 	"github.com/tektoncd/operator/pkg/reconciler/shared/tektonconfig/pipeline"
 	"github.com/tektoncd/operator/pkg/reconciler/shared/tektonconfig/trigger"
 	"k8s.io/apimachinery/pkg/api/errors"
@@ -144,6 +145,21 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, tc *v1alpha1.TektonConfi
 		}
 	}
 
+	// Create TektonChains CR if profile is all
+	if tc.Spec.Profile == v1alpha1.ProfileAll {
+		if _, err := chains.EnsureTektonChainsExists(ctx, r.operatorClientSet.OperatorV1alpha1().TektonChainses(), tc); err != nil {
+			tc.Status.MarkComponentNotReady(fmt.Sprintf("TektonChains: %s", err.Error()))
+			r.enqueueAfter(tc, 10*time.Second)
+			return err
+		}
+	} else {
+		if err := chains.TektonChainsCRDelete(ctx, r.operatorClientSet.OperatorV1alpha1().TektonChainses(), v1alpha1.ChainsResourceName); err != nil {
+			tc.Status.MarkComponentNotReady(fmt.Sprintf("TektonChains: %s", err.Error()))
+			r.enqueueAfter(tc, 10*time.Second)
+			return err
+		}
+	}
+
 	if err := common.Prune(ctx, r.kubeClientSet, tc); err != nil {
 		tc.Status.MarkComponentNotReady(fmt.Sprintf("tekton-resource-pruner: %s", err.Error()))
 		logger.Error(err)
diff --git a/pkg/webhook/webhook.go b/pkg/webhook/webhook.go
index 42517f7b8..41a45598d 100644
--- a/pkg/webhook/webhook.go
+++ b/pkg/webhook/webhook.go
@@ -35,6 +35,7 @@ var types = map[schema.GroupVersionKind]resourcesemantics.GenericCRD{
 	v1alpha1.SchemeGroupVersion.WithKind("TektonPipeline"): &v1alpha1.TektonPipeline{},
 	v1alpha1.SchemeGroupVersion.WithKind("TektonTrigger"):  &v1alpha1.TektonTrigger{},
 	v1alpha1.SchemeGroupVersion.WithKind("TektonHub"):      &v1alpha1.TektonHub{},
+	v1alpha1.SchemeGroupVersion.WithKind("TektonChains"):   &v1alpha1.TektonChains{},
 }
 
 func SetTypes(platform string) {
diff --git a/tekton/task-fetch-components.yaml b/tekton/task-fetch-components.yaml
index b170dd1e0..8f0297215 100644
--- a/tekton/task-fetch-components.yaml
+++ b/tekton/task-fetch-components.yaml
@@ -18,6 +18,9 @@ spec:
   - name: RESULTS_VERSION
     description: Version of TektonCD Results being fetched
     default: "latest"
+  - name: CHAINS_VERSION
+    description: Version of TektonCD Chains being fetched
+    default: "latest"
   - name: TARGET_PLATFORMS
     description: Target platform for for which the payload is going to be used
     default: "kubernetes openshift"
@@ -30,7 +33,7 @@ spec:
       apk add bash # Bash is not present
       for platform in $(params.TARGET_PLATFORMS); do
         echo "Fetching Tekton components for ${platform} build"
-        ./hack/fetch-releases.sh ${platform} $(params.PIPELINES_VERSION) $(params.TRIGGERS_VERSION) $(params.DASHBOARD_VERSION) $(params.RESULTS_VERSION)
+        ./hack/fetch-releases.sh ${platform} $(params.PIPELINES_VERSION) $(params.TRIGGERS_VERSION) $(params.DASHBOARD_VERSION) $(params.RESULTS_VERSION) $(params.CHAINS_VERSION)
 
         # print directory structure of cmd/<platform>/operator/kodata
         find cmd/${platform}/operator/kodata/


Test patch:
diff --git a/pkg/apis/operator/v1alpha1/tektonchains_lifecycle_test.go b/pkg/apis/operator/v1alpha1/tektonchains_lifecycle_test.go
new file mode 100644
index 000000000..4775ecb8b
--- /dev/null
+++ b/pkg/apis/operator/v1alpha1/tektonchains_lifecycle_test.go
@@ -0,0 +1,144 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1alpha1
+
+import (
+	"testing"
+
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	apistest "knative.dev/pkg/apis/testing"
+)
+
+func TestTektonChainsGroupVersionKind(t *testing.T) {
+	r := &TektonChains{}
+	want := schema.GroupVersionKind{
+		Group:   GroupName,
+		Version: SchemaVersion,
+		Kind:    KindTektonChains,
+	}
+	if got := r.GetGroupVersionKind(); got != want {
+		t.Errorf("got: %v, want: %v", got, want)
+	}
+}
+
+func TestTektonChainsHappyPath(t *testing.T) {
+	tt := &TektonChainsStatus{}
+	tt.InitializeConditions()
+
+	apistest.CheckConditionOngoing(tt, DependenciesInstalled, t)
+	apistest.CheckConditionOngoing(tt, PreReconciler, t)
+	apistest.CheckConditionOngoing(tt, InstallerSetAvailable, t)
+	apistest.CheckConditionOngoing(tt, InstallerSetReady, t)
+	apistest.CheckConditionOngoing(tt, PostReconciler, t)
+
+	// Dependencies installed
+	tt.MarkDependenciesInstalled()
+	apistest.CheckConditionSucceeded(tt, DependenciesInstalled, t)
+
+	// Pre reconciler completes execution
+	tt.MarkPreReconcilerComplete()
+	apistest.CheckConditionSucceeded(tt, PreReconciler, t)
+
+	// Installer set created
+	tt.MarkInstallerSetAvailable()
+	apistest.CheckConditionSucceeded(tt, InstallerSetAvailable, t)
+
+	// InstallerSet is not ready when deployment pods are not up
+	tt.MarkInstallerSetNotReady("waiting for deployments")
+	apistest.CheckConditionFailed(tt, InstallerSetReady, t)
+
+	// InstallerSet and then PostReconciler become ready and we're good.
+	tt.MarkInstallerSetReady()
+	apistest.CheckConditionSucceeded(tt, InstallerSetReady, t)
+
+	tt.MarkPostReconcilerComplete()
+	apistest.CheckConditionSucceeded(tt, PostReconciler, t)
+
+	if ready := tt.IsReady(); !ready {
+		t.Errorf("tt.IsReady() = %v, want true", ready)
+	}
+}
+
+func TestTektonChainsErrorPath(t *testing.T) {
+	tr := &TektonChainsStatus{}
+	tr.InitializeConditions()
+
+	apistest.CheckConditionOngoing(tr, DependenciesInstalled, t)
+	apistest.CheckConditionOngoing(tr, PreReconciler, t)
+	apistest.CheckConditionOngoing(tr, InstallerSetAvailable, t)
+	apistest.CheckConditionOngoing(tr, InstallerSetReady, t)
+	apistest.CheckConditionOngoing(tr, PostReconciler, t)
+
+	// Dependencies installed
+	tr.MarkDependenciesInstalled()
+	apistest.CheckConditionSucceeded(tr, DependenciesInstalled, t)
+
+	// Pre reconciler completes execution
+	tr.MarkPreReconcilerComplete()
+	apistest.CheckConditionSucceeded(tr, PreReconciler, t)
+
+	// Installer set created
+	tr.MarkInstallerSetAvailable()
+	apistest.CheckConditionSucceeded(tr, InstallerSetAvailable, t)
+
+	// InstallerSet is not ready when deployment pods are not up
+	tr.MarkInstallerSetNotReady("waiting for deployments")
+	apistest.CheckConditionFailed(tr, InstallerSetReady, t)
+
+	// InstallerSet and then PostReconciler become ready and we're good.
+	tr.MarkInstallerSetReady()
+	apistest.CheckConditionSucceeded(tr, InstallerSetReady, t)
+
+	tr.MarkPostReconcilerComplete()
+	apistest.CheckConditionSucceeded(tr, PostReconciler, t)
+
+	if ready := tr.IsReady(); !ready {
+		t.Errorf("tr.IsReady() = %v, want true", ready)
+	}
+
+	// In further reconciliation deployment might fail and installer
+	// set will change to not ready
+
+	tr.MarkInstallerSetNotReady("webhook not ready")
+	apistest.CheckConditionFailed(tr, InstallerSetReady, t)
+	if ready := tr.IsReady(); ready {
+		t.Errorf("tr.IsReady() = %v, want false", ready)
+	}
+
+}
+
+func TestTektonChainsExternalDependency(t *testing.T) {
+	tt := &TektonChainsStatus{}
+	tt.InitializeConditions()
+
+	// External marks dependency as failed.
+	tt.MarkDependencyMissing("test")
+
+	apistest.CheckConditionFailed(tt, DependenciesInstalled, t)
+	apistest.CheckConditionOngoing(tt, PreReconciler, t)
+	apistest.CheckConditionOngoing(tt, InstallerSetAvailable, t)
+	apistest.CheckConditionOngoing(tt, InstallerSetReady, t)
+	apistest.CheckConditionOngoing(tt, PostReconciler, t)
+
+	// Dependencies are now ready.
+	tt.MarkDependenciesInstalled()
+	apistest.CheckConditionSucceeded(tt, DependenciesInstalled, t)
+	apistest.CheckConditionOngoing(tt, PreReconciler, t)
+	apistest.CheckConditionOngoing(tt, InstallerSetAvailable, t)
+	apistest.CheckConditionOngoing(tt, InstallerSetReady, t)
+	apistest.CheckConditionOngoing(tt, PostReconciler, t)
+}
diff --git a/pkg/apis/operator/v1alpha1/tektonchains_validation_test.go b/pkg/apis/operator/v1alpha1/tektonchains_validation_test.go
new file mode 100644
index 000000000..ec0669ed2
--- /dev/null
+++ b/pkg/apis/operator/v1alpha1/tektonchains_validation_test.go
@@ -0,0 +1,60 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1alpha1
+
+import (
+	"context"
+	"testing"
+
+	"gotest.tools/v3/assert"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"knative.dev/pkg/apis"
+)
+
+func Test_ValidateTektonChains_MissingTargetNamespace(t *testing.T) {
+
+	td := &TektonChains{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "chains",
+			Namespace: "namespace",
+		},
+		Spec: TektonChainsSpec{},
+	}
+
+	err := td.Validate(context.TODO())
+	assert.Equal(t, "missing field(s): spec.targetNamespace", err.Error())
+}
+
+func Test_ValidateTektonChains_OnDelete(t *testing.T) {
+
+	td := &TektonChains{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "name",
+			Namespace: "namespace",
+		},
+		Spec: TektonChainsSpec{
+			CommonSpec: CommonSpec{
+				TargetNamespace: "namespace",
+			},
+		},
+	}
+
+	err := td.Validate(apis.WithinDelete(context.Background()))
+	if err != nil {
+		t.Errorf("ValidateTektonChains.Validate() on Delete expected no error, but got one, ValidateTektonChains: %v", err)
+	}
+}
diff --git a/pkg/apis/operator/v1alpha1/tektonhub_lifecycle_test.go b/pkg/apis/operator/v1alpha1/tektonhub_lifecycle_test.go
index a670d13c7..b1618f8cf 100644
--- a/pkg/apis/operator/v1alpha1/tektonhub_lifecycle_test.go
+++ b/pkg/apis/operator/v1alpha1/tektonhub_lifecycle_test.go
@@ -74,6 +74,18 @@ func TestTektonHubHappyPath(t *testing.T) {
 	th.MarkApiDependenciesInstalled()
 	apistest.CheckConditionSucceeded(th, ApiDependenciesInstalled, t)
 
+	// UI
+	th.MarkUiDependenciesInstalled()
+	apistest.CheckConditionSucceeded(th, UiDependenciesInstalled, t)
+
+	// InstallerSet is not ready when deployment pods are not up
+	th.MarkUiInstallerSetNotAvailable("waiting for UI deployments")
+	apistest.CheckConditionFailed(th, UiInstallerSetAvailable, t)
+
+	// Installer set created for UI
+	th.MarkUiInstallerSetAvailable()
+	apistest.CheckConditionSucceeded(th, UiInstallerSetAvailable, t)
+
 	th.MarkPreReconcilerComplete()
 	apistest.CheckConditionSucceeded(th, PreReconciler, t)
 
@@ -139,6 +151,18 @@ func TestTektonHubErrorPath(t *testing.T) {
 	th.MarkApiInstallerSetAvailable()
 	apistest.CheckConditionSucceeded(th, ApiInstallerSetAvailable, t)
 
+	// UI
+	th.MarkUiDependenciesInstalled()
+	apistest.CheckConditionSucceeded(th, UiDependenciesInstalled, t)
+
+	// InstallerSet is not ready when deployment pods are not up
+	th.MarkUiInstallerSetNotAvailable("waiting for UI deployments")
+	apistest.CheckConditionFailed(th, UiInstallerSetAvailable, t)
+
+	// Installer set created for UI
+	th.MarkUiInstallerSetAvailable()
+	apistest.CheckConditionSucceeded(th, UiInstallerSetAvailable, t)
+
 	th.MarkPostReconcilerComplete()
 	apistest.CheckConditionSucceeded(th, PostReconciler, t)
 
diff --git a/pkg/reconciler/shared/tektonconfig/chains/chains_test.go b/pkg/reconciler/shared/tektonconfig/chains/chains_test.go
new file mode 100644
index 000000000..c5748f20a
--- /dev/null
+++ b/pkg/reconciler/shared/tektonconfig/chains/chains_test.go
@@ -0,0 +1,46 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package chains
+
+import (
+	"testing"
+
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	"github.com/tektoncd/operator/pkg/client/injection/client/fake"
+	util "github.com/tektoncd/operator/pkg/reconciler/common/testing"
+	ts "knative.dev/pkg/reconciler/testing"
+)
+
+func TestTektonChainsCreateAndDeleteCR(t *testing.T) {
+	ctx, _, _ := ts.SetupFakeContextWithCancel(t)
+	c := fake.Get(ctx)
+	tConfig := GetTektonConfig()
+	_, err := EnsureTektonChainsExists(ctx, c.OperatorV1alpha1().TektonChainses(), tConfig)
+	util.AssertNotEqual(t, err, nil)
+	// recheck chains creation
+	_, err = EnsureTektonChainsExists(ctx, c.OperatorV1alpha1().TektonChainses(), tConfig)
+	util.AssertNotEqual(t, err, nil)
+	err = TektonChainsCRDelete(ctx, c.OperatorV1alpha1().TektonChainses(), v1alpha1.ChainsResourceName)
+	util.AssertEqual(t, err, nil)
+}
+
+func TestTektonChainsCRDelete(t *testing.T) {
+	ctx, _, _ := ts.SetupFakeContextWithCancel(t)
+	c := fake.Get(ctx)
+	err := TektonChainsCRDelete(ctx, c.OperatorV1alpha1().TektonChainses(), v1alpha1.ChainsResourceName)
+	util.AssertEqual(t, err, nil)
+}
diff --git a/test/config.sh b/test/config.sh
index b164c555d..21aea2046 100644
--- a/test/config.sh
+++ b/test/config.sh
@@ -2,4 +2,5 @@ export TEKTON_PIPELINE_VERSION=latest
 export TEKTON_TRIGGERS_VERSION=latest
 export TEKTON_RESULTS_VERSION=v0.4.0
 export TEKTON_DASHBOARD_VERSION=latest
+export TEKTON_CHAINS_VERSION=latest
 export PAC_VERSION=0.5.2
diff --git a/test/e2e-common.sh b/test/e2e-common.sh
index b780751c9..621c1eec8 100755
--- a/test/e2e-common.sh
+++ b/test/e2e-common.sh
@@ -31,6 +31,7 @@ function install_operator_resources() {
   echo :Payload Targets:
   echo Pipelines: ${PIPELINES_VERSION}
   echo Triggers: ${TRIGGERS_VERSION}
+  echo Chains: ${CHAINS_VERSION}
   if [[ ${TARGET} != "openshift" ]]; then
     echo Results: ${RESULTS_VERSION}
     echo Dashboard: ${DASHBOARD_VERSION}
diff --git a/test/e2e/common/tektonconfigdeployment_test.go b/test/e2e/common/00_tektonconfigdeployment_test.go
similarity index 97%
rename from test/e2e/common/tektonconfigdeployment_test.go
rename to test/e2e/common/00_tektonconfigdeployment_test.go
index 7af80fe30..8eb319d99 100644
--- a/test/e2e/common/tektonconfigdeployment_test.go
+++ b/test/e2e/common/00_tektonconfigdeployment_test.go
@@ -120,6 +120,11 @@ func runFeatureTest(t *testing.T, clients *utils.Clients, tc *v1alpha1.TektonCon
 			}
 		}
 
+		// make sure chains is created
+		if _, err := clients.Operator.TektonChainses().Get(context.TODO(), v1alpha1.ChainsResourceName, metav1.GetOptions{}); err != nil {
+			t.Fatalf("failed to get tektonchains")
+		}
+
 		// change the profile and make sure it is reflected on the cluster
 		// ALL -> BASIC
 		tc.Spec.Profile = v1alpha1.ProfileBasic
@@ -147,6 +152,11 @@ func runFeatureTest(t *testing.T, clients *utils.Clients, tc *v1alpha1.TektonCon
 				t.Fatalf("expected error but got nil, tektondashboard not deleted")
 			}
 		}
+
+		// make sure chains is deleted
+		if _, err := clients.Operator.TektonChainses().Get(context.TODO(), v1alpha1.ChainsResourceName, metav1.GetOptions{}); err == nil {
+			t.Fatalf("expected error but got nil, tektonchains not deleted")
+		}
 	})
 
 	t.Run("change-spec-configuration-and-validate", func(t *testing.T) {
diff --git a/test/e2e/common/tektonpipelinedeployment_test.go b/test/e2e/common/01_tektonpipelinedeployment_test.go
similarity index 100%
rename from test/e2e/common/tektonpipelinedeployment_test.go
rename to test/e2e/common/01_tektonpipelinedeployment_test.go
diff --git a/test/e2e/common/tektontriggerdeployment_test.go b/test/e2e/common/02_tektontriggerdeployment_test.go
similarity index 100%
rename from test/e2e/common/tektontriggerdeployment_test.go
rename to test/e2e/common/02_tektontriggerdeployment_test.go
diff --git a/test/e2e/common/03_tektonchainsdeployment_test.go b/test/e2e/common/03_tektonchainsdeployment_test.go
new file mode 100644
index 000000000..8a9574899
--- /dev/null
+++ b/test/e2e/common/03_tektonchainsdeployment_test.go
@@ -0,0 +1,92 @@
+// +build e2e
+
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package common
+
+import (
+	"os"
+	"testing"
+
+	"github.com/tektoncd/operator/test/client"
+	"github.com/tektoncd/operator/test/resources"
+	"github.com/tektoncd/operator/test/utils"
+)
+
+// TestTektonChainsDeployment verifies the TektonChains creation, deployment recreation, and TektonChains deletion.
+func TestTektonChainsDeployment(t *testing.T) {
+	clients := client.Setup(t)
+
+	crNames := utils.ResourceNames{
+		TektonConfig:    "config",
+		TektonPipeline:  "pipeline",
+		TektonChains:    "chains",
+		TargetNamespace: "tekton-pipelines",
+	}
+
+	if os.Getenv("TARGET") == "openshift" {
+		crNames.TargetNamespace = "openshift-pipelines"
+	}
+
+	utils.CleanupOnInterrupt(func() { utils.TearDownPipeline(clients, crNames.TektonPipeline) })
+	defer utils.TearDownPipeline(clients, crNames.TektonPipeline)
+
+	utils.CleanupOnInterrupt(func() { utils.TearDownChains(clients, crNames.TektonChains) })
+	defer utils.TearDownChains(clients, crNames.TektonChains)
+
+	resources.EnsureNoTektonConfigInstance(t, clients, crNames)
+
+	// Create a TektonPipeline
+	if _, err := resources.EnsureTektonPipelineExists(clients.TektonPipeline(), crNames); err != nil {
+		t.Fatalf("TektonPipeline %q failed to create: %v", crNames.TektonPipeline, err)
+	}
+
+	// Test if TektonPipeline can reach the READY status
+	t.Run("create-pipeline", func(t *testing.T) {
+		resources.AssertTektonPipelineCRReadyStatus(t, clients, crNames)
+	})
+
+	// Create a TektonChains
+	if _, err := resources.EnsureTektonChainsExists(clients.TektonChains(), crNames); err != nil {
+		t.Fatalf("TektonChains %q failed to create: %v", crNames.TektonChains, err)
+	}
+
+	// Test if TektonChains can reach the READY status
+	t.Run("create-chains", func(t *testing.T) {
+		resources.AssertTektonChainsCRReadyStatus(t, clients, crNames)
+	})
+
+	// Delete the deployments one by one to see if they will be recreated.
+	t.Run("restore-chains-deployments", func(t *testing.T) {
+		resources.AssertTektonChainsCRReadyStatus(t, clients, crNames)
+		resources.DeleteAndVerifyDeployments(t, clients, crNames.TargetNamespace, utils.TektonChainsDeploymentLabel)
+		resources.AssertTektonChainsCRReadyStatus(t, clients, crNames)
+	})
+
+	// Delete the TektonChains CR instance to see if all resources will be removed
+	t.Run("delete-chains", func(t *testing.T) {
+		resources.AssertTektonChainsCRReadyStatus(t, clients, crNames)
+		resources.TektonChainsCRDelete(t, clients, crNames)
+	})
+
+	// Delete the TektonPipeline CR instance to see if all resources will be removed
+	t.Run("delete-pipeline", func(t *testing.T) {
+		resources.AssertTektonPipelineCRReadyStatus(t, clients, crNames)
+		resources.TektonPipelineCRDelete(t, clients, crNames)
+	})
+
+}
diff --git a/test/resources/tektonchains.go b/test/resources/tektonchains.go
new file mode 100644
index 000000000..546c60769
--- /dev/null
+++ b/test/resources/tektonchains.go
@@ -0,0 +1,138 @@
+/*
+Copyright 2022 The Tekton Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package resources
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"path/filepath"
+	"runtime"
+	"testing"
+
+	mfc "github.com/manifestival/client-go-client"
+	mf "github.com/manifestival/manifestival"
+	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	typedv1alpha1 "github.com/tektoncd/operator/pkg/client/clientset/versioned/typed/operator/v1alpha1"
+	"github.com/tektoncd/operator/test/utils"
+	apierrs "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/util/wait"
+	"knative.dev/pkg/test/logging"
+)
+
+// EnsureTektonChainsExists creates a TektonChains with the name names.TektonChains, if it does not exist.
+func EnsureTektonChainsExists(clients typedv1alpha1.TektonChainsInterface, names utils.ResourceNames) (*v1alpha1.TektonChains, error) {
+	// If this function is called by the upgrade tests, we only create the custom resource, if it does not exist.
+	ks, err := clients.Get(context.TODO(), names.TektonChains, metav1.GetOptions{})
+	if apierrs.IsNotFound(err) {
+		ks := &v1alpha1.TektonChains{
+			ObjectMeta: metav1.ObjectMeta{
+				Name: names.TektonChains,
+			},
+			Spec: v1alpha1.TektonChainsSpec{
+				CommonSpec: v1alpha1.CommonSpec{
+					TargetNamespace: names.TargetNamespace,
+				},
+			},
+		}
+		return clients.Create(context.TODO(), ks, metav1.CreateOptions{})
+	}
+	return ks, err
+}
+
+// WaitForTektonChainsState polls the status of the TektonChains called name
+// from client every `interval` until `inState` returns `true` indicating it
+// is done, returns an error or timeout.
+func WaitForTektonChainsState(clients typedv1alpha1.TektonChainsInterface, name string,
+	inState func(s *v1alpha1.TektonChains, err error) (bool, error)) (*v1alpha1.TektonChains, error) {
+	span := logging.GetEmitableSpan(context.Background(), fmt.Sprintf("WaitForTektonChainsState/%s/%s", name, "TektonChainsIsReady"))
+	defer span.End()
+
+	var lastState *v1alpha1.TektonChains
+	waitErr := wait.PollImmediate(Interval, Timeout, func() (bool, error) {
+		lastState, err := clients.Get(context.TODO(), name, metav1.GetOptions{})
+		return inState(lastState, err)
+	})
+
+	if waitErr != nil {
+		return lastState, fmt.Errorf("tektonchains %s is not in desired state, got: %+v: %w", name, lastState, waitErr)
+	}
+	return lastState, nil
+}
+
+// IsTektonChainsReady will check the status conditions of the TektonChains and return true if the TektonChains is ready.
+func IsTektonChainsReady(s *v1alpha1.TektonChains, err error) (bool, error) {
+	return s.Status.IsReady(), err
+}
+
+// AssertTektonChainsCRReadyStatus verifies if the TektonChains reaches the READY status.
+func AssertTektonChainsCRReadyStatus(t *testing.T, clients *utils.Clients, names utils.ResourceNames) {
+	if _, err := WaitForTektonChainsState(clients.TektonChains(), names.TektonChains,
+		IsTektonChainsReady); err != nil {
+		t.Fatalf("TektonChainsCR %q failed to get to the READY status: %v", names.TektonChains, err)
+	}
+}
+
+// TektonChainsCRDelete deletes tha TektonChains to see if all resources will be deleted
+func TektonChainsCRDelete(t *testing.T, clients *utils.Clients, crNames utils.ResourceNames) {
+	if err := clients.TektonChains().Delete(context.TODO(), crNames.TektonChains, metav1.DeleteOptions{}); err != nil {
+		t.Fatalf("TektonChains %q failed to delete: %v", crNames.TektonChains, err)
+	}
+	err := wait.PollImmediate(Interval, Timeout, func() (bool, error) {
+		_, err := clients.TektonChains().Get(context.TODO(), crNames.TektonChains, metav1.GetOptions{})
+		if apierrs.IsNotFound(err) {
+			return true, nil
+		}
+		return false, err
+	})
+	if err != nil {
+		t.Fatal("Timed out waiting on TektonChains to delete", err)
+	}
+	_, b, _, _ := runtime.Caller(0)
+	m, err := mfc.NewManifest(filepath.Join((filepath.Dir(b)+"/.."), "manifests/"), clients.Config)
+	if err != nil {
+		t.Fatal("Failed to load manifest", err)
+	}
+	if err := verifyNoTektonChainsCR(clients); err != nil {
+		t.Fatal(err)
+	}
+
+	// verify all but the CRD's and the Namespace are gone
+	for _, u := range m.Filter(mf.NoCRDs, mf.Not(mf.ByKind("Namespace"))).Resources() {
+		if _, err := m.Client.Get(&u); !apierrs.IsNotFound(err) {
+			t.Fatalf("The %s %s failed to be deleted: %v", u.GetKind(), u.GetName(), err)
+		}
+	}
+	// verify all the CRD's remain
+	for _, u := range m.Filter(mf.CRDs).Resources() {
+		if _, err := m.Client.Get(&u); apierrs.IsNotFound(err) {
+			t.Fatalf("The %s CRD was deleted", u.GetName())
+		}
+	}
+}
+
+func verifyNoTektonChainsCR(clients *utils.Clients) error {
+	chains, err := clients.TektonChainsAll().List(context.TODO(), metav1.ListOptions{})
+	if err != nil {
+		return err
+	}
+	if len(chains.Items) > 0 {
+		return errors.New("Unable to verify cluster-scoped resources are deleted if any TektonChains exists")
+	}
+	return nil
+}
diff --git a/test/resources/tektontriggers.go b/test/resources/tektontriggers.go
index 57a13e339..20c2b7d7b 100644
--- a/test/resources/tektontriggers.go
+++ b/test/resources/tektontriggers.go
@@ -73,7 +73,7 @@ func WaitForTektonTriggerState(clients triggerv1alpha1.TektonTriggerInterface, n
 	})
 
 	if waitErr != nil {
-		return lastState, fmt.Errorf("tektonpipeline %s is not in desired state, got: %+v: %w", name, lastState, waitErr)
+		return lastState, fmt.Errorf("tektontriggers %s is not in desired state, got: %+v: %w", name, lastState, waitErr)
 	}
 	return lastState, nil
 }
diff --git a/test/utils/cleanup.go b/test/utils/cleanup.go
index 294f6dff4..d18114df4 100644
--- a/test/utils/cleanup.go
+++ b/test/utils/cleanup.go
@@ -84,3 +84,10 @@ func TearDownResult(clients *Clients, name string) {
 		_ = clients.TektonResult().Delete(context.TODO(), name, metav1.DeleteOptions{})
 	}
 }
+
+// TearDownChains will delete created TektonChains CRs using clients.
+func TearDownChains(clients *Clients, name string) {
+	if clients != nil && clients.Operator != nil {
+		_ = clients.TektonChains().Delete(context.TODO(), name, metav1.DeleteOptions{})
+	}
+}
diff --git a/test/utils/clients.go b/test/utils/clients.go
index ff5d082c2..55a513421 100644
--- a/test/utils/clients.go
+++ b/test/utils/clients.go
@@ -140,6 +140,14 @@ func (c *Clients) TektonResultAll() operatorv1alpha1.TektonResultInterface {
 	return c.Operator.TektonResults()
 }
 
+func (c *Clients) TektonChains() operatorv1alpha1.TektonChainsInterface {
+	return c.Operator.TektonChainses()
+}
+
+func (c *Clients) TektonChainsAll() operatorv1alpha1.TektonChainsInterface {
+	return c.Operator.TektonChainses()
+}
+
 func (c *Clients) TektonInstallerSet() operatorv1alpha1.TektonInstallerSetInterface {
 	return c.Operator.TektonInstallerSets()
 }
diff --git a/test/utils/e2e_flags.go b/test/utils/e2e_flags.go
index 4353ffecc..c0ad74037 100644
--- a/test/utils/e2e_flags.go
+++ b/test/utils/e2e_flags.go
@@ -20,4 +20,5 @@ var (
 	TektonPipelineDeploymentLabel  = "app.kubernetes.io/part-of=tekton-pipelines"
 	TektonTriggerDeploymentLabel   = "app.kubernetes.io/part-of=tekton-triggers"
 	TektonDashboardDeploymentLabel = "app.kubernetes.io/part-of=tekton-dashboard"
+	TektonChainsDeploymentLabel    = "app.kubernetes.io/name=tekton-pipelines"
 )
diff --git a/test/utils/names.go b/test/utils/names.go
index 684586ef9..2728fe785 100644
--- a/test/utils/names.go
+++ b/test/utils/names.go
@@ -24,6 +24,7 @@ type ResourceNames struct {
 	TektonAddon     string
 	TektonConfig    string
 	TektonResult    string
+	TektonChains    string
 	Namespace       string
 	TargetNamespace string
 }