Repository: tektoncd/operator
Pull request #1195 (2022-11-30 11:33:56)

Update ClusterInterceptor ClusterRoleBinding after the namespace removal
# Changes

**Issue:** openshift-pipelines-clusterinterceptors ClusterRoleBinding not updated after namespace removal
**Fixes:** Operator rbac will keep on watching on the namespaces which are there in `Subjects` of  openshift-pipelines-clusterinterceptors ClusterRoleBinding and whenever namespace get deleted rbac will update  ClusterRoleBinding by removing the namespace 

**Before:**
```
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: "2022-11-30T10:57:38Z"
  name: openshift-pipelines-clusterinterceptors
  ownerReferences:
  - apiVersion: operator.tekton.dev/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: TektonInstallerSet
    name: rhosp-rbac-z4v56
    uid: f591469b-125d-43c1-ba9a-7f1c95ef98d7
  resourceVersion: "151362"
  uid: 291c40fa-1390-4e90-a391-4e8856ca5a3f
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: openshift-pipelines-clusterinterceptors
subjects:
- kind: ServiceAccount
  name: pipeline
  namespace: default
- kind: ServiceAccount
  name: pipeline
  namespace: openshift
- kind: ServiceAccount
  name: pipeline
  namespace: test
```

**After:**
```
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: "2022-11-30T10:57:38Z"
  name: openshift-pipelines-clusterinterceptors
  ownerReferences:
  - apiVersion: operator.tekton.dev/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: TektonInstallerSet
    name: rhosp-rbac-z4v56
    uid: f591469b-125d-43c1-ba9a-7f1c95ef98d7
  resourceVersion: "151522"
  uid: 291c40fa-1390-4e90-a391-4e8856ca5a3f
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: openshift-pipelines-clusterinterceptors
subjects:
- kind: ServiceAccount
  name: pipeline
  namespace: default
- kind: ServiceAccount
  name: pipeline
  namespace: openshift

```
Signed-off-by: Savita Ashture sashture@redhat.com


<!-- 🎉🎉🎉 Thank you for the PR!!! 🎉🎉🎉 -->

<!-- Describe your changes here- ideally you can get that description straight from
your descriptive commit message(s)! -->

# Submitter Checklist

These are the criteria that every PR should meet, please check them off as you
review them:

- [ ] Run `make test lint` before submitting a PR
- [ ] Includes [tests](https://github.com/tektoncd/community/blob/master/standards.md#principles) (if functionality changed/added)
- [ ] Includes [docs](https://github.com/tektoncd/community/blob/master/standards.md#principles) (if user facing)
- [ ] 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

<!--
Describe any user facing changes here, or delete this block.

Examples of user facing changes:
- API changes
- Bug fixes
- Any changes in behavior
- Changes requiring upgrade notices or deprecation warnings

For pull requests with a release note:

```release-note
Your release note here
```

For pull requests that require additional action from users switching to the new release, include the string "action required" (case insensitive) in the release note:

```release-note
action required: your release note here
```

For pull requests that don't need to be mentioned at release time, use the `/release-note-none` Prow command to add the `release-note-none` label to the PR. You can also write the string "NONE" as a release note in your PR description:

```release-note
NONE
```
-->


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 ask for approval from **savitaashture** after the PR has been reviewed.

The full list of commands accepted by this bot can be found [here](https://prow.tekton.dev/command-help?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":["savitaashture"]} -->
sm43: > From a "performance" perspective, I am a bit worried. Looking at the code, we would execute this every second (right ?). And this would generate a relatively decent amount of API calls (because we are using the clients) : 1 for the `ClusterRoleBinding` and then one for each namespaces referenced in the `ClusterRoleBinding`.
> 
> I wonder if there would be better alternative(s):
> 
>     * We may want to make use of the _global resync tick_ or something to not execute this every second
> 
>     * We may want to use informers instead of client to use cached result instead of query the API too much
> 
>     * We may want to have a specific reconciler (or something) that watch namespaces and reconcile the `ClusterRoleBinding` with it
> 
> 
> cc @sm43 @concaf

one way could be moving `ensureClusterRoleBindings` out of the for loop
so we know which namespace we want to have in clusterrolebinding 
so we check if they exist at once
we could use hash to detect change... hashing the ns array
sm43: > From a "performance" perspective, I am a bit worried. Looking at the code, we would execute this every second (right ?). And this would generate a relatively decent amount of API calls (because we are using the clients) : 1 for the `ClusterRoleBinding` and then one for each namespaces referenced in the `ClusterRoleBinding`.
> 
> I wonder if there would be better alternative(s):
> 
>     * We may want to make use of the _global resync tick_ or something to not execute this every second
> 
>     * We may want to use informers instead of client to use cached result instead of query the API too much
> 
>     * We may want to have a specific reconciler (or something) that watch namespaces and reconcile the `ClusterRoleBinding` with it
> 
> 
> cc @sm43 @concaf


well about the optimization, yeah we could do that too, using listers to fetch and client only to update
having a seperate reconciler would be my proposal
as change in ns trigger TC reconciler which does a lot other than rbac

savitaashture: > From a "performance" perspective, I am a bit worried. Looking at the code, we would execute this every second (right ?). And this would generate a relatively decent amount of API calls (because we are using the clients) : 1 for the `ClusterRoleBinding` and then one for each namespaces referenced in the `ClusterRoleBinding`.
> 
> I wonder if there would be better alternative(s):
> 
> * We may want to make use of the _global resync tick_ or something to not execute this every second
> * We may want to use informers instead of client to use cached result instead of query the API too much
> * We may want to have a specific reconciler (or something) that watch namespaces and reconcile the `ClusterRoleBinding` with it
> 
> cc @sm43 @concaf

* We may want to use informers instead of client to use cached result instead of query the API too much
Can try this because it avoids too many API calls
savitaashture: @vdemeester @sm43 
Updated PR
PTAL
Thank you

Patch:
diff --git a/config/openshift/base/operator.yaml b/config/openshift/base/operator.yaml
index 06e93c2d1..ed5aa191a 100644
--- a/config/openshift/base/operator.yaml
+++ b/config/openshift/base/operator.yaml
@@ -81,15 +81,15 @@ spec:
         - name: CONFIG_OBSERVABILITY_NAME
           value: tekton-config-observability
         - name: IMAGE_HUB_TEKTON_HUB_DB
-          value: registry.redhat.io/rhel8/postgresql-13@sha256:9fd7af383b4070866b7ae013f19e9c672de7dff14e1661fd24d763277ac1cfd3
+          value: registry.redhat.io/rhel8/postgresql-13@sha256:d3872cca802419af86eab8b0a566ae94c85cec6a8786a3b97f43ca5fcb095248
         - name: IMAGE_ADDONS_PARAM_BUILDER_IMAGE
-          value: registry.redhat.io/rhel8/buildah@sha256:0a86ecbdfbe86e9d225b7fe4b090a0dd6d323f8afdfdf2bd933ff223ddb53320
+          value: registry.redhat.io/rhel8/buildah@sha256:ac0b8714cc260c94435cab46fe41b3de0ccbc3d93e38c395fa9d52ac49e521fe
         - name: IMAGE_ADDONS_PARAM_KN_IMAGE
-          value: registry.redhat.io/openshift-serverless-1/client-kn-rhel8@sha256:356a55c587203ae8205fd177f39cd1a6dbd8962c4dffcbc576d74009b668d256
+          value: registry.redhat.io/openshift-serverless-1/client-kn-rhel8@sha256:89fb53858bb93ada958faff761915f45d01e3364b5e5df4ba05b01c4b8cde587
         - name: IMAGE_ADDONS_MVN_SETTINGS
-          value: registry.redhat.io/ubi8/ubi-minimal@sha256:c7b45019f4db32e536e69e102c4028b66bf5cde173cfff4ffd3281ccf7bb3863
+          value: registry.redhat.io/ubi8/ubi-minimal@sha256:6910799b75ad41f00891978575a0d955be2f800c51b955af73926e7ab59a41c3
         - name: IMAGE_ADDONS_SKOPEO_COPY
-          value: registry.redhat.io/rhel8/skopeo@sha256:5a83242e519a2b6e3387c3567ba799a94604be1b7d2e3cd134a631b9827c9762
+          value: registry.redhat.io/rhel8/skopeo@sha256:52579594e3057f7a5f7a4665d0b5ceeb1204e24e020a45553d6aae7c6820bb31
         - name: IMAGE_ADDONS_GENERATE
           value: registry.redhat.io/ocp-tools-4-tech-preview/source-to-image-rhel8@sha256:98d8cb3a255641ca6a1bce854e5e2460c20de9fb9b28e3cc67eb459f122873dd
         - name: IMAGE_ADDONS_GEN_ENV_FILE
diff --git a/config/openshift/base/role.yaml b/config/openshift/base/role.yaml
index a06415d84..4212838ae 100644
--- a/config/openshift/base/role.yaml
+++ b/config/openshift/base/role.yaml
@@ -128,6 +128,8 @@ rules:
   - create
   - update
   - delete
+  - list
+  - watch
 - apiGroups:
   - apiextensions.k8s.io
   resources:
diff --git a/docs/TektonHub.md b/docs/TektonHub.md
index c08843847..a895827ee 100644
--- a/docs/TektonHub.md
+++ b/docs/TektonHub.md
@@ -14,6 +14,9 @@ To install Tekton Hub on your cluster follow steps as given below:
   - Resources in the hub db will be also automatically refreshed with the updated data with the time which is specified in the Hub CR i.e `catalogRefreshInterval: 30m`. Default time interval is 30m
   -  If you are using your database instead of default one then
   secret name for the database should be `tekton-hub-db` and you need to create the secret in your targetNamespace with the following keys
+  - **The dependency of config.yaml from git is removed and complete config data is moved into API configMap. Now user can add the config data i.e.
+    `categories, catalogs, scopes and defaultScopes` in the Hub CR itself. If user does not add any data then default
+    data provided by Hub in the API configMap will be used**
 
   ```yaml
   apiVersion: v1
@@ -46,10 +49,39 @@ To install Tekton Hub on your cluster follow steps as given below:
     # in default installation namespace ie `openshift-pipelines` in case of OpenShift and `tekton-pipelines` in case of Kubernetes
     db:                      # 👈 Optional: If user wants to use his database
       secret: tekton-hub-db  # 👈 Name of db secret should be `tekton-hub-db`
+  
+    categories:                     # 👈 Optional: If user wants to use his categories 
+      - Automation
+      - Build Tools
+      - CLI
+      - Cloud
+      - Code Quality
+      - ...
+  
+    catalogs:                       # 👈 Optional: If user wants to use his catalogs
+      - name: tekton
+        org: tektoncd
+        type: community
+        provider: github
+        url: https://github.com/tektoncd/catalog
+        revision: main
+
+    scopes:                         # 👈 Optional: User can define his scopes  
+      - name: agent:create
+        users: [abc, qwe, pqr]
+      - name: catalog:refresh
+        users: [abc, qwe, pqr]
+      - name: config:refresh
+        users: [abc, qwe, pqr]
+
+    default:                       # 👈 Optional: User can define his default scopes
+      scopes:
+        - rating:read
+        - rating:write
+
     api:
-      hubConfigUrl: https://raw.githubusercontent.com/tektoncd/hub/main/config.yaml
       catalogRefreshInterval: 30m     # After every 30min catalog resources in the hub db would be refreshed to get the updated data from the catalog. Supported time units are As(A seconds), Bm(B minutes) Ch(C hours), Dd(D days) and Ew(E weeks).
-    ```
+  ```
 
 - You can install Tekton Hub by running the command
 
@@ -101,8 +133,37 @@ To install Tekton Hub on your cluster follow steps as given below:
       # in default installation namespace ie `openshift-pipelines` in case of OpenShift and `tekton-pipelines` in case of Kubernetes
       db:                      # 👈 Optional: If user wants to use his database
         secret: tekton-hub-db  # 👈 Name of db secret should be `tekton-hub-db`
+   
+      categories:                     # 👈 Optional: If user wants to use his categories 
+        - Automation
+        - Build Tools
+        - CLI
+        - Cloud
+        - Code Quality
+        - ...
+  
+      catalogs:                       # 👈 Optional: If user wants to use his catalogs
+        - name: tekton
+          org: tektoncd
+          type: community
+          provider: github
+          url: https://github.com/tektoncd/catalog
+          revision: main
+
+      scopes:                         # 👈 Optional: User can define his scopes 
+        - name: agent:create
+          users: [abc, qwe, pqr]
+        - name: catalog:refresh
+          users: [abc, qwe, pqr]
+        - name: config:refresh
+          users: [abc, qwe, pqr]
+
+      default:                       # 👈 Optional: User can define his default scopes
+        scopes:
+          - rating:read
+          - rating:write
+   
       api:
-        hubConfigUrl: https://raw.githubusercontent.com/tektoncd/hub/main/config.yaml
         catalogRefreshInterval: 30m     # After every 30min catalog resources in the hub db would be refreshed to get the updated data from the catalog. Supported time units are As(A seconds), Bm(B minutes) Ch(C hours), Dd(D days) and Ew(E weeks).
     ```
 
diff --git a/operatorhub/openshift/config.yaml b/operatorhub/openshift/config.yaml
index 9b2dd7061..5656a122a 100644
--- a/operatorhub/openshift/config.yaml
+++ b/operatorhub/openshift/config.yaml
@@ -90,7 +90,7 @@ image-substitutions:
       containerName: openshift-pipelines-operator-lifecycle
       envKeys:
       - IMAGE_PIPELINES_ARG__NOP_IMAGE
-- image: registry.redhat.io/ubi8/ubi-minimal@sha256:c7b45019f4db32e536e69e102c4028b66bf5cde173cfff4ffd3281ccf7bb3863
+- image: registry.redhat.io/ubi8/ubi-minimal@sha256:6910799b75ad41f00891978575a0d955be2f800c51b955af73926e7ab59a41c3
   replaceLocations:
     envTargets:
     - deploymentName: openshift-pipelines-operator
@@ -125,21 +125,21 @@ image-substitutions:
       containerName: openshift-pipelines-operator-lifecycle
       envKeys:
       - IMAGE_TRIGGERS_ARG__EL_IMAGE
-- image: registry.redhat.io/openshift-serverless-1/client-kn-rhel8@sha256:356a55c587203ae8205fd177f39cd1a6dbd8962c4dffcbc576d74009b668d256
+- image: registry.redhat.io/openshift-serverless-1/client-kn-rhel8@sha256:89fb53858bb93ada958faff761915f45d01e3364b5e5df4ba05b01c4b8cde587
   replaceLocations:
     envTargets:
     - deploymentName: openshift-pipelines-operator
       containerName: openshift-pipelines-operator-lifecycle
       envKeys:
       - IMAGE_ADDONS_PARAM_KN_IMAGE
-- image: registry.redhat.io/rhel8/skopeo@sha256:5a83242e519a2b6e3387c3567ba799a94604be1b7d2e3cd134a631b9827c9762
+- image: registry.redhat.io/rhel8/skopeo@sha256:52579594e3057f7a5f7a4665d0b5ceeb1204e24e020a45553d6aae7c6820bb31
   replaceLocations:
     envTargets:
     - deploymentName: openshift-pipelines-operator
       containerName: openshift-pipelines-operator-lifecycle
       envKeys:
       - IMAGE_ADDONS_SKOPEO_COPY
-- image: registry.redhat.io/rhel8/buildah@sha256:0a86ecbdfbe86e9d225b7fe4b090a0dd6d323f8afdfdf2bd933ff223ddb53320
+- image: registry.redhat.io/rhel8/buildah@sha256:ac0b8714cc260c94435cab46fe41b3de0ccbc3d93e38c395fa9d52ac49e521fe
   replaceLocations:
     envTargets:
     - deploymentName: openshift-pipelines-operator
@@ -155,7 +155,7 @@ image-substitutions:
       - IMAGE_ADDONS_GENERATE
       - IMAGE_ADDONS_GEN_ENV_FILE
 
-- image: registry.redhat.io/ubi8/ubi-minimal@sha256:c7b45019f4db32e536e69e102c4028b66bf5cde173cfff4ffd3281ccf7bb3863
+- image: registry.redhat.io/ubi8/ubi-minimal@sha256:6910799b75ad41f00891978575a0d955be2f800c51b955af73926e7ab59a41c3
   replaceLocations:
     envTargets:
       - deploymentName: openshift-pipelines-operator
@@ -189,7 +189,7 @@ image-substitutions:
         containerName: openshift-pipelines-operator-lifecycle
         envKeys:
           - IMAGE_CHAINS_TEKTON_CHAINS_CONTROLLER
-- image: registry.redhat.io/rhel8/postgresql-13@sha256:9fd7af383b4070866b7ae013f19e9c672de7dff14e1661fd24d763277ac1cfd3
+- image: registry.redhat.io/rhel8/postgresql-13@sha256:d3872cca802419af86eab8b0a566ae94c85cec6a8786a3b97f43ca5fcb095248
   replaceLocations:
     envTargets:
       - deploymentName: openshift-pipelines-operator
diff --git a/pkg/reconciler/common/prune.go b/pkg/reconciler/common/prune.go
index 25f52e1e1..a1d6ce39d 100644
--- a/pkg/reconciler/common/prune.go
+++ b/pkg/reconciler/common/prune.go
@@ -333,6 +333,9 @@ func createCronJob(ctx context.Context, kc kubernetes.Interface, cronName, targe
 	backOffLimit := int32(3)
 	ttlSecondsAfterFinished := int32(3600)
 	runAsNonRoot := true
+	runAsUser := int64(65532)
+	fsGroup := int64(65532)
+
 	cj := &batchv1.CronJob{
 		TypeMeta: v1.TypeMeta{
 			Kind:       "CronJob",
@@ -365,6 +368,8 @@ func createCronJob(ctx context.Context, kc kubernetes.Interface, cronName, targe
 								SeccompProfile: &corev1.SeccompProfile{
 									Type: corev1.SeccompProfileTypeRuntimeDefault,
 								},
+								RunAsUser: &runAsUser,
+								FSGroup:   &fsGroup,
 							},
 						},
 					},
diff --git a/pkg/reconciler/kubernetes/tektoninstallerset/client/update.go b/pkg/reconciler/kubernetes/tektoninstallerset/client/update.go
index 69fc0f684..81e2b3c46 100644
--- a/pkg/reconciler/kubernetes/tektoninstallerset/client/update.go
+++ b/pkg/reconciler/kubernetes/tektoninstallerset/client/update.go
@@ -32,32 +32,22 @@ import (
 func (i *InstallerSetClient) update(ctx context.Context, comp v1alpha1.TektonComponent, toBeUpdatedIS []v1alpha1.TektonInstallerSet, manifest *mf.Manifest, filterAndTransform FilterAndTransform, isType string) ([]v1alpha1.TektonInstallerSet, error) {
 	logger := logging.FromContext(ctx).With("kind", i.resourceKind, "type", isType)
 
-	switch isType {
-	case InstallerTypeMain:
+	if isType == InstallerTypeMain {
 		sets, err := i.updateMainSets(ctx, comp, toBeUpdatedIS, manifest, filterAndTransform)
 		if err != nil {
 			logger.Errorf("installer set update failed for main type: %v", err)
 			return sets, err
 		}
 		return sets, nil
-
-	case InstallerTypePre, InstallerTypePost:
-		logger.Infof("updating installer set: %v", toBeUpdatedIS[0].GetName())
-		updatedSet, err := i.updateSet(ctx, comp, toBeUpdatedIS[0], manifest, filterAndTransform)
-		if err != nil {
-			return nil, fmt.Errorf("failed to update installerset : %v", err)
-		}
-		logger.Infof("updated installer set: %v", toBeUpdatedIS[0].GetName())
-		return []v1alpha1.TektonInstallerSet{*updatedSet}, nil
-
-	case InstallerTypeCustom:
-	// TODO
-
-	default:
-		return nil, fmt.Errorf("invalid installer set type")
 	}
 
-	return nil, nil
+	logger.Infof("updating installer set: %v", toBeUpdatedIS[0].GetName())
+	updatedSet, err := i.updateSet(ctx, comp, toBeUpdatedIS[0], manifest, filterAndTransform)
+	if err != nil {
+		return nil, fmt.Errorf("failed to update installerset : %v", err)
+	}
+	logger.Infof("updated installer set: %v", toBeUpdatedIS[0].GetName())
+	return []v1alpha1.TektonInstallerSet{*updatedSet}, nil
 }
 
 func (i *InstallerSetClient) updateMainSets(ctx context.Context, comp v1alpha1.TektonComponent, toBeUpdatedIS []v1alpha1.TektonInstallerSet, manifest *mf.Manifest, filterAndTransform FilterAndTransform) ([]v1alpha1.TektonInstallerSet, error) {
diff --git a/pkg/reconciler/openshift/tektonaddon/clustertTask.go b/pkg/reconciler/openshift/tektonaddon/clustertTask.go
index 4cef22521..ecbc3e2a1 100644
--- a/pkg/reconciler/openshift/tektonaddon/clustertTask.go
+++ b/pkg/reconciler/openshift/tektonaddon/clustertTask.go
@@ -23,6 +23,7 @@ import (
 
 	mf "github.com/manifestival/manifestival"
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
 	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client"
 )
 
@@ -42,9 +43,11 @@ func (r *Reconciler) EnsureClusterTask(ctx context.Context, enable string, ta *v
 func filterAndTransformClusterTask() client.FilterAndTransform {
 	return func(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) (*mf.Manifest, error) {
 		addon := comp.(*v1alpha1.TektonAddon)
+		addonImages := common.ToLowerCaseKeys(common.ImagesFromEnv(common.AddonsImagePrefix))
 		tfs := []mf.Transformer{
 			replaceKind(KindTask, KindClusterTask),
 			injectLabel(labelProviderType, providerTypeRedHat, overwrite, "ClusterTask"),
+			common.TaskImages(addonImages),
 		}
 		if err := transformers(ctx, manifest, addon, tfs...); err != nil {
 			return nil, err
diff --git a/pkg/reconciler/openshift/tektonaddon/clustertTaskVersioned.go b/pkg/reconciler/openshift/tektonaddon/clustertTaskVersioned.go
index c7e204efb..fb7cd492a 100644
--- a/pkg/reconciler/openshift/tektonaddon/clustertTaskVersioned.go
+++ b/pkg/reconciler/openshift/tektonaddon/clustertTaskVersioned.go
@@ -21,6 +21,7 @@ import (
 
 	mf "github.com/manifestival/manifestival"
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
 	"github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client"
 )
 
@@ -40,9 +41,11 @@ func (r *Reconciler) EnsureVersionedClusterTask(ctx context.Context, enable stri
 func filterAndTransformVersionedClusterTask(version string) client.FilterAndTransform {
 	return func(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) (*mf.Manifest, error) {
 		addon := comp.(*v1alpha1.TektonAddon)
+		addonImages := common.ToLowerCaseKeys(common.ImagesFromEnv(common.AddonsImagePrefix))
 		tfs := []mf.Transformer{
 			replaceKind(KindTask, KindClusterTask),
 			injectLabel(labelProviderType, providerTypeRedHat, overwrite, "ClusterTask"),
+			common.TaskImages(addonImages),
 			setVersionedNames(version),
 		}
 		if err := transformers(ctx, manifest, addon, tfs...); err != nil {
diff --git a/pkg/reconciler/openshift/tektonconfig/extension.go b/pkg/reconciler/openshift/tektonconfig/extension.go
index 81ec6ec8c..364763a63 100644
--- a/pkg/reconciler/openshift/tektonconfig/extension.go
+++ b/pkg/reconciler/openshift/tektonconfig/extension.go
@@ -28,8 +28,12 @@ import (
 	"github.com/tektoncd/operator/pkg/reconciler/common"
 	"github.com/tektoncd/operator/pkg/reconciler/openshift/tektonconfig/extension"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	nsV1 "k8s.io/client-go/informers/core/v1"
+	rbacV1 "k8s.io/client-go/informers/rbac/v1"
 	"k8s.io/client-go/kubernetes"
 	kubeclient "knative.dev/pkg/client/injection/kube/client"
+	namespaceinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/namespace"
+	rbacInformer "knative.dev/pkg/client/injection/kube/informers/rbac/v1/clusterrolebinding"
 )
 
 const (
@@ -40,12 +44,16 @@ func OpenShiftExtension(ctx context.Context) common.Extension {
 	return openshiftExtension{
 		operatorClientSet: operatorclient.Get(ctx),
 		kubeClientSet:     kubeclient.Get(ctx),
+		rbacInformer:      rbacInformer.Get(ctx),
+		nsInformer:        namespaceinformer.Get(ctx),
 	}
 }
 
 type openshiftExtension struct {
 	operatorClientSet versioned.Interface
 	kubeClientSet     kubernetes.Interface
+	rbacInformer      rbacV1.ClusterRoleBindingInformer
+	nsInformer        nsV1.NamespaceInformer
 }
 
 func (oe openshiftExtension) Transformers(comp v1alpha1.TektonComponent) []mf.Transformer {
@@ -57,6 +65,8 @@ func (oe openshiftExtension) PreReconcile(ctx context.Context, tc v1alpha1.Tekto
 	r := rbac{
 		kubeClientSet:     oe.kubeClientSet,
 		operatorClientSet: oe.operatorClientSet,
+		rbacInformer:      oe.rbacInformer,
+		nsInformer:        oe.nsInformer,
 		version:           os.Getenv(versionKey),
 		tektonConfig:      config,
 	}
diff --git a/pkg/reconciler/openshift/tektonconfig/rbac.go b/pkg/reconciler/openshift/tektonconfig/rbac.go
index 24a567e48..9fcffc191 100644
--- a/pkg/reconciler/openshift/tektonconfig/rbac.go
+++ b/pkg/reconciler/openshift/tektonconfig/rbac.go
@@ -29,6 +29,10 @@ import (
 	rbacv1 "k8s.io/api/rbac/v1"
 	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/apimachinery/pkg/selection"
+	nsV1 "k8s.io/client-go/informers/core/v1"
+	rbacV1 "k8s.io/client-go/informers/rbac/v1"
 	"k8s.io/client-go/kubernetes"
 	v1 "k8s.io/client-go/kubernetes/typed/core/v1"
 	"knative.dev/pkg/logging"
@@ -72,6 +76,8 @@ var nsRegex = regexp.MustCompile(common.NamespaceIgnorePattern)
 type rbac struct {
 	kubeClientSet     kubernetes.Interface
 	operatorClientSet clientset.Interface
+	rbacInformer      rbacV1.ClusterRoleBindingInformer
+	nsInformer        nsV1.NamespaceInformer
 	ownerRef          metav1.OwnerReference
 	version           string
 	tektonConfig      *v1alpha1.TektonConfig
@@ -172,6 +178,11 @@ func (r *rbac) createResources(ctx context.Context) error {
 		return err
 	}
 
+	if err := r.removeAndUpdateNSFromCI(ctx); err != nil {
+		logger.Error(err)
+		return err
+	}
+
 	// list of namespaces rbac resources need to be created
 	var rbacNamespaces []corev1.Namespace
 
@@ -605,6 +616,59 @@ func (r *rbac) ensureClusterRoleBindings(ctx context.Context, sa *corev1.Service
 	return err
 }
 
+func (r *rbac) removeAndUpdateNSFromCI(ctx context.Context) error {
+	logger := logging.FromContext(ctx)
+
+	rbacClient := r.kubeClientSet.RbacV1()
+	rb, err := r.rbacInformer.Lister().Get(clusterInterceptors)
+	if err != nil && !errors.IsNotFound(err) {
+		logger.Error(err, "failed to get"+clusterInterceptors)
+		return err
+	}
+	if rb == nil {
+		return nil
+	}
+
+	req, err := labels.NewRequirement(namespaceVersionLabel, selection.Equals, []string{r.version})
+	if err != nil {
+		logger.Error(err, "failed to create requirement: ")
+		return err
+	}
+
+	namespaces, err := r.nsInformer.Lister().List(labels.NewSelector().Add(*req))
+	if err != nil && !errors.IsNotFound(err) {
+		logger.Error(err, "failed to list namespace: ")
+		return err
+	}
+
+	nsMap := map[string]string{}
+	for i := range namespaces {
+		nsMap[namespaces[i].Name] = namespaces[i].Name
+	}
+
+	var update bool
+	for i := 0; i <= len(rb.Subjects)-1; i++ {
+		if len(nsMap) != len(rb.Subjects) {
+			if _, ok := nsMap[rb.Subjects[i].Namespace]; !ok {
+				rb.Subjects = removeIndex(rb.Subjects, i)
+				update = true
+			}
+		}
+	}
+	if update {
+		if _, err := rbacClient.ClusterRoleBindings().Update(ctx, rb, metav1.UpdateOptions{}); err != nil {
+			logger.Error(err, "failed to update "+clusterInterceptors+" crb")
+			return err
+		}
+		logger.Infof("successfully removed namespace and updated %s ", clusterInterceptors)
+	}
+	return nil
+}
+
+func removeIndex(s []rbacv1.Subject, index int) []rbacv1.Subject {
+	return append(s[:index], s[index+1:]...)
+}
+
 func (r *rbac) updateClusterRoleBinding(ctx context.Context, rb *rbacv1.ClusterRoleBinding, sa *corev1.ServiceAccount) error {
 	logger := logging.FromContext(ctx)
 
diff --git a/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/clusterrolebinding/clusterrolebinding.go b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/clusterrolebinding/clusterrolebinding.go
new file mode 100644
index 000000000..7c2081d55
--- /dev/null
+++ b/vendor/knative.dev/pkg/client/injection/kube/informers/rbac/v1/clusterrolebinding/clusterrolebinding.go
@@ -0,0 +1,110 @@
+/*
+Copyright 2022 The Knative 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 clusterrolebinding
+
+import (
+	context "context"
+
+	apirbacv1 "k8s.io/api/rbac/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	v1 "k8s.io/client-go/informers/rbac/v1"
+	kubernetes "k8s.io/client-go/kubernetes"
+	rbacv1 "k8s.io/client-go/listers/rbac/v1"
+	cache "k8s.io/client-go/tools/cache"
+	client "knative.dev/pkg/client/injection/kube/client"
+	factory "knative.dev/pkg/client/injection/kube/informers/factory"
+	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.Rbac().V1().ClusterRoleBindings()
+	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) v1.ClusterRoleBindingInformer {
+	untyped := ctx.Value(Key{})
+	if untyped == nil {
+		logging.FromContext(ctx).Panic(
+			"Unable to fetch k8s.io/client-go/informers/rbac/v1.ClusterRoleBindingInformer from context.")
+	}
+	return untyped.(v1.ClusterRoleBindingInformer)
+}
+
+type wrapper struct {
+	client kubernetes.Interface
+
+	resourceVersion string
+}
+
+var _ v1.ClusterRoleBindingInformer = (*wrapper)(nil)
+var _ rbacv1.ClusterRoleBindingLister = (*wrapper)(nil)
+
+func (w *wrapper) Informer() cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(nil, &apirbacv1.ClusterRoleBinding{}, 0, nil)
+}
+
+func (w *wrapper) Lister() rbacv1.ClusterRoleBindingLister {
+	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 []*apirbacv1.ClusterRoleBinding, err error) {
+	lo, err := w.client.RbacV1().ClusterRoleBindings().List(context.TODO(), metav1.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) (*apirbacv1.ClusterRoleBinding, error) {
+	return w.client.RbacV1().ClusterRoleBindings().Get(context.TODO(), name, metav1.GetOptions{
+		ResourceVersion: w.resourceVersion,
+	})
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index b9bfb76c6..bf2ab9e66 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -2336,6 +2336,7 @@ knative.dev/pkg/client/injection/kube/informers/admissionregistration/v1/validat
 knative.dev/pkg/client/injection/kube/informers/apps/v1/deployment
 knative.dev/pkg/client/injection/kube/informers/core/v1/namespace
 knative.dev/pkg/client/injection/kube/informers/factory
+knative.dev/pkg/client/injection/kube/informers/rbac/v1/clusterrolebinding
 knative.dev/pkg/codegen/cmd/injection-gen
 knative.dev/pkg/codegen/cmd/injection-gen/args
 knative.dev/pkg/codegen/cmd/injection-gen/generators


Test patch:
diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go b/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go
index 315bc56bd..a4eec9655 100644
--- a/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go
+++ b/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go
@@ -18,7 +18,6 @@ package v1alpha1
 
 import (
 	"context"
-	"os"
 	"testing"
 
 	"gotest.tools/v3/assert"
@@ -86,8 +85,7 @@ func Test_SetDefaults_Addon_Params(t *testing.T) {
 			},
 		},
 	}
-	assert.NilError(t, os.Setenv("PLATFORM", "openshift"))
-	defer os.Clearenv()
+	t.Setenv("PLATFORM", "openshift")
 
 	tc.SetDefaults(context.TODO())
 	if len(tc.Spec.Addon.Params) != 3 {
@@ -122,8 +120,7 @@ func Test_SetDefaults_Triggers_Properties(t *testing.T) {
 }
 
 func Test_SetDefaults_PipelineAsCode(t *testing.T) {
-	assert.NilError(t, os.Setenv("PLATFORM", "openshift"))
-	defer os.Clearenv()
+	t.Setenv("PLATFORM", "openshift")
 
 	// PAC disabled through addon
 	tc := &TektonConfig{
diff --git a/pkg/apis/operator/v1alpha1/tektonhub_default_test.go b/pkg/apis/operator/v1alpha1/tektonhub_default_test.go
index 3b12fdbfc..021348fe3 100644
--- a/pkg/apis/operator/v1alpha1/tektonhub_default_test.go
+++ b/pkg/apis/operator/v1alpha1/tektonhub_default_test.go
@@ -18,7 +18,6 @@ package v1alpha1
 
 import (
 	"context"
-	"os"
 	"testing"
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -26,8 +25,7 @@ import (
 
 func TestSetDefault(t *testing.T) {
 
-	os.Setenv("DEFAULT_TARGET_NAMESPACE", "tekton-pipelines")
-	defer os.Unsetenv("DEFAULT_TARGET_NAMESPACE")
+	t.Setenv("DEFAULT_TARGET_NAMESPACE", "tekton-pipelines")
 	th := &TektonHub{
 		ObjectMeta: metav1.ObjectMeta{
 			Name: "hub",
diff --git a/pkg/reconciler/common/prune_test.go b/pkg/reconciler/common/prune_test.go
index f54b50c14..3c6227920 100644
--- a/pkg/reconciler/common/prune_test.go
+++ b/pkg/reconciler/common/prune_test.go
@@ -19,7 +19,6 @@ package common
 import (
 	"context"
 	"errors"
-	"os"
 	"strings"
 	"testing"
 
@@ -109,8 +108,7 @@ func TestCompleteFlowPrune(t *testing.T) {
 		&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-three", Annotations: anno1}},
 		&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-four", Annotations: anno4}},
 	)
-	os.Setenv(JobsTKNImageName, "some")
-	defer os.Unsetenv(JobsTKNImageName)
+	t.Setenv(JobsTKNImageName, "some")
 
 	err := Prune(context.TODO(), client, config)
 	if err != nil {
@@ -211,8 +209,7 @@ func TestAnnotationCmd(t *testing.T) {
 		&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-ten", Annotations: annoResourceTrPr}},
 		&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-thirteen", Annotations: annoStrategyKeep}},
 	)
-	os.Setenv(JobsTKNImageName, "some")
-	defer os.Unsetenv(JobsTKNImageName)
+	t.Setenv(JobsTKNImageName, "some")
 
 	err := Prune(context.TODO(), client, config)
 	if err != nil {
@@ -284,8 +281,7 @@ func TestConfigChange(t *testing.T) {
 		&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "kube-api"}},
 		&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-one", Annotations: anno1}},
 	)
-	os.Setenv(JobsTKNImageName, "some")
-	defer os.Unsetenv(JobsTKNImageName)
+	t.Setenv(JobsTKNImageName, "some")
 
 	err := Prune(context.TODO(), client, config)
 	if err != nil {
@@ -389,8 +385,7 @@ func TestNodeSelectorOrTolerationsChange(t *testing.T) {
 		&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-two", Annotations: annoUniqueSchedule}},
 		&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "ns-three", Annotations: annoUniqueSchedule2}},
 	)
-	os.Setenv(JobsTKNImageName, "some")
-	defer os.Unsetenv(JobsTKNImageName)
+	t.Setenv(JobsTKNImageName, "some")
 
 	// Pruning with the nodes and Tolerations
 	err := Prune(context.TODO(), client, config1)
diff --git a/pkg/reconciler/common/releases_test.go b/pkg/reconciler/common/releases_test.go
index f3d2bfd34..9889d59b4 100644
--- a/pkg/reconciler/common/releases_test.go
+++ b/pkg/reconciler/common/releases_test.go
@@ -17,7 +17,6 @@ limitations under the License.
 package common
 
 import (
-	"os"
 	"testing"
 
 	mf "github.com/manifestival/manifestival"
@@ -31,8 +30,7 @@ const (
 
 func TestGetLatestRelease(t *testing.T) {
 	koPath := "testdata/kodata"
-	os.Setenv(KoEnvKey, koPath)
-	defer os.Unsetenv(KoEnvKey)
+	t.Setenv(KoEnvKey, koPath)
 
 	version := latestRelease(&v1alpha1.TektonTrigger{})
 	util.AssertEqual(t, version, VERSION)
@@ -40,8 +38,7 @@ func TestGetLatestRelease(t *testing.T) {
 
 func TestListReleases(t *testing.T) {
 	koPath := "testdata/kodata"
-	os.Setenv(KoEnvKey, koPath)
-	defer os.Unsetenv(KoEnvKey)
+	t.Setenv(KoEnvKey, koPath)
 	expectedVersionList := []string{"0.15.2", "0.14.3", "0.13.2"}
 
 	version, err := allReleases(&v1alpha1.TektonTrigger{})
diff --git a/pkg/reconciler/common/stages_test.go b/pkg/reconciler/common/stages_test.go
index 6e98bc241..38df48fde 100644
--- a/pkg/reconciler/common/stages_test.go
+++ b/pkg/reconciler/common/stages_test.go
@@ -18,7 +18,6 @@ package common
 
 import (
 	"context"
-	"os"
 	"testing"
 
 	mf "github.com/manifestival/manifestival"
@@ -30,8 +29,7 @@ import (
 )
 
 func TestDeleteObsoleteResources(t *testing.T) {
-	os.Setenv(KoEnvKey, "testdata/kodata")
-	defer os.Unsetenv(KoEnvKey)
+	t.Setenv(KoEnvKey, "testdata/kodata")
 	client := fake.New()
 	manifest, err := mf.NewManifest("testdata/test_delete_obsolete_resources/dummy.release.notags.yaml", mf.UseClient(client))
 	if err != nil {
diff --git a/pkg/reconciler/common/transformers_test.go b/pkg/reconciler/common/transformers_test.go
index 6c5835fa9..6562c9972 100644
--- a/pkg/reconciler/common/transformers_test.go
+++ b/pkg/reconciler/common/transformers_test.go
@@ -18,7 +18,6 @@ package common
 
 import (
 	"context"
-	"os"
 	"path"
 	"testing"
 
@@ -97,7 +96,7 @@ func TestCommonTransformers(t *testing.T) {
 }
 
 func TestImagesFromEnv(t *testing.T) {
-	os.Setenv("IMAGE_PIPELINES_CONTROLLER", "docker.io/pipeline")
+	t.Setenv("IMAGE_PIPELINES_CONTROLLER", "docker.io/pipeline")
 	data := ImagesFromEnv(PipelinesImagePrefix)
 	if !cmp.Equal(data, map[string]string{"CONTROLLER": "docker.io/pipeline"}) {
 		t.Fatalf("Unexpected ImageFromEnv: %s", cmp.Diff(data, map[string]string{"CONTROLLER": "docker.io/pipeline"}))
diff --git a/pkg/reconciler/kubernetes/tektonconfig/extension/dashboard_test.go b/pkg/reconciler/kubernetes/tektonconfig/extension/dashboard_test.go
index af4a4fed8..b122ff0cd 100644
--- a/pkg/reconciler/kubernetes/tektonconfig/extension/dashboard_test.go
+++ b/pkg/reconciler/kubernetes/tektonconfig/extension/dashboard_test.go
@@ -18,7 +18,6 @@ package extension
 
 import (
 	"context"
-	"os"
 	"testing"
 
 	op "github.com/tektoncd/operator/pkg/client/clientset/versioned/typed/operator/v1alpha1"
@@ -109,14 +108,16 @@ func makeUpgradeCheckPass(t *testing.T, ctx context.Context, c op.TektonDashboar
 	// set necessary version labels to make upgrade check pass
 	dashboard, err := c.Get(ctx, v1alpha1.DashboardResourceName, metav1.GetOptions{})
 	util.AssertEqual(t, err, nil)
-	setDummyVersionLabel(dashboard)
+	setDummyVersionLabel(t, dashboard)
 	_, err = c.Update(ctx, dashboard, metav1.UpdateOptions{})
 	util.AssertEqual(t, err, nil)
 }
 
-func setDummyVersionLabel(td *v1alpha1.TektonDashboard) {
+func setDummyVersionLabel(t *testing.T, td *v1alpha1.TektonDashboard) {
+	t.Helper()
+
 	oprVersion := "v1.2.3"
-	os.Setenv(v1alpha1.VersionEnvKey, oprVersion)
+	t.Setenv(v1alpha1.VersionEnvKey, oprVersion)
 
 	labels := td.GetLabels()
 	if labels == nil {
diff --git a/pkg/reconciler/kubernetes/tektoninstallerset/client/update_test.go b/pkg/reconciler/kubernetes/tektoninstallerset/client/update_test.go
index a6ce02dd6..1b5e13837 100644
--- a/pkg/reconciler/kubernetes/tektoninstallerset/client/update_test.go
+++ b/pkg/reconciler/kubernetes/tektoninstallerset/client/update_test.go
@@ -65,6 +65,27 @@ func TestInstallerSetClient_Update(t *testing.T) {
 		wantIS     int
 		wantErr    error
 	}{
+		{
+			name:    "update custom set",
+			setType: InstallerTypeCustom,
+			existingIS: []v1alpha1.TektonInstallerSet{
+				{
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "addon-custom-set-asdas",
+						Annotations: map[string]string{
+							v1alpha1.LastAppliedHashKey: "custom",
+						},
+					},
+					Spec: v1alpha1.TektonInstallerSetSpec{
+						Manifests: []unstructured.Unstructured{
+							serviceAccount, deployment,
+						},
+					},
+				},
+			},
+			resources: []unstructured.Unstructured{serviceAccount, deployment},
+			wantErr:   nil,
+		},
 		{
 			name:    "update pre set",
 			setType: InstallerTypePre,
diff --git a/pkg/reconciler/openshift/tektonconfig/extension/addon_test.go b/pkg/reconciler/openshift/tektonconfig/extension/addon_test.go
index 7fdc7c4fd..2826cb14a 100644
--- a/pkg/reconciler/openshift/tektonconfig/extension/addon_test.go
+++ b/pkg/reconciler/openshift/tektonconfig/extension/addon_test.go
@@ -18,7 +18,6 @@ package extension
 
 import (
 	"context"
-	"os"
 	"testing"
 
 	"github.com/tektoncd/operator/pkg/reconciler/shared/tektonconfig/pipeline"
@@ -110,14 +109,16 @@ func makeUpgradeCheckPass(t *testing.T, ctx context.Context, c op.TektonAddonInt
 	// set necessary version labels to make upgrade check pass
 	addon, err := c.Get(ctx, v1alpha1.AddonResourceName, metav1.GetOptions{})
 	util.AssertEqual(t, err, nil)
-	setDummyVersionLabel(addon)
+	setDummyVersionLabel(t, addon)
 	_, err = c.Update(ctx, addon, metav1.UpdateOptions{})
 	util.AssertEqual(t, err, nil)
 }
 
-func setDummyVersionLabel(ta *v1alpha1.TektonAddon) {
+func setDummyVersionLabel(t *testing.T, ta *v1alpha1.TektonAddon) {
+	t.Helper()
+
 	oprVersion := "v1.2.3"
-	os.Setenv(v1alpha1.VersionEnvKey, oprVersion)
+	t.Setenv(v1alpha1.VersionEnvKey, oprVersion)
 
 	labels := ta.GetLabels()
 	if labels == nil {
diff --git a/pkg/reconciler/openshift/tektonconfig/extension/pipelinesascode_test.go b/pkg/reconciler/openshift/tektonconfig/extension/pipelinesascode_test.go
index c457cce8f..a2718c62d 100644
--- a/pkg/reconciler/openshift/tektonconfig/extension/pipelinesascode_test.go
+++ b/pkg/reconciler/openshift/tektonconfig/extension/pipelinesascode_test.go
@@ -18,13 +18,10 @@ package extension
 
 import (
 	"context"
-	"os"
 	"testing"
 
-	"github.com/tektoncd/operator/pkg/reconciler/shared/tektonconfig/pipeline"
-	"gotest.tools/v3/assert"
-
 	op "github.com/tektoncd/operator/pkg/client/clientset/versioned/typed/operator/v1alpha1"
+	"github.com/tektoncd/operator/pkg/reconciler/shared/tektonconfig/pipeline"
 
 	"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
 	"github.com/tektoncd/operator/pkg/client/injection/client/fake"
@@ -38,8 +35,7 @@ func TestEnsureOpenShiftPipelinesAsCodeExists(t *testing.T) {
 	c := fake.Get(ctx)
 	tConfig := pipeline.GetTektonConfig()
 
-	assert.NilError(t, os.Setenv("PLATFORM", "openshift"))
-	defer os.Clearenv()
+	t.Setenv("PLATFORM", "openshift")
 
 	tConfig.SetDefaults(ctx)
 	// first invocation should create instance as it is non-existent and return RECONCILE_AGAIN_ERR
@@ -71,8 +67,7 @@ func TestEnsureOpenShiftPipelinesAsCodeCRNotExists(t *testing.T) {
 	ctx, _, _ := ts.SetupFakeContextWithCancel(t)
 	c := fake.Get(ctx)
 
-	assert.NilError(t, os.Setenv("PLATFORM", "openshift"))
-	defer os.Clearenv()
+	t.Setenv("PLATFORM", "openshift")
 
 	// when no instance exists, nil error is returned immediately
 	err := EnsureOpenShiftPipelinesAsCodeCRNotExists(ctx, c.OperatorV1alpha1().OpenShiftPipelinesAsCodes())
diff --git a/pkg/reconciler/shared/tektonconfig/pipeline/pipeline_test.go b/pkg/reconciler/shared/tektonconfig/pipeline/pipeline_test.go
index c8bd97ba3..13a5e3adc 100644
--- a/pkg/reconciler/shared/tektonconfig/pipeline/pipeline_test.go
+++ b/pkg/reconciler/shared/tektonconfig/pipeline/pipeline_test.go
@@ -18,7 +18,6 @@ package pipeline
 
 import (
 	"context"
-	"os"
 	"testing"
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -108,14 +107,16 @@ func makeUpgradeCheckPass(t *testing.T, ctx context.Context, c op.TektonPipeline
 	// set necessary version labels to make upgrade check pass
 	pipeline, err := c.Get(ctx, v1alpha1.PipelineResourceName, metav1.GetOptions{})
 	util.AssertEqual(t, err, nil)
-	setDummyVersionLabel(pipeline)
+	setDummyVersionLabel(t, pipeline)
 	_, err = c.Update(ctx, pipeline, metav1.UpdateOptions{})
 	util.AssertEqual(t, err, nil)
 }
 
-func setDummyVersionLabel(tp *v1alpha1.TektonPipeline) {
+func setDummyVersionLabel(t *testing.T, tp *v1alpha1.TektonPipeline) {
+	t.Helper()
+
 	oprVersion := "v1.2.3"
-	os.Setenv(v1alpha1.VersionEnvKey, oprVersion)
+	t.Setenv(v1alpha1.VersionEnvKey, oprVersion)
 
 	labels := tp.GetLabels()
 	if labels == nil {
diff --git a/pkg/reconciler/shared/tektonconfig/trigger/trigger_test.go b/pkg/reconciler/shared/tektonconfig/trigger/trigger_test.go
index 7f650eec1..abb15693f 100644
--- a/pkg/reconciler/shared/tektonconfig/trigger/trigger_test.go
+++ b/pkg/reconciler/shared/tektonconfig/trigger/trigger_test.go
@@ -18,7 +18,6 @@ package trigger
 
 import (
 	"context"
-	"os"
 	"testing"
 
 	op "github.com/tektoncd/operator/pkg/client/clientset/versioned/typed/operator/v1alpha1"
@@ -109,14 +108,16 @@ func makeUpgradeCheckPass(t *testing.T, ctx context.Context, c op.TektonTriggerI
 	// set necessary version labels to make upgrade check pass
 	trigger, err := c.Get(ctx, v1alpha1.TriggerResourceName, metav1.GetOptions{})
 	util.AssertEqual(t, err, nil)
-	setDummyVersionLabel(trigger)
+	setDummyVersionLabel(t, trigger)
 	_, err = c.Update(ctx, trigger, metav1.UpdateOptions{})
 	util.AssertEqual(t, err, nil)
 }
 
-func setDummyVersionLabel(tr *v1alpha1.TektonTrigger) {
+func setDummyVersionLabel(t *testing.T, tr *v1alpha1.TektonTrigger) {
+	t.Helper()
+
 	oprVersion := "v1.2.3"
-	os.Setenv(v1alpha1.VersionEnvKey, oprVersion)
+	t.Setenv(v1alpha1.VersionEnvKey, oprVersion)
 
 	labels := tr.GetLabels()
 	if labels == nil {
diff --git a/pkg/webhook/webhook_init_test.go b/pkg/webhook/webhook_init_test.go
index 4d439a18a..bf332c0f9 100644
--- a/pkg/webhook/webhook_init_test.go
+++ b/pkg/webhook/webhook_init_test.go
@@ -1,7 +1,6 @@
 package webhook
 
 import (
-	"os"
 	"path/filepath"
 	"testing"
 
@@ -20,10 +19,7 @@ func TestCreateWebhookResources(t *testing.T) {
 		testdataPath := filepath.Join("testdata", "validating-defaulting-webhook")
 		m, err := mf.ManifestFrom(mf.Path(testdataPath))
 		assert.NilError(t, err)
-		os.Setenv(POD_NAMESPACE_ENV_KEY, namespace_new)
-		defer func() {
-			os.Unsetenv(POD_NAMESPACE_ENV_KEY)
-		}()
+		t.Setenv(POD_NAMESPACE_ENV_KEY, namespace_new)
 		mOut, err := manifestTransform(&m)
 		assert.NilError(t, err)
 		for _, res := range mOut.Resources() {
diff --git a/test/e2e/common/00_tektonconfigdeployment_test.go b/test/e2e/common/00_tektonconfigdeployment_test.go
index f51c93341..c99d40a74 100644
--- a/test/e2e/common/00_tektonconfigdeployment_test.go
+++ b/test/e2e/common/00_tektonconfigdeployment_test.go
@@ -354,6 +354,10 @@ func runAddonTest(t *testing.T, clients *utils.Clients, tc *v1alpha1.TektonConfi
 				Name:  v1alpha1.ClusterTasksParam,
 				Value: "false",
 			},
+			{
+				Name:  v1alpha1.CommunityClusterTasks,
+				Value: "false",
+			},
 			{
 				Name:  v1alpha1.PipelineTemplatesParam,
 				Value: "false",