The Keycloak operator now has Renovate tracking. Its version is the real Keycloak version, and updates to it are never auto-merged. The phantom server image reference is gone.
platform/keycloak/kustomization.yaml: the three keycloak-k8s-resources/26.0.6 URLs each get a # renovate: datasource=github-tags depName=keycloak/keycloak-k8s-resources marker, which is the existing custom.regex format. The Keycloak CR has no spec.image, so the operator's RELATED_IMAGE_KEYCLOAK picks the server. Measured on prod: operator 26.0.6 runs server quay.io/keycloak/keycloak:26.0.6.
renovate.json5: two new rules.
keycloak/keycloak-k8s-resources gets groupName: keycloak-operator, automerge: false and the labels needs-review + blast-radius. The comment explains why: the operator, CRDs and server are released in lockstep, the IdP gates SSO for every app and kubectl, and passkey-reconciler.yaml encodes 26.0.6 Admin API shapes. Majors still need a dashboard tick.
quay.io/keycloak/keycloak is set to enabled: false.
catalog/keycloak.yaml: source.image is pinned to :26.0.6 and marked documentation-only. apps/wave-1/keycloak.yaml is re-rendered, which changes one line.
platform/keycloak/README.md: corrects the false "Renovate maintains the version" claim. Adds an "Upgrading Keycloak" section with what to check against the passkey reconciler on every bump.
Why the phantom is pinned and not deleted.apps/wave-1/keycloak.yaml deploys nothing, but it is the fixture for the keycloak keycloak-down cases in apps/wave-1/tests/app-slis.test.yaml. Deleting it means relocating that rule, which is a separate observability fix. Finding: Keycloak has no deployed IdP-down alert today. There is no keycloak PrometheusRule on prod. See the handoff.
Verification
renovate-config-validator on 44.167.0: validated successfully.
Local dry run (--platform=local --dry-run=full, 44.167.0):
The operator dependency is extracted 3 times at 26.0.6. Each has one update, 26.8.1 (minor), and all three go to one branch, renovate/keycloak-operator.
quay.io/keycloak/keycloak in the catalog and in the render reports skipReason: disabled with no updates.
Renovate's own applyPackageRules on this config:
Operator minor and patch: automerge:false, labels needs-review, blast-radius.
Operator major: also dependencyDashboardApproval:true.
Control: a sonarr patch still gets automerge:true.
Toolbox gate at 8ed4e30: rc 3, not green. gitea-settings is the only stage that did not run. spec-immutability, decisions-log, lint, l0, render-golden, l1 and approval-policy all passed. L2/L3 scaffold-skipped.
No sensitive paths are touched (infra/gitea/approval-policy.json), so no override is needed.
## What
The Keycloak operator now has Renovate tracking. Its version is the real Keycloak version, and updates to it are never auto-merged. The phantom server image reference is gone.
- **`platform/keycloak/kustomization.yaml`**: the three `keycloak-k8s-resources/26.0.6` URLs each get a `# renovate: datasource=github-tags depName=keycloak/keycloak-k8s-resources` marker, which is the existing `custom.regex` format. The `Keycloak` CR has no `spec.image`, so the operator's `RELATED_IMAGE_KEYCLOAK` picks the server. Measured on prod: operator 26.0.6 runs server `quay.io/keycloak/keycloak:26.0.6`.
- **`renovate.json5`**: two new rules.
- `keycloak/keycloak-k8s-resources` gets `groupName: keycloak-operator`, `automerge: false` and the labels `needs-review` + `blast-radius`. The comment explains why: the operator, CRDs and server are released in lockstep, the IdP gates SSO for every app and kubectl, and `passkey-reconciler.yaml` encodes 26.0.6 Admin API shapes. Majors still need a dashboard tick.
- `quay.io/keycloak/keycloak` is set to `enabled: false`.
- **`catalog/keycloak.yaml`**: `source.image` is pinned to `:26.0.6` and marked documentation-only. `apps/wave-1/keycloak.yaml` is re-rendered, which changes one line.
- **`platform/keycloak/README.md`**: corrects the false "Renovate maintains the version" claim. Adds an "Upgrading Keycloak" section with what to check against the passkey reconciler on every bump.
**Why the phantom is pinned and not deleted.** `apps/wave-1/keycloak.yaml` deploys nothing, but it is the fixture for the keycloak `keycloak-down` cases in `apps/wave-1/tests/app-slis.test.yaml`. Deleting it means relocating that rule, which is a separate observability fix. Finding: Keycloak has **no** deployed IdP-down alert today. There is no keycloak PrometheusRule on prod. See the handoff.
## Verification
- `renovate-config-validator` on `44.167.0`: validated successfully.
- Local dry run (`--platform=local --dry-run=full`, 44.167.0):
- The operator dependency is extracted 3 times at 26.0.6. Each has one update, **26.8.1 (minor)**, and all three go to one branch, `renovate/keycloak-operator`.
- `quay.io/keycloak/keycloak` in the catalog and in the render reports `skipReason: disabled` with no updates.
- Renovate's own `applyPackageRules` on this config:
- Operator minor and patch: `automerge:false`, labels `needs-review, blast-radius`.
- Operator major: also `dependencyDashboardApproval:true`.
- Control: a sonarr patch still gets `automerge:true`.
- Toolbox gate at 8ed4e30: **rc 3, not green**. `gitea-settings` is the only stage that did not run. spec-immutability, decisions-log, lint, l0, render-golden, l1 and approval-policy all passed. L2/L3 scaffold-skipped.
- No sensitive paths are touched (`infra/gitea/approval-policy.json`), so no override is needed.
Handoff: `decisions/2026-10-30-renovate-track-keycloak-operator.md`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The Keycloak CR has no spec.image, so the operator's RELATED_IMAGE_KEYCLOAK picks the
server image; the three keycloak-k8s-resources release URLs in
platform/keycloak/kustomization.yaml are therefore THE Keycloak version, and Renovate
could not see them (no `# renovate:` marker). They now carry markers under one depName
(one branch, groupName keycloak-operator), with a packageRule: automerge false, labels
needs-review + blast-radius; majors still wait on the dashboard.
The untagged quay.io/keycloak/keycloak in catalog/keycloak.yaml renders
apps/wave-1/keycloak.yaml, which no kustomization lists. It is pinned to the operator's
26.0.6 as documentation, re-rendered, and Renovate is disabled for that image so it
cannot raise PRs against a file nothing deploys. The render is kept (not deleted): it is
the fixture for apps/wave-1/tests/app-slis.test.yaml's keycloak SLI rule tests.
README: an "Upgrading Keycloak" section — an operator bump must be checked against
passkey-reconciler.yaml's 26.0.6 Admin API assumptions.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
The Keycloak operator now has Renovate tracking. Its version is the real Keycloak version, and updates to it are never auto-merged. The phantom server image reference is gone.
platform/keycloak/kustomization.yaml: the threekeycloak-k8s-resources/26.0.6URLs each get a# renovate: datasource=github-tags depName=keycloak/keycloak-k8s-resourcesmarker, which is the existingcustom.regexformat. TheKeycloakCR has nospec.image, so the operator'sRELATED_IMAGE_KEYCLOAKpicks the server. Measured on prod: operator 26.0.6 runs serverquay.io/keycloak/keycloak:26.0.6.renovate.json5: two new rules.keycloak/keycloak-k8s-resourcesgetsgroupName: keycloak-operator,automerge: falseand the labelsneeds-review+blast-radius. The comment explains why: the operator, CRDs and server are released in lockstep, the IdP gates SSO for every app and kubectl, andpasskey-reconciler.yamlencodes 26.0.6 Admin API shapes. Majors still need a dashboard tick.quay.io/keycloak/keycloakis set toenabled: false.catalog/keycloak.yaml:source.imageis pinned to:26.0.6and marked documentation-only.apps/wave-1/keycloak.yamlis re-rendered, which changes one line.platform/keycloak/README.md: corrects the false "Renovate maintains the version" claim. Adds an "Upgrading Keycloak" section with what to check against the passkey reconciler on every bump.Why the phantom is pinned and not deleted.
apps/wave-1/keycloak.yamldeploys nothing, but it is the fixture for the keycloakkeycloak-downcases inapps/wave-1/tests/app-slis.test.yaml. Deleting it means relocating that rule, which is a separate observability fix. Finding: Keycloak has no deployed IdP-down alert today. There is no keycloak PrometheusRule on prod. See the handoff.Verification
renovate-config-validatoron44.167.0: validated successfully.--platform=local --dry-run=full, 44.167.0):renovate/keycloak-operator.quay.io/keycloak/keycloakin the catalog and in the render reportsskipReason: disabledwith no updates.applyPackageRuleson this config:automerge:false, labelsneeds-review, blast-radius.dependencyDashboardApproval:true.automerge:true.8ed4e30: rc 3, not green.gitea-settingsis the only stage that did not run. spec-immutability, decisions-log, lint, l0, render-golden, l1 and approval-policy all passed. L2/L3 scaffold-skipped.infra/gitea/approval-policy.json), so no override is needed.Handoff:
decisions/2026-10-30-renovate-track-keycloak-operator.md.🤖 Generated with Claude Code