Skip to content

proposal: ApplicationDefinition multi-version conversion#6

Open
kvaps wants to merge 1 commit intomainfrom
proposal/application-definition-versioning
Open

proposal: ApplicationDefinition multi-version conversion#6
kvaps wants to merge 1 commit intomainfrom
proposal/application-definition-versioning

Conversation

@kvaps
Copy link
Copy Markdown
Member

@kvaps kvaps commented Apr 30, 2026

Summary

Draft design proposal for versioning the API surface of
ApplicationDefinition while keeping values.yaml as the storage form.

  • Per-version ApplicationSchema files under packages/apps/<name>/api/
  • Conversion expressed as a pair of go-template snippets (to / from)
    for non-storage versions only
  • Migration controller normalizes existing HelmReleases to the current
    storage version in the background
  • Chart-side guard turns version mismatches into human-readable errors
  • New cozyschema build tool generates ApplicationDefinition,
    JSON schema, chart annotations, and the guard include from the
    per-version sources

UI metadata placement is deliberately left as an open question; one
suggestion is a separate ApplicationView resource bound to a schema
by name and version. To be picked up by a follow-up proposal.

Test plan

This is a design-only change. No code lands with this PR.

  • Reviewed by core maintainers
  • Open questions resolved or explicitly deferred
  • Alternatives considered are accurate

Summary by CodeRabbit

  • Documentation
    • Added design documentation for a multi-version application definition conversion system, including API version schema definitions with conversion templates, automated migration controller behavior, value storage and projection mechanics, version compatibility during upgrades and rollbacks, build and testing specifications, schema guard validation, and security constraints for template usage.

Introduces a draft design for versioning the API surface of
ApplicationDefinitions while keeping values.yaml as the storage
form. Defines per-version ApplicationSchema files, a pair of
go-template conversion snippets (to/from storage), a migration
controller for self-recovery, and a chart-side version guard.

Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

📝 Walkthrough

Walkthrough

Introduces a design proposal document detailing an ApplicationDefinition multi-version conversion strategy. The approach uses values.yaml as the storage format with additional API versions defined through ApplicationSchema resources containing conversion templates, a migration controller for version healing, build tooling integration, and compatibility/testing specifications.

Changes

Cohort / File(s) Summary
Application Definition Versioning Design
design-proposals/application-definition-versioning/README.md
New documentation introducing a multi-version conversion approach for ApplicationDefinition with storage-form values.yaml, API version projections via conversion templates, migration controller healing, cozyschema build integration, upgrade/rollback compatibility rules, and security constraints for template functions.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐰 A versioning scheme takes shape today,
With templates dancing in the fray,
Storage and schemas hand in hand,
Converting values across the land,
The docs are written, the plan is clear! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'proposal: ApplicationDefinition multi-version conversion' accurately summarizes the main objective of the PR: introducing a design proposal for handling multiple API versions of ApplicationDefinition through a conversion approach.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch proposal/application-definition-versioning

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
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

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

@kvaps kvaps marked this pull request as ready for review April 30, 2026 18:22
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a design proposal for multi-version conversion of ApplicationDefinition in Cozystack, enabling versioned API surfaces for values.yaml through Go-template-based conversions and a background migration controller. The review feedback highlights the need for more robust field access in conversion templates, explicit error handling for 'poison pill' resources in the migration controller, and a more flexible approach to consecutive storage version bumps to ensure long-term upgrade stability.

Comment on lines +134 to +135
replicas: {{ .replicas }}
maxConnections: {{ index .postgresql.parameters "max_connections" }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

While some parts of the example use default (e.g., line 137), lines 134 and 135 access fields directly. If .replicas is missing or .postgresql is nil, the template will either produce invalid YAML (replicas: <no value>) or fail with a rendering error. It is recommended to consistently use default or existence checks for all field accesses to ensure the conversion is robust against partial data.

if cv not in servedVersions:
emit Warning: ManualMigrationRequired
continue
valuesNew := apply(versions[cv].to, valuesOld)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The migration controller pseudo-code should explicitly define how to handle failures during the apply step. Since Go templates can encounter runtime errors (e.g., invalid syntax in generated YAML or logic errors), the controller needs a mechanism to handle 'poison pill' resources—such as logging the error and skipping the resource—to prevent a single failing conversion from stalling the entire migration process.

Comment on lines +288 to +289
in a row. Two consecutive storage bumps would require a transitive
conversion path that is not supported here.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The restriction against consecutive storage bumps creates a significant maintenance burden and upgrade risk. If the storage version is the 'hub', every time it is bumped, all existing legacy version templates must be updated to target the new hub. Without this, users skipping a Cozystack release would find their resources un-migratable. The design should consider if a transitive conversion mechanism (e.g., V1 -> V2 -> V3) is necessary for long-term stability.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
design-proposals/application-definition-versioning/README.md (4)

202-212: 💤 Low value

Add language specifier to pseudocode block.

The migration controller logic is clear, but the code block should specify a language.

📝 Suggested fix
-```
+```python
 for hr in helmreleases of this kind:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@design-proposals/application-definition-versioning/README.md` around lines
202 - 212, Add a language specifier to the fenced code block containing the
migration pseudocode (the block starting with "for hr in helmreleases of this
kind:") so the snippet is marked as a language (e.g., ```python) to enable
proper syntax highlighting; update the opening fence to include the chosen
language without altering the pseudocode lines such as "cv :=
hr.values._version", "if cv not in servedVersions", "valuesNew :=
apply(versions[cv].to, valuesOld)", and "patch(hr, valuesNew)".

170-192: 💤 Low value

Add language specifier to pseudocode block.

The conversion flow logic is sound (storage-as-hub pattern), but the code block should specify a language.

📝 Suggested fix
-```
+```python
 Write spec_X (any served X):
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@design-proposals/application-definition-versioning/README.md` around lines
170 - 192, The pseudocode block for the "Conversion flow" should explicitly
declare a language for syntax highlighting; update the fenced code block that
currently starts with ``` to include a language tag (e.g., ```python) so the
block containing the Write spec_X / Read as Y flow (references: spec_X,
values_X, versions[X].to, versions[Y].from, _version, values_storage,
HelmRelease) is fenced as a named language; do not alter the pseudocode
itself—only change the opening triple-backtick to include the language
specifier.

100-108: 💤 Low value

Add language specifier to code block.

The file layout is clear, but the fenced code block should specify a language for better rendering and tooling support.

📝 Suggested fix
-```
+```text
 packages/apps/<name>/
 ├── values.yaml                    # storage form, single source of truth
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@design-proposals/application-definition-versioning/README.md` around lines
100 - 108, The fenced code block showing the directory tree (the block that
begins with "packages/apps/<name>/" and lists values.yaml, api/v1alpha1.yaml,
v1.yaml, and templates/_cozystack-version.tpl) should include a language
specifier for proper rendering; update the opening fence from ``` to a specific
language hint such as ```text (or ```bash) in README.md so tooling and renderers
treat the block as plain text.

287-289: ⚡ Quick win

Consider enforcing the storage version bump constraint.

The constraint "A single Cozystack release should not bump storage version twice in a row" is critical for avoiding transitive conversion paths, but it's stated as a "should" without enforcement mechanism.

Consider whether cozyschema build or a CI check could enforce this by examining version history across releases, or at minimum, add this to the CI checks list (lines 251-260).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@design-proposals/application-definition-versioning/README.md` around lines
287 - 289, Add an automated enforcement of the "no two consecutive storage
version bumps" rule by implementing a check in the existing tooling and/or CI:
extend the command "cozyschema build" to inspect the repository's
release/version history (tags or stored schema versions) and detect if the most
recent release and the previous release both include storage version bumps,
failing with a clear error if so, and/or add a CI job (e.g.,
"check-storage-version-bumps") that runs this same check during PRs; update
documentation to reference the new check in the CI checks list and ensure the
check uses unique identifiers like storage version fields and release tags to
determine consecutive bumps.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@design-proposals/application-definition-versioning/README.md`:
- Around line 306-309: Add the missing legacyDefault field to the
ApplicationDefinition examples and schema outputs: update the ApplicationSchema
example (the block showing ApplicationDefinition structure) to include a brief
legacyDefault: <version> entry and reflect that same field in the cozyschema
build outputs section so readers can see where legacyDefault lives; reference
the ApplicationDefinition examples and the generated cozyschema output blocks to
ensure the field name matches exactly ("legacyDefault") and include a short
comment noting the open question if needed.

---

Nitpick comments:
In `@design-proposals/application-definition-versioning/README.md`:
- Around line 202-212: Add a language specifier to the fenced code block
containing the migration pseudocode (the block starting with "for hr in
helmreleases of this kind:") so the snippet is marked as a language (e.g.,
```python) to enable proper syntax highlighting; update the opening fence to
include the chosen language without altering the pseudocode lines such as "cv :=
hr.values._version", "if cv not in servedVersions", "valuesNew :=
apply(versions[cv].to, valuesOld)", and "patch(hr, valuesNew)".
- Around line 170-192: The pseudocode block for the "Conversion flow" should
explicitly declare a language for syntax highlighting; update the fenced code
block that currently starts with ``` to include a language tag (e.g., ```python)
so the block containing the Write spec_X / Read as Y flow (references: spec_X,
values_X, versions[X].to, versions[Y].from, _version, values_storage,
HelmRelease) is fenced as a named language; do not alter the pseudocode
itself—only change the opening triple-backtick to include the language
specifier.
- Around line 100-108: The fenced code block showing the directory tree (the
block that begins with "packages/apps/<name>/" and lists values.yaml,
api/v1alpha1.yaml, v1.yaml, and templates/_cozystack-version.tpl) should include
a language specifier for proper rendering; update the opening fence from ``` to
a specific language hint such as ```text (or ```bash) in README.md so tooling
and renderers treat the block as plain text.
- Around line 287-289: Add an automated enforcement of the "no two consecutive
storage version bumps" rule by implementing a check in the existing tooling
and/or CI: extend the command "cozyschema build" to inspect the repository's
release/version history (tags or stored schema versions) and detect if the most
recent release and the previous release both include storage version bumps,
failing with a clear error if so, and/or add a CI job (e.g.,
"check-storage-version-bumps") that runs this same check during PRs; update
documentation to reference the new check in the CI checks list and ensure the
check uses unique identifiers like storage version fields and release tags to
determine consecutive bumps.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 37d66c26-647e-45d0-8154-6ae87860b41a

📥 Commits

Reviewing files that changed from the base of the PR and between abb40d0 and 8556c88.

📒 Files selected for processing (1)
  • design-proposals/application-definition-versioning/README.md

Comment on lines +306 to +309
- Missing `_version` on a HelmRelease (legacy resource): the
`ApplicationDefinition` may declare a `legacyDefault: <version>`.
The api-server treats absent `_version` as that default on the
next read or migration.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Show legacyDefault in ApplicationSchema example.

The failure-handling section mentions legacyDefault as a field in ApplicationDefinition (line 307), but this field isn't shown in the ApplicationSchema example (lines 116-159) or in the cozyschema build outputs (lines 239-250).

Consider adding a brief example showing where legacyDefault appears in the ApplicationDefinition structure, even if it's deferred to an open question (line 367-368).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@design-proposals/application-definition-versioning/README.md` around lines
306 - 309, Add the missing legacyDefault field to the ApplicationDefinition
examples and schema outputs: update the ApplicationSchema example (the block
showing ApplicationDefinition structure) to include a brief legacyDefault:
<version> entry and reflect that same field in the cozyschema build outputs
section so readers can see where legacyDefault lives; reference the
ApplicationDefinition examples and the generated cozyschema output blocks to
ensure the field name matches exactly ("legacyDefault") and include a short
comment noting the open question if needed.

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.

1 participant