Repository navigation
fix(tenant): render the chart without the platform's injected values - #3636
Merged
Merged
Conversation
`helm lint packages/apps/tenant` fails, and two of its three errors are
the chart's own.
`templates/keycloakgroups.yaml` reads `index .Values._cluster
"oidc-enabled"`. `_cluster` is injected by the platform, so it is absent
whenever the chart is rendered on its own, and `index` on a nil map is a
hard error: `index of untyped nil`. The chart cannot be rendered or
linted outside a cluster at all.
The idiom the neighbouring charts use for the same lookup does not
rescue this on its own, which is worth stating because it looks like it
does. `(index .Values._cluster "x") | default "y"` still errors: `index`
evaluates first and fails on the nil map, so `default` never sees a
result to substitute; it only ever covered a key missing from a map that
exists.
The spelling alone does not decide whether a chart breaks, though.
`packages/system/cozystack-basics` uses it and lints clean, because line
1 of its values.yaml is `_cluster: {}`, which makes the map non-nil
before `index` runs. So a chart is broken only when it neither declares
the empty map nor guards at the use site. Guarding at the use site is
preferred here because it makes the template correct whatever
values.yaml contains, which is what lets the chart render standalone;
and `_cluster` is platform-internal, while this chart's values.yaml,
schema and README are generated together from
api/apps/v1alpha1/tenant/types.go as user-facing output.
The guard has to sit on the map rather than on the value it returns,
hence `index (.Values._cluster | default dict) "oidc-enabled"`.
That is behaviour-preserving rather than merely quieter. With `_cluster`
present, `| default dict` returns it untouched and the lookup is what it
was. With it absent the lookup is nil, the `eq` below is false, and the
block stays unrendered, which is what an unconfigured tenant should
produce. Rendered both ways before and after, with
`--api-versions v1.edp.epam.com/v1` so the capability-gated block
actually executes, the output is identical byte for byte: four
KeycloakRealmGroups when `oidc-enabled` is `"true"`, none when it is
`"false"`. Rendering with no values at all goes from a hard error to a
clean render with no groups.
`Chart.yaml` also does not declare `cozy-lib`, which is present as a
symlink under `charts/`, so lint reports missing chart metadata. Declare
it the way `packages/apps/qdrant` does, that being the one chart in the
tree that declares it and does not carry this error. Rendering is
unchanged by the declaration, checked the same way.
`tests/keycloakgroups_oidc_test.yaml` pins all three branches of the
gate: four realm groups when `oidc-enabled` is `"true"`, none when it is
`"false"`, and none when the platform injected no `_cluster` at all.
That third case is the one the guard exists for, and it needs no mock,
because `_cluster` is absent from values.yaml and so "not injected" is
simply the chart's own default state. Against the unguarded template the
suite fails with `index of untyped nil`; the chart's other seven suites
pass identically either way, which is what left the change uncovered.
The third error, `invalid icon URL '/logos/tenant.svg'`, is deliberately
left. Lint wants a URL with a scheme, and all 31 charts in the tree that
carry an icon use a relative path, none an absolute one. Changing this
one would make it the only chart with a different convention, and
choosing the URL a relative path should become is a decision about where
those assets are served from, not about lint.
Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
Aleksei Sviridkin (lexfrei)
requested review from
IvanHunters,
myasnikovdaniil and
scooby87
as code owners
August 7, 2026 23:55
Contributor
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe tenant chart now includes the local ChangesTenant OIDC rendering
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Aug 8, 2026
1 of 11 tasks
Aleksei Sviridkin (lexfrei)
added a commit
that referenced
this pull request
Aug 14, 2026
…ason (#3661) ## What this PR does Two tests in `packages/apps/tenant/tests/vmo_webhook_dependson_test.yaml` say the seaweedfs and gateway HelmReleases deliberately carry no operator gate, and assert that with `notExists: spec.dependsOn` and nothing else. A bare absence assert also passes when the template renders no document at all, so both stayed green with those two releases switched off entirely. With `seaweedfs: false, gateway: false` the suite still reported 5 of 5 passing; pinning `metadata.name` next to the absence turns the same run into 2 failures. An earlier check on these asserts injected a `dependsOn` and watched them redden. That proves they catch an added gate, which is the other direction. For a negative assert the direction that matters is the document going away, and that one was never covered. Pairing `equal: metadata.name` with the absence is not a new idiom introduced here. `no_upgrade_force_test.yaml`, in the same directory, already anchors all seven of its releases that way, and this brings the last two suites in the chart into line with it. Both suite headers also carried a reason for their `templates:` list that has expired: that rendering the whole chart fails because `keycloakgroups.yaml` indexes `.Values._cluster` unguarded. #3636 added the guard, so a no-values render of the chart now succeeds. The list is still load-bearing, for the reason `no_upgrade_force_test.yaml` already records — it keeps an unrelated template breaking out of this suite's result. Checked by adding a nil dereference to a template neither suite asserts on: both suites stay green with their lists and error without them. ### Screenshots Not a UI change. ### Downstream repositories Walked the trigger map against the diff. It touches two files, both under `packages/apps/tenant/tests/`, and no chart, template, values file or tooling. Nothing in the map keys on test files. - [x] No downstream repository is affected by this change - [ ] [cozystack/website](https://github.com/cozystack/website) - follow-up: - [ ] [cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack) - follow-up: - [ ] [cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack) - follow-up: - [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up: - [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up: - [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) - follow-up: - [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) - follow-up: - [ ] [cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server) - follow-up: - [ ] [cozystack/external-apps-example](https://github.com/cozystack/external-apps-example) - follow-up: - [ ] [cozystack/examples](https://github.com/cozystack/examples) - follow-up: ### Release note ```release-note NONE ```
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does
helm lint packages/apps/tenantfails on main with three errors. This removes two of the three; the branch name notwithstanding, lint still exits 1 afterwards on the third, which is a repository-wide convention question rather than a defect in this chart.The chart cannot be rendered outside a cluster at all.
templates/keycloakgroups.yamlreadsindex .Values._cluster "oidc-enabled", and_clusteris injected by the platform, so it is absent whenever the chart is rendered on its own.indexon a nil map is a hard error, not an empty result, so bothhelm lintand a plainhelm templatedie on line 1.The idiom the neighbouring charts use for the same lookup does not rescue this on its own, which is worth stating because it looks exactly like a guard.
(index .Values._cluster "x") | default "y"still fails:indexis evaluated first and errors on the nil map, sodefaultnever receives a result to substitute; it only ever covered a key missing from a map that exists.The spelling alone does not decide whether a chart breaks, though.
packages/system/cozystack-basicsuses it and lints clean, because line 1 of itsvalues.yamlis_cluster: {}, which makes the map non-nil beforeindexruns. A chart is broken only when it neither declares the empty map nor guards at the use site, and a lint sweep across the catalog found 27 in that state. Guarding at the use site is the choice here because it makes the template correct whatevervalues.yamlcontains, and because_clusteris platform-internal while this chart'svalues.yaml, schema and README are generated together fromapi/apps/v1alpha1/tenant/types.goas user-facing output. The guard has to sit on the map rather than on the value it returns:This is behaviour-preserving, and that is checked rather than asserted. With
_clusterpresent,| default dictreturns it untouched and the lookup is what it was; with it absent the lookup is nil, theeqbelow is false, and the block stays unrendered, which is what an unconfigured tenant should produce. Rendering before and after gives byte-identical output:_cluster.oidc-enabled: "true"_cluster.oidc-enabled: "false"Worth recording how that comparison has to be run, because the obvious way proves nothing. The KeycloakRealmGroup block sits behind
.Capabilities.APIVersions.Has "v1.edp.epam.com/v1", which is false under a plainhelm template, so a first pass rendered the same output in both the enabled and disabled cases, and a diff of those two would have compared one empty result against another. The renders above pass--api-versions v1.edp.epam.com/v1so the guarded branch actually executes. Anyone proving neutrality on a capability-gated template needs that flag or the proof is vacuous.Chart.yamldoes not declarecozy-lib, which is present as a symlink undercharts/, so lint reports missing chart metadata. It is declared the waypackages/apps/qdrantdoes it, that being the one chart in the tree which declares it and does not carry this error. Rendering is unchanged by the declaration, checked the same way as above.Two things that could plausibly have broken and did not, checked rather than assumed: rendering from a packaged
helm packageartifact is byte-identical, and thecharts/cozy-libsymlink is still expanded into the tgz with the dependency declared. And neitherhack/update-crd.shnor thefix-chartstarget inpackages/apps/Makefilereads thedependencies:block, so nothing needs regenerating.The icon error is left in place on purpose, and the relative path is load-bearing.
helm lintwants a URL with a scheme, and/logos/tenant.svghas none. Buthack/update-crd.shconsumes exactly this form: it rewrites a leading slash to./, then reads that file off disk and base64-encodes it into.spec.dashboard.iconof the generated ApplicationDefinition.packages/apps/tenant/logos/tenant.svgis that file. Give the chart a URL with a scheme and the generator's[[ ! -f "$ICON_PATH" ]]check no longer finds anything to encode. So the relative form is a requirement of the pipeline rather than a stylistic convention, all 31 icon-carrying charts use it, and satisfying helm lint here means changing the generator, not the charts. That is a repository-wide decision and not this PR's.tests/keycloakgroups_oidc_test.yamlpins the gate in all three directions: four realm groups whenoidc-enabledis"true", none when it is"false", and none when the platform injected no_clusterat all. The last case is the one the guard exists for, and it needs no mocking, since_clusteris absent fromvalues.yamland "not injected" is just the chart's default state. Against the unguarded template that suite fails withindex of untyped nil. The chart's other seven suites pass identically with and without the fix, which is precisely why the change needed its own.Two limits of the new suite, stated rather than left to be found. It pins how many documents render, not which: renaming the four groups or breaking a
realmRefwould pass. And the template's second gate,.Capabilities.APIVersions.Has "v1.edp.epam.com/v1", is enabled for the whole suite, so no case covers its absence. Both are worth closing on the next touch of this file; neither weakens what the suite does pin, which is that the chart renders at all when the platform injected nothing.A trap for anyone reproducing this by hand: the gate compares against the string
"true", so--set _cluster.oidc-enabled=truepasses a YAML boolean and renders nothing, while--set-stringrenders the four groups. The platform writes a genuine string, and it survives the round-trip through a Secret becausetoYamlquotes it. Note also that this chart's helpers reject a release name that does not begin withtenant-, which will silently render nothing for either form.One note in case a future change teaches the linter to inject the platform's values, which would hide this class of error without fixing it: the guard is still worth having, because it is what lets
helm template packages/apps/tenantsucceed with no values file at all. A chart that renders standalone can be inspected, diffed and unit-tested without reproducing the platform around it.Screenshots
Downstream repositories
Release note
Summary by CodeRabbit
New Features
Bug Fixes
Tests