-
Notifications
You must be signed in to change notification settings - Fork 66
🐛 Add support for build metadata precedence in bundle version comparison #2273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
🐛 Add support for build metadata precedence in bundle version comparison #2273
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.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes bundle version comparison logic to properly handle registry+v1 bundles that use build metadata in their version strings. The implementation introduces a VersionRelease
type that treats build metadata as comparable/orderable release information for registry+v1 bundles (a semver spec violation that exists for backward compatibility). The fix ensures exact version+release matching for pinned versions and successor determination.
Key changes:
- Introduced
VersionRelease
type combining semver version with release metadata parsed from build metadata - Updated comparison and filtering logic to use exact version+release matching instead of semver-only matching
- Replaced
GetVersion
withGetVersionAndRelease
throughout the codebase
Reviewed Changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
File | Description |
---|---|
internal/shared/util/slices/slices.go | Added generic Map utility function |
internal/operator-controller/resolve/resolver.go | Updated interface to use VersionRelease instead of semver.Version |
internal/operator-controller/resolve/catalog.go | Updated to use new comparison functions and moved Map function to shared utilities |
internal/operator-controller/controllers/clusterextension_controller.go | Added conversion to legacy registry+v1 version format when creating bundle metadata |
internal/operator-controller/catalogmetadata/filter/successors_test.go | Added test case for exact version matching with build metadata |
internal/operator-controller/catalogmetadata/filter/successors.go | Implemented exact version+release matching for installed bundle comparison |
internal/operator-controller/catalogmetadata/filter/bundle_predicates_test.go | Updated test to use new InSemverRange function |
internal/operator-controller/catalogmetadata/filter/bundle_predicates.go | Replaced Masterminds semver with blang semver and added exact version matching |
internal/operator-controller/catalogmetadata/compare/compare_test.go | Added tests for NewVersionRange and updated existing tests for new comparison logic |
internal/operator-controller/catalogmetadata/compare/compare.go | Implemented NewVersionRange with exact build metadata matching and renamed ByVersion to ByVersionAndRelease |
internal/operator-controller/bundleutil/bundle_test.go | Added comprehensive tests for VersionRelease comparison logic |
internal/operator-controller/bundleutil/bundle.go | Introduced VersionRelease, Release types and legacy registry+v1 conversion logic |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
c2cd023
to
d352bc0
Compare
// then the returned function will match any version that matches the semver version, ignoring the | ||
// build metadata of matched versions. | ||
// | ||
// Otherwise, Masterminds semver constraints semantics are used to match versions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should not both libraries implement semver spec? would it be possible to use just single library?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main reason we have both is that they have different implementations of version ranges. OLMv0 used blang's version ranges for skipRange
semantics, so we need to continue using that for back-compat reasons.
However, blang's semver range semantics have some footguns and are not all that ergonomic. So we chose Masterminds range semantics for spec.source.catalog.version
in OLMv1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, for the explanation, perhaps you could add to the comment in the code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps instead of leaking that that the function uses Masterminds library under the hood, it would be more helpful to document actually what are all supported version range syntax?
@@ -0,0 +1,9 @@ | |||
package slices | |||
|
|||
func Map[I any, O any](in []I, f func(I) O) []O { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function is available in https://github.com/samber/lo/blob/master/slice.go#L26 - how about to use it instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not strongly opinionated. I do notice that that would be a new dependency to pull in to the project, so I could go either way.
Anyone else have opinions?
d352bc0
to
e8571b6
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #2273 +/- ##
==========================================
+ Coverage 72.73% 73.04% +0.30%
==========================================
Files 89 90 +1
Lines 8747 8829 +82
==========================================
+ Hits 6362 6449 +87
+ Misses 1968 1959 -9
- Partials 417 421 +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:
|
This change fixes an issue to ensure that operator-controller properly handles and compares registry+v1 bundle versions that include build metadata as specified in the semver version. The intention is that we only treat build metadata as a release value for registry+v1 bundles, which already have this precedent set. If/when operator-controller gains support for new bundle types, the intention is to avoid continuing the practice (and semver violation) of treating version build metadata as comparable/orderable. Key changes: - Introduce VersionRelease type combining semver version with release metadata - Update bundle comparison logic to consider build metadata when present - Add exact version matching for pinned versions with build metadata - Replace GetVersion with GetVersionAndRelease across the codebase - Ensure successors are determined based on exact version+release matching This is particularly important for registry+v1 bundles that encode release information in the build metadata field of their version strings. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
e8571b6
to
b398c34
Compare
slicesutil "github.com/operator-framework/operator-controller/internal/shared/util/slices" | ||
) | ||
|
||
func NewLegacyRegistryV1VersionRelease(vStr string) (*VersionRelease, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add the docs.
Release Release | ||
} | ||
|
||
func (vr *VersionRelease) Compare(other VersionRelease) int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please document
|
||
type Release []bsemver.PRVersion | ||
|
||
func (r Release) Compare(other Release) int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func (r Release) Compare(other Release) int { | |
func (r *Release) Compare(other Release) int { |
) | ||
|
||
func GetVersion(b declcfg.Bundle) (*bsemver.Version, error) { | ||
func GetVersionAndRelease(b declcfg.Bundle) (*bundle.VersionRelease, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense to move this function to the new bundle/versionsrelease.go
file?
wantErr: true, | ||
}, | ||
{ | ||
name: "invalid release", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we give here more details why the given release is invalid?
// then the returned function will match any version that matches the semver version, ignoring the | ||
// build metadata of matched versions. | ||
// | ||
// Otherwise, Masterminds semver constraints semantics are used to match versions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps instead of leaking that that the function uses Masterminds library under the hood, it would be more helpful to document actually what are all supported version range syntax?
// ByVersionAndRelease is a comparison function that compares bundles by | ||
// version and release. Bundles with lower versions/releases are | ||
// considered less than bundles with higher versions/releases. | ||
func ByVersionAndRelease(b1, b2 declcfg.Bundle) int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: how about that we implement Compare
method on declcfg.Bundle
instead?
) | ||
|
||
func InMastermindsSemverRange(semverRange *mmsemver.Constraints) filter.Predicate[declcfg.Bundle] { | ||
func ExactVersionRelease(expect bundle.VersionRelease) filter.Predicate[declcfg.Bundle] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please document
} | ||
} | ||
|
||
func InSemverRange(versionRange bsemver.Range) filter.Predicate[declcfg.Bundle] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please document
Description
This change fixes an issue to ensure that operator-controller properly handles and compares registry+v1 bundle versions that include build metadata as specified in the semver version.
The intention is that we only treat build metadata as a release value for registry+v1 bundles, which already have this precedent set. If/when operator-controller gains support for new bundle types, the intention is to avoid continuing the practice (and semver violation) of treating version build metadata as comparable/orderable.
Key changes:
This is particularly important for registry+v1 bundles that encode release information in the build metadata field of their version strings.
🤖 Generated with Claude Code
Reviewer Checklist