Skip to content

feat: Add statefulSet as opt-in deployment option - #534

Open
OpinionatedHeron wants to merge 8 commits into
redhat-developer:mainfrom
OpinionatedHeron:stateful
Open

OpinionatedHeron wants to merge 8 commits into
redhat-developer:mainfrom
OpinionatedHeron:stateful

Conversation

@OpinionatedHeron

@OpinionatedHeron OpinionatedHeron commented Sep 14, 2026

Copy link
Copy Markdown
Member

Description of the change

Creating workload templates for multiple workload kinds in order to enable StatefulSet as an option.

Which issue(s) does this PR fix or relate to

Checklist

  • For each Chart updated, version bumped in the corresponding Chart.yaml according to Semantic Versioning.
  • For each Chart updated, variables are documented in the values.yaml and added to the corresponding README.md. The pre-commit utility can be used to generate the necessary content. Run pre-commit run --all-files to run the hooks and then push any resulting changes. The pre-commit Workflow will enforce this and warn you if needed.
  • JSON Schema template updated and re-generated the raw schema via the pre-commit hook.
  • Tests pass using the Chart Testing tool and the ct lint command.
  • If you updated the orchestrator-infra chart, make sure the versions of the Knative CRDs are aligned with the versions of the CRDs installed by the OpenShift Serverless operators declared in the values.yaml file. See Installing Knative Eventing and Knative Serving CRDs for more details.

Signed-off-by: Leanne Ahern <lahern@redhat.com>
Signed-off-by: Leanne Ahern <lahern@redhat.com>
@OpinionatedHeron OpinionatedHeron changed the title feature: Creating workload templates feat: Creating workload templates Sep 14, 2026
Signed-off-by: Leanne Ahern <lahern@redhat.com>

@rm3l rm3l left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OpinionatedHeron Can you rebase your branch and fix the conflicts, so that CI can be triggered? Thanks.

Signed-off-by: Leanne Ahern <lahern@redhat.com>

@rm3l rm3l left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a CI values setting the workload kind to StatefulSet? It would be great to have this tested in CI. Thanks.
See https://github.com/OpinionatedHeron/rhdh-chart/tree/stateful/charts/rhdh/ci

Signed-off-by: Leanne Ahern <lahern@redhat.com>
Signed-off-by: Leanne Ahern <lahern@redhat.com>
Signed-off-by: Leanne Ahern <lahern@redhat.com>
@OpinionatedHeron OpinionatedHeron changed the title feat: Creating workload templates feat: Add statefulSet as opt-in deployment option Sep 17, 2026
Signed-off-by: Leanne Ahern <lahern@redhat.com>
@sonarqubecloud

Copy link
Copy Markdown

@OpinionatedHeron
OpinionatedHeron marked this pull request as ready for review September 17, 2026 21:56
@OpinionatedHeron
OpinionatedHeron requested a review from a team as a code owner September 17, 2026 21:56
@openshift-ci
openshift-ci Bot requested a review from zdrapela September 17, 2026 21:56
@rm3l

rm3l commented Sep 18, 2026

Copy link
Copy Markdown
Member

/agentic_review

@rhdh-qodo-merge

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 🔗 Cross-repo conflicts (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Kind switches run duplicate app pods 🐞 Bug ☼ Reliability
Description
statefulset.yaml creates a different resource kind with the same name and selector as the
Deployment, so Helm cannot patch the existing object in place and creates the StatefulSet before
pruning the obsolete Deployment. Switching workload.kind on an existing release therefore lets
both controllers run their own matching pods during the upgrade, temporarily connecting duplicate
Backstage instances to the same database.
Code

charts/rhdh/templates/workload/statefulset.yaml[R3-5]

+kind: StatefulSet
+metadata:
+  name: {{ include "rhdh.fullname" . }}
Relevance

●● Moderate

Upgrade lifecycle risk is plausible, but Helm’s documented replacement behavior makes team
acceptance uncertain.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The Deployment and StatefulSet have the same generated name and both use rhdh.selectorLabels,
while their mutually exclusive templates change the Kubernetes resource kind. The documentation
explicitly supports changing the kind with a normal Helm upgrade, but the chart contains no
migration hook or other ordering mechanism to remove the previous controller before creating the new
one.

charts/rhdh/templates/deployment.yaml[1-31]
charts/rhdh/templates/workload/statefulset.yaml[1-38]
charts/rhdh/templates/_helpers.tpl[47-54]
charts/rhdh/README.md[422-424]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Switching between Deployment and StatefulSet creates the new controller before Helm removes the old controller, while both use the same pod selector. This temporarily runs duplicate Backstage pods during an upgrade.

## Fix Focus Areas
- charts/rhdh/templates/deployment.yaml[1-31]
- charts/rhdh/templates/workload/statefulset.yaml[1-38]
- charts/rhdh/README.md.gotmpl[261-269]

## Recommended Fix
Add a pre-upgrade migration mechanism that removes the opposite workload kind and waits for its pods to terminate before Helm creates the selected controller. Add upgrade tests for both Deployment-to-StatefulSet and StatefulSet-to-Deployment transitions, and update the documentation to describe the enforced replacement behavior.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Diagnostics miss StatefulSet applications 🔗 Cross-repo conflict ≡ Correctness
Description
collectReleaseData in rhdh-must-gather selects the primary RHDH workload only from Deployments and
treats the first StatefulSet as a database. When workload.kind is StatefulSet, collection omits
the application's runtime data, process information, and heap dumps, and releases containing
PostgreSQL may also leave one StatefulSet entirely uncollected.
Code

charts/rhdh/templates/workload/statefulset.yaml[R1-3]

+{{- if eq (include "rhdh.workloadKind" .) "StatefulSet" }}
+apiVersion: apps/v1
+kind: StatefulSet
Relevance

●● Moderate

Cross-repository collector behavior is plausible, but no closely matching repository precedent
confirms acceptance.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR replaces the application Deployment with a StatefulSet when selected. The must-gather
collector gathers application diagnostics only from its selected primary Deployment, while its
StatefulSet path handles one object as a database and collects only resource details and logs.

charts/rhdh/templates/workload/statefulset.yaml[1-3]
charts/rhdh/templates/deployment.yaml[1-4]
External repo: redhat-developer/rhdh-must-gather, internal/collector/helm.go [202-253]
External repo: redhat-developer/rhdh-must-gather, internal/collector/helm.go [580-621]
External repo: redhat-developer/rhdh-must-gather, internal/collector/workload.go [76-121]
External repo: redhat-developer/rhdh-must-gather, internal/collector/workload.go [125-171]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new application StatefulSet is incompatible with rhdh-must-gather's native Helm collector, which only identifies Deployments as primary workloads and treats a single StatefulSet as the database.

## Fix Focus Areas
- charts/rhdh/templates/workload/statefulset.yaml[1-3]
- /cross_repos/rhdh-must-gather/internal/collector/helm.go[202-253]
- /cross_repos/rhdh-must-gather/internal/collector/helm.go[580-597]

## Recommended Fix
Coordinate a rhdh-must-gather update that enumerates every Deployment and StatefulSet, identifies the primary workload by its `backstage-backend` container regardless of kind, and invokes `CollectWorkload` with application-data collection enabled for that workload. Keep PostgreSQL collection separate and add an end-to-end case for a Helm release using `workload.kind=StatefulSet` before releasing this chart option.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Long release names block installation 🐞 Bug ≡ Correctness
Description
rhdh.statefulSetHeadlessServiceName appends -headless to a fullname that may already be
truncated to the 63-character limit. With a fullname longer than 54 characters, StatefulSet mode
emits an invalid headless Service name and the installation fails resource validation.
Code

charts/rhdh/templates/_helpers.tpl[R68-70]

+{{- define "rhdh.statefulSetHeadlessServiceName" -}}
+{{- printf "%s-headless" (include "rhdh.fullname" .) -}}
+{{- end -}}
Relevance

●●● Strong

Clear Kubernetes naming-limit bug; repository accepts fixes for generated resource names violating
constraints.

PR-#407

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The existing fullname helper permits a 63-character result, after which the new helper adds nine
more characters. That result is used directly as the headless Service's metadata name and as the
StatefulSet's governing service name.

charts/rhdh/templates/_helpers.tpl[13-25]
charts/rhdh/templates/_helpers.tpl[68-73]
charts/rhdh/templates/workload/headless-service.yaml[3-5]
charts/rhdh/templates/workload/statefulset.yaml[17-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The headless Service helper appends a suffix after the fullname has already been truncated, allowing the resulting Service name to exceed 63 characters.

## Fix Focus Areas
- charts/rhdh/templates/_helpers.tpl[68-73]

## Recommended Fix
Apply `trunc 63 | trimSuffix "-"` after combining the fullname with `-headless`. Add a rendering test using a 63-character fullname override and verify that both the Service name and StatefulSet service reference contain the same valid truncated value.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Plugin claims ignore retention settings 🐞 Bug ≡ Correctness
Description
statefulset.yaml emits persistentVolumeClaimRetentionPolicy without emitting
spec.volumeClaimTemplates, while the only dynamically created plugin claim is a pod-level generic
ephemeral volume and the other PVC-backed volumes merely reference existing claims. When StatefulSet
users configure the advertised policy, Kubernetes has no StatefulSet-owned claim to govern, so the
generated plugin claim continues to follow the pod lifecycle.
Code

charts/rhdh/templates/workload/statefulset.yaml[R29-31]

+  {{- with .Values.workload.statefulSet.persistentVolumeClaimRetentionPolicy }}
+  persistentVolumeClaimRetentionPolicy:
+    {{- include "common.tplvalues.render" (dict "value" . "context" $) | nindent 4 }}
Relevance

●●● Strong

Configured StatefulSet retention policy has no StatefulSet-owned claims to govern, making the
advertised setting ineffective.

PR-#382

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The StatefulSet template renders the retention policy but ends after the shared pod template without
defining volumeClaimTemplates, and no other chart template renders such an entry. The shared pod
template instead provides direct references to existing PVCs or creates the dynamic-plugin claim
under ephemeral.volumeClaimTemplate; because the values default dynamic plugins to this ephemeral
storage while exposing the retention-policy setting, none of these volumes is a StatefulSet-created
claim to which that policy can apply.

charts/rhdh/templates/workload/statefulset.yaml[17-37]
charts/rhdh/templates/workload/_backstage-pod-template.tpl[48-74]
charts/rhdh/values.yaml[116-143]
charts/rhdh/values.yaml[207-227]
charts/rhdh/templates/workload/statefulset.yaml[25-38]
charts/rhdh/templates/workload/_backstage-pod-template.tpl[106-114]
charts/rhdh/values.yaml[220-227]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`workload.statefulSet.persistentVolumeClaimRetentionPolicy` is exposed in the values, schema, and documentation and rendered by the StatefulSet template even though the chart does not create any StatefulSet `volumeClaimTemplates`. Its dynamically created plugin PVC is instead a pod-level generic ephemeral volume, leaving the retention policy without an applicable StatefulSet-owned claim.

## Fix Focus Areas
- charts/rhdh/templates/workload/statefulset.yaml[17-37]
- charts/rhdh/templates/workload/_backstage-pod-template.tpl[48-74]
- charts/rhdh/values.yaml[207-227]
- charts/rhdh/values.schema.tmpl.json[443-447]
- charts/rhdh/README.md.gotmpl[222-225]

## Recommended Fix
Either implement dynamic-plugin storage as a StatefulSet `volumeClaimTemplates` entry and mount that claim when `workload.kind` is `StatefulSet`, including a validated volume-claim-template value if needed, or remove `persistentVolumeClaimRetentionPolicy` from the template, values, schema, and documentation until the chart supports StatefulSet-owned claim templates. Keep the existing Deployment storage behavior unchanged.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
⚠️ Tickets: not configured — ticket URL found in PR but could not be fetched — check ticket provider credentials
✅ Cross-repo context — repo relationships
  Explored: repo: redhat-developer/rhdh (sha: b8140abe)
  Explored: repo: redhat-developer/rhdh-must-gather (sha: f253551c)
  Explored: repo: redhat-developer/rhdh-operator (branch: main, sha: 540c6d67)
  Explored: repo: redhat-developer/rhdh-adr (sha: 02b1e659)
Review mode: 🧠 Deep: This is a substantial Helm runtime change introducing parallel Deployment/StatefulSet paths, shared pod-template refactoring, HPA and service behavior, schema validation, and upgrade semantics, creating many independent opportunities for subtle defects.

Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest moving this under the templates folder, not under workload/

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest moving this under the templates folder, not under workload/

Comment thread charts/rhdh/Chart.yaml
version: 2.4.1
appVersion: 2.1.0
version: 2.5.0
appVersion: 2.2.0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
appVersion: 2.2.0
appVersion: 2.1.0

Should not be changed. This is the version of RHDH.

Comment thread charts/rhdh/values.yaml
updateStrategy: {}

# -- Optional PVC retention policy for the StatefulSet.
persistentVolumeClaimRetentionPolicy: {}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This retention policy makes sense for StatefulSet-owned PVCs. So if this is configurable, it will make sense to also expose a field like volumeClaimTemplates IMO.

Comment thread charts/rhdh/values.yaml
# -- StatefulSet update strategy.
updateStrategy: {}

# -- Optional PVC retention policy for the StatefulSet.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# -- Optional PVC retention policy for the StatefulSet.
# -- Optional PVC retention policy for the StatefulSet.

Otherwise it won't show up in the generated README

@rm3l rm3l Sep 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually all the files under workload/ could be flattened into the parent templates/ folder. Otherwise, it is confusing to see stateful.yaml in workload/ but not deployment.yaml.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants