Skip to content

docs(api): separate the healthCheckExprs failure modes - #4387

Merged
Aleksei Sviridkin (lexfrei) merged 1 commit into
mainfrom
docs/healthcheckexprs-failure-modes
Sep 23, 2026
Merged

Aleksei Sviridkin (lexfrei) merged 1 commit into
mainfrom
docs/healthcheckexprs-failure-modes

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does

The healthCheckExprs field doc said any bad expression makes the HelmRelease hang until its timeout. That is true for some mistakes and wrong for others, and the text ships in the CRDs, so kubectl explain sends people to the wrong place.

The doc now lists the cases separately, checked against the controller versions this repo installs (helm-controller v1.5.0, fluxcd/pkg runtime v0.100.2, Helm v4.1.1). An expression that does not parse, an empty current, or a duplicate group and kind stall the release right away with reason InvalidCELExpression, and no Helm action runs. An expression that errors on the object keeps the wait polling until the timeout with the CEL error in the message. A current expression that evaluates but never turns true also runs the timeout out, with no error to point at it. A wrong group or kind leaves the expressions unused.

Two details go against the issue text. Reading status before the CR's controller writes one errors even inside has(), as the issue says, but the object is only Unknown on that poll, and the wait still succeeds once a status shows up. A CRD that is not installed does not hang the wait: Helm fails to build the manifest and the action fails before any wait starts.

Doc comments and the regenerated CRD YAML only, no behaviour change.

Closes #4154

Screenshots

No UI change.

Downstream repositories

Release note

docs(api): describe each healthCheckExprs failure mode separately in the ApplicationDefinition and PackageSource field docs.

Summary by CodeRabbit

  • Documentation
    • Expanded the health-check expression guidance to explain how invalid or duplicate expressions, evaluation errors, expressions that remain false, unmatched resource types, and missing CRDs affect Helm releases.
    • Clarified that health-check expressions are not evaluated when Helm action waiting is disabled.

The field doc filed every mistake under one outcome, a HelmRelease
that hangs until its timeout. helm-controller treats them differently.
An expression that does not parse is rejected before any Helm action
and stalls the release at once, with a named reason. One that parses
but errors on the object keeps the wait polling with the CEL error
attached, and a current expression that evaluates cleanly but never
turns true runs the wait out with no error at all. A read of status
errors until the CR's controller writes one, even inside has(), but
the wait survives it. A wrong group or kind silently falls back to
the built-in readiness rules, and a CR whose CRD is missing fails the
Helm action before the wait starts.

The text ships in the CRDs and is what kubectl explain shows, so a
reader who cannot check it against the controller source was sent
to the wrong place for the parse error and the missing CRD.

Assisted-by: LLM
Signed-off-by: Aleksei Sviridkin <[email protected]>
@coderabbitai

coderabbitai Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: cozystack/cozystack/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 9045070b-ebc1-4a13-b40e-e28aeb65f34d

📥 Commits

Reviewing files that changed from the base of the PR and between a759190 and 65a038c.

📒 Files selected for processing (4)
  • api/v1alpha1/applicationdefinitions_types.go
  • api/v1alpha1/packagesource_types.go
  • internal/crdinstall/manifests/cozystack.io_packagesources.yaml
  • packages/system/application-definition-crd/definition/cozystack.io_applicationdefinitions.yaml

Included review availability: Your plan provides up to 8 included reviews per hour; 4 remain after this review.


📝 Walkthrough

Walkthrough

The HealthCheckExprs comments and CRD schema descriptions now explain distinct outcomes for invalid expressions, evaluation errors, expressions that remain false, unmatched group/kind entries, and missing CRDs.

Changes

Health-check expression documentation

Layer / File(s) Summary
Document health-check outcomes
api/v1alpha1/applicationdefinitions_types.go, api/v1alpha1/packagesource_types.go, internal/crdinstall/manifests/cozystack.io_packagesources.yaml, packages/system/application-definition-crd/definition/cozystack.io_applicationdefinitions.yaml
Expanded the API comments and CRD schema descriptions to distinguish validation failures, evaluation errors, expressions that remain false, unmatched group/kind entries, and missing CRDs.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Other

Suggested reviewers: myasnikovdaniil

Fixed issue severity: <fixed_issue_severity>Low</fixed_issue_severity>

Merge Risk: ⚪ Minimal · up to 65a03

This documentation-only change is ready to merge; the reviewed API comments and generated CRDs consistently describe the relevant health-check caveats.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The documentation distinguishes syntax failures from evaluation errors as #4154 requests. It states that syntax failures stall with InvalidCELExpression before a Helm action, and that evaluation err… Update the healthCheckExprs documentation in the API comments and both CRD descriptions to match #4154's stated missing-CRD behavior, or resolve that requirement in the linked issue before treating this documentation change as complete.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the documentation change and its focus on separating healthCheckExprs failure modes.
Out of Scope Changes check ✅ Passed All changed files update healthCheckExprs documentation or its CRD copies. The added details about empty or duplicate expressions, unmatched group/kind entries, and wait-disabled behavior clarify th…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Full details: Linked Issues check

Explanation

The documentation distinguishes syntax failures from evaluation errors as #4154 requests. It states that syntax failures stall with InvalidCELExpression before a Helm action, and that evaluation errors continue until timeout with the CEL error in the message. However, #4154 says a missing CRD also takes the wait-to-timeout path. The changed documentation instead says a missing CRD fails the Helm action before the wait.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added area/api Issues or PRs related to the cozystack-api aggregated API server kind/documentation Categorizes issue or PR as related to documentation size/M This PR changes 30-99 lines, ignoring generated files labels Sep 22, 2026
@lexfrei
Aleksei Sviridkin (lexfrei) marked this pull request as ready for review September 22, 2026 21:30

@IvanHunters IvanHunters left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Verdict

LGTM with non-blocking notes

Every claim in the new list holds against the helm-controller v1.5.0 this repo installs, and both CRDs regenerate byte-identical. The paragraph left standing underneath the list now contradicts its first bullet.

Findings

  • [MINOR] api/v1alpha1/applicationdefinitions_types.go:123, the retained disable-wait paragraph re-merges the modes the list separated
  • [MINOR] api/v1alpha1/applicationdefinitions_types.go:102, the shipped text names no version for the behaviour it asserts
  • [MINOR] api/v1alpha1/applicationdefinitions_types.go:118, the over-match direction is missing

Caveats

The six claims were run rather than read, against fluxcd/pkg runtime v0.100.2. A parse error, an empty current, and two entries differing only in apiVersion all fail at construction. A misspelled field, a non-boolean result, and has(status.x) against an object with no status at all each raise an eval error that cli-utils statusreaders/common.go:181-186 turns into Unknown carrying that error. A present status: {} makes has() come out false cleanly, and a clean-but-false current gives InProgress. ssa v0.67.1 manager_wait.go:133-148 and :172-181 confirm that neither state is terminal, that FailFast fires only on Failed, and that the error rides the timeout message only when there is one.

controller-gen v0.16.4 over ./api/... reproduced all 25 CRD files byte-identical to what is committed, so neither manifest is hand-edited and none is missing. Only that step ran: the full hack/update-codegen.sh does not execute in a review checkout, so its client-gen half is unverified here.

With every description stripped, base and head are identical on both CRDs, so no field, enum or validation rule moved. The chart renders and kubeconform -strict accepts both manifests.

One scoping note the text doesn't carry. waitStrategy: legacy routes to helm's own waiter (internal/action/client.go:68-69), which never sees the CEL readers, so bullets 2 through 4 describe the poller path only. The sibling WaitStrategy doc says as much and cozystack defaults to poller when expressions are set, but kubectl explain on this field alone does not.

// kstatus rules instead.
// A CR whose CRD is not installed fails the Helm action before any wait,
// whatever these expressions say.
// Upstream evaluates these only when the Helm action itself has wait

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[MINOR] the retained disable-wait paragraph re-merges the modes the list separated

"makes them a silent no-op whatever waitStrategy says ... with no error or warning" is not true of the bullet-1 class. In helm-controller v1.5.0 cel.NewStatusReader runs at internal/controller/helmrelease_controller.go:202, above reconcileChartTemplate (213) and reconcileRelease (217), while DisableWait is read later in the action config at internal/action/wait.go:51, reached from internal/action/install.go:92. With the annotation set, a non-parsing expression, an empty current or a duplicate group+kind still stalls the release at Ready=False / Stalled=True with reason InvalidCELExpression and a Warning Event, and helm never applies the CR. Scope the sentence to evaluation and note the first bullet still applies, since that check runs before any Helm action.

// that the CEL compiles or that the referenced apiVersion/kind CRD is
// installed; a bad expression or a not-yet-installed CRD makes the
// HelmRelease hang until its timeout (the backstop).
// as soon as helm applies it. OpenAPI validates only the struct shape, so

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[MINOR] the shipped text names no version for the behaviour it asserts

The PR body pins the claims to helm-controller v1.5.0, fluxcd/pkg runtime v0.100.2 and Helm v4.1.1. The comment that ships into the CRD and into kubectl explain names none, so a flux bump turns it into a description of a version nobody runs, with nothing to flag it. That is not hypothetical here: v1.5.0 exists only in the vendored render (packages/core/flux-aio/manifests/fluxcd.yaml:8097), while the bundle it comes from asks for version: "latest" (packages/core/flux-aio/flux-aio.cue:8), so a regeneration can move it without touching this file. The repo already stamps this kind of claim, at packages/apps/postgres/values.yaml:170 and packages/system/postgres-rd/cozyrds/postgres.yaml:7; one clause on the "mistakes surface in helm-controller" line would carry it. Same for api/v1alpha1/packagesource_types.go:158.

// such as a comparison against the wrong value, leaves the CR
// InProgress, and the Helm action waits out its timeout with no CEL
// error to point at the expression.
// - A group or kind that does not match the CR the chart renders leaves

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[MINOR] the over-match direction is missing

The list covers a group/kind matching nothing, not one matching too much. Spec-defined readers are prepended ahead of the built-ins (helmrelease_controller.go:1055-1057, [email protected] polling/polling.go:29 before :32) and statusReaderForGroupKind returns the first reader supporting the kind (polling/engine/engine.go:242-249), so an entry for apps/v1 Deployment replaces kstatus's Deployment rules for every Deployment in the release.

@lexfrei
Aleksei Sviridkin (lexfrei) merged commit ce35da4 into main Sep 23, 2026
87 of 88 checks passed
@lexfrei
Aleksei Sviridkin (lexfrei) deleted the docs/healthcheckexprs-failure-modes branch September 23, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api Issues or PRs related to the cozystack-api aggregated API server kind/documentation Categorizes issue or PR as related to documentation size/M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

healthCheckExprs field docs merge three failure modes into one clause, and two of them behave oppositely

2 participants