Expected Behavior
Setting spec.platforms.kubernetes.pipelinesAsCode.enable: false (or the deprecated spec.addon.enablePipelinesAsCode: false) on TektonConfig should disable PipelinesAsCode and be admitted.
Actual Behavior
The update is rejected, and tekton-operator-webhook panics on every attempt:
Error from server (InternalError): Internal error occurred: failed calling webhook
"validation.webhook.operator.tekton.dev": failed to call webhook: Post
"https://tekton-operator-webhook.tekton-operator.svc:443/resource-validation?timeout=10s":
EOF (retried 5 times)
http: panic serving [...]: assignment to entry in nil map
panic({0x193dc20?, 0x345c720?})
runtime/panic.go:860 +0x12c
github.com/openshift-pipelines/pipelines-as-code/pkg/params/settings.getHubCatalogs(0x..., 0x..., 0x0, 0x...)
github.com/openshift-pipelines/pipelines-as-code@v0.49.0/pkg/params/settings/default.go:21 +0x8c
github.com/openshift-pipelines/pipelines-as-code/pkg/params/settings.SyncConfig(0x..., 0x..., 0x0, 0x...)
github.com/openshift-pipelines/pipelines-as-code@v0.49.0/pkg/params/settings/config.go:122 +0x3c
github.com/tektoncd/operator/pkg/apis/operator/v1alpha1.(*PACSettings).validate(...)
github.com/tektoncd/operator/pkg/apis/operator/v1alpha1/openshiftpipelinesascode_validation.go:58 +0x204
github.com/tektoncd/operator/pkg/apis/operator/v1alpha1.(*TektonConfig).Validate(...)
github.com/tektoncd/operator/pkg/apis/operator/v1alpha1/tektonconfig_validation.go:81 +0x568
Steps to Reproduce the Problem
- Install operator v0.81.0 (or current
main) on Kubernetes (non-OpenShift) with profile: all.
- Let the default
TektonConfig reconcile once, so PAC is auto-enabled and platforms.kubernetes.pipelinesAsCode is populated.
- Run
kubectl patch tektonconfig config --type=merge -p '{"spec":{"platforms":{"kubernetes":{"pipelinesAsCode":{"enable":false}}}}}' — it fails with the error above, and kubectl logs -n tekton-operator deploy/tekton-operator-webhook shows the panic.
Additional Info
Client Version: v1.33.4
Server Version: v1.36.2-eks-bca9cf6
➜ tkn version
Client version: 0.42.0
Pipeline version: v1.15.0
Triggers version: v0.37.0
Dashboard version: v0.71.0
PACSettings.Settings is nil (third arg 0x0), and getHubCatalogs writes into it unconditionally at default.go:21. setPACDefaults() is the only code that initializes Settings, and it is gated on PAC being enabled (tektonconfig_defaults.go, Kubernetes branch):
if tc.Spec.Addon.EnablePAC != nil && !*tc.Spec.Addon.EnablePAC {
tc.Spec.Platforms.Kubernetes.PipelinesAsCode.Enable = ptr.Bool(false)
tc.Spec.Platforms.Kubernetes.PipelinesAsCode.PACSettings.Settings = nil
}
if *tc.Spec.Platforms.Kubernetes.PipelinesAsCode.Enable {
tc.Spec.Platforms.Kubernetes.PipelinesAsCode.PACSettings.setPACDefaults(logger) // skipped when disabled
}
It guards Settings == nil internally but never runs on the disable path, and (*PACSettings).validate then calls SyncConfig(..., ps.Settings, ...) unguarded — so defaulting produces an object validation cannot process.
Both routes to disabling hit this, so there is no field-level workaround: addon.enablePipelinesAsCode: false explicitly nils Settings, and platforms.kubernetes.pipelinesAsCode.enable: false leaves it never initialized. The OpenShift branch has the same pattern.
This is permanent rather than transient — every retry fails identically, and because the whole object is rejected, unrelated fields (spec.pipeline.*, spec.trigger.*, spec.dashboard.*, …) cannot be updated either while the disable is requested.
Initializing Settings to map[string]string{} instead of nil when disabling, or moving setPACDefaults outside the *Enable check, would fix it. OpenShiftPipelinesAsCode.SetDefaults in openshiftpipelinesascode_defaults.go already has the equivalent guard.
Expected Behavior
Setting
spec.platforms.kubernetes.pipelinesAsCode.enable: false(or the deprecatedspec.addon.enablePipelinesAsCode: false) onTektonConfigshould disable PipelinesAsCode and be admitted.Actual Behavior
The update is rejected, and
tekton-operator-webhookpanics on every attempt:Steps to Reproduce the Problem
main) on Kubernetes (non-OpenShift) withprofile: all.TektonConfigreconcile once, so PAC is auto-enabled andplatforms.kubernetes.pipelinesAsCodeis populated.kubectl patch tektonconfig config --type=merge -p '{"spec":{"platforms":{"kubernetes":{"pipelinesAsCode":{"enable":false}}}}}'— it fails with the error above, andkubectl logs -n tekton-operator deploy/tekton-operator-webhookshows the panic.Additional Info
Kubernetes version:
Output of
kubectl version:PACSettings.Settingsis nil (third arg0x0), andgetHubCatalogswrites into it unconditionally atdefault.go:21.setPACDefaults()is the only code that initializesSettings, and it is gated on PAC being enabled (tektonconfig_defaults.go, Kubernetes branch):It guards
Settings == nilinternally but never runs on the disable path, and(*PACSettings).validatethen callsSyncConfig(..., ps.Settings, ...)unguarded — so defaulting produces an object validation cannot process.Both routes to disabling hit this, so there is no field-level workaround:
addon.enablePipelinesAsCode: falseexplicitly nilsSettings, andplatforms.kubernetes.pipelinesAsCode.enable: falseleaves it never initialized. The OpenShift branch has the same pattern.This is permanent rather than transient — every retry fails identically, and because the whole object is rejected, unrelated fields (
spec.pipeline.*,spec.trigger.*,spec.dashboard.*, …) cannot be updated either while the disable is requested.Initializing
Settingstomap[string]string{}instead ofnilwhen disabling, or movingsetPACDefaultsoutside the*Enablecheck, would fix it.OpenShiftPipelinesAsCode.SetDefaultsinopenshiftpipelinesascode_defaults.goalready has the equivalent guard.