✨ Add support for parsing and persisting explicit pkg.Release field#2543
✨ Add support for parsing and persisting explicit pkg.Release field#2543rashmigottipati wants to merge 4 commits intooperator-framework:mainfrom
Conversation
✅ Deploy Preview for olmv1 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Pull request overview
This PR introduces an alpha feature gate to allow OLMv1 upgrade resolution to treat “re-released” bundles (same semver, higher release/build value like 2.0.0+1 -> 2.0.0+2) as valid successors when explicitly enabled.
Changes:
- Added
ReleaseVersionPriorityfeature gate (Alpha, default disabled). - Added
SameVersionHigherRelease()predicate and integrated it intoSuccessorsOf()behind the feature gate. - Added unit tests for
SameVersionHigherRelease()and forSuccessorsOf()with the gate disabled.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/operator-controller/features/features.go | Defines the new ReleaseVersionPriority feature gate and its spec. |
| internal/operator-controller/catalogmetadata/filter/successors.go | Conditionally expands successor matching to include same-version/higher-release bundles when gated on. |
| internal/operator-controller/catalogmetadata/filter/bundle_predicates.go | Adds the SameVersionHigherRelease() predicate. |
| internal/operator-controller/catalogmetadata/filter/bundle_predicates_test.go | Adds predicate unit tests including edge cases. |
| internal/operator-controller/catalogmetadata/filter/successors_test.go | Adds a regression test to ensure default (gate-off) behavior does not accept higher-release bundles. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #2543 +/- ##
==========================================
+ Coverage 68.92% 69.00% +0.07%
==========================================
Files 141 141
Lines 10005 10078 +73
==========================================
+ Hits 6896 6954 +58
- Misses 2594 2605 +11
- Partials 515 519 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
If I understand this correctly, it looks like this introduces the new behavior that an explicit upgrade edge doesn't actually have to exist in the catalog to upgrade to a bundle that has the same version and a higher release. Is that the intent? (If so let's make that clear in the PR description). Is it also the intent that we'll inherit the upgrade edges of the first release of the version? |
|
#2273 makes the claim that future bundle types will drop this approach, not that registry+v1 bundles should. So that's my bad. |
Sadly, we have to rely on the presence of existing graph edges or we break assumptions users have with the registry+v1 bundle format, coming from v0. So even though we have the ability to prefer version+release over version, since replaces/skips use named bundles instead of bundle versions we have to support the older behavior. |
That would be a regression of a bug fix that #2273 made though, right?
Yeah, agreed. I reached the same conclusion after thinking about this more. So if I understand correctly now:
So the change we need now is "look for |
5681488 to
8dcab49
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Adjusted my comments. I missed the part of the #2273 description when it said that we wouldn't divert from semver ordering for any new bundle formats. |
a2e5062 to
1e9cded
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
a833002 to
3b933d4
Compare
3b933d4 to
d13ce71
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
pedjak
left a comment
There was a problem hiding this comment.
Deep Review: Roundtrip Correctness and Ungated API Change
The core design (separating release from version, feature-gating the new parsing path) is sound. The CRD field documentation, validation regex, and deep-copy generation all look correct.
However, I traced the full data lifecycle through all paths (resolve → MetadataFor → annotations → GetRevisionStates → SuccessorsOf → ExactVersionRelease) and found two issues that need attention before merge:
-
Ungated Version field change — The
MetadataForsignature change strips build metadata from theVersionfield for all users, not just those withBundleReleaseSupportenabled. Standard CRD users lose release information entirely (thereleasefield is pruned by the API server). -
Roundtrip correctness bug during controller upgrade — Writing
BundleReleaseKeyunconditionally creates a nil-vs-empty-string Release ambiguity that causesExactVersionReleaseto fail matching the installed bundle against itself in the catalog.
Both issues and suggested fixes are detailed in the inline comments below.
Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
0601331 to
3af1ee4
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
3af1ee4 to
8644489
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
d7d5091 to
f1985dc
Compare
| // +optional | ||
| // <opcon:experimental> | ||
| // +kubebuilder:validation:XValidation:rule="self.matches(\"^$|^(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\\\\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*$\")",message="release must be empty or consist of dot-separated identifiers (numeric without leading zeros, or alphanumeric)" | ||
| Release *string `json:"release,omitempty"` |
There was a problem hiding this comment.
I was planning to do this in a follow-up PR, because I think it ultimately should be based on op-reg Release type instead of op-con Release type.
This is neither.
Do we have any concern if a later PR makes this explicitly declcfg.Release type?
Please align the type+validation with api and my follow-on PR in operator-registry.
There was a problem hiding this comment.
Unless there is meaning between nil and empty, we generally prefer to do
| Release *string `json:"release,omitempty"` | |
| Release string `json:"release,omitzero"` |
I don't think there's any difference between these cases for this type. If the release is empty or omitted then it equates to no release value.
| var rel bundle.Release | ||
| if releaseStr == "" { | ||
| // Explicit empty release: use empty slice (not nil) | ||
| rel = bundle.Release([]bsemver.PRVersion{}) |
There was a problem hiding this comment.
This goes against bundle.NewRelease handling, which returns nil if given an empty string.
I've also aligned with that approach here.
| return nil, fmt.Errorf("error unmarshalling package property: %w", err) | ||
| } | ||
|
|
||
| // Check if release field is explicitly present in JSON (even if empty). |
There was a problem hiding this comment.
Since Package.Release is defined in operator-registry as string with omitzero, isn't the salient test whether the unmarshaled Package at 28 has a non-empty Release or not?
If we are worried about the scenario where the feature is disabled, but a bundle with a release version is in the catalog, then we can explicitly clear the field.
Is there another scenario that's important?
| Name: bundleName, | ||
| Version: vr.Version.String(), | ||
| } | ||
| if vr.Release != nil { |
There was a problem hiding this comment.
This looks like we could skip it if we we move to omitempty instead of a pointer with omitzero, and furthermore could be omitted if we're using an explicit type instead of a string.
(I don't think we can use an explicit type yet, unless the bundle.Release supports marshaling/unmarshaling.)
| Version: rev.Annotations[labels.BundleVersionKey], | ||
| }, | ||
| } | ||
| // Only set Release if the annotation key exists (to distinguish "not set" from "explicitly empty") |
There was a problem hiding this comment.
I don't think these are different cases. The value is only salient if it exists and is non-empty. Otherwise, there is no effective release.
Description
Summary
Adds support for parsing the explicit
pkg.Releasefield from bundle metadata and persisting it through cluster storage (roundtripping). This is gated by the newBundleReleaseSupportalpha feature gate (disabled by default).Changes
BundleReleaseSupportalpha feature gate (disabled by default)Releasefield toBundleMetadataCRD typeBundleReleaseKeylabel constant for annotation storagebundleutil.parseVersionRelease()to: Parse explicitpkg.Releasewhen feature gate enabled and field present. Fall back to legacy registry+v1 behavior (release in build metadata) otherwisebundleutil.MetadataFor()to serialize release value fromVersionReleaseFeature Gate Behavior
When enabled:
pkg.Releasefield: release parsed separately, build metadata preserved for proper semver purposeWhen feature gate disabled:
pkg.Releasefield ignoredReviewer Checklist
Link to Github Issue: #2495
Epic: #2479