-
Notifications
You must be signed in to change notification settings - Fork 68
🐛 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. |
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
VersionReleasetype 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
GetVersionwithGetVersionAndReleasethroughout 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
internal/operator-controller/catalogmetadata/compare/compare.go
Outdated
Show resolved
Hide resolved
| @@ -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?
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.
Hearing no other opinions, my vote is to leave as is. With this commit moving this function into a new package in the shared/utils space, hopefully future contributions will find this location to add new generic slice methods, and we can revisit the question again when there is more to be gained from pulling in a new dep.
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.
I'm of two minds on the subject. The reference is to what looks like a personal library, which normally garners a 'no' from me. But it has a mess of contributions, releases, and some kind of community, which relaxes that somewhat.
I'd prefer that this package didn't reuse the same name as a standard library (https://pkg.go.dev/slices).
But otherwise I'm fine with having a minimal utility library here.
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.
But it has a mess of contributions, releases, and some kind of community, which relaxes that somewhat.
The library has 20.5k stars which is really a lot and is a very good signal.
d352bc0 to
e8571b6
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #2273 +/- ##
==========================================
- Coverage 72.73% 71.39% -1.34%
==========================================
Files 89 92 +3
Lines 8747 7052 -1695
==========================================
- Hits 6362 5035 -1327
+ Misses 1968 1601 -367
+ Partials 417 416 -1
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:
|
e8571b6 to
b398c34
Compare
| ) | ||
|
|
||
| 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?
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 here, but I do I kinda like bundle/versionsrelease.go as a pure implementation of the type without the baggage of the various kinds of things that we might source or derive a VersionRelease from.
internal/operator-controller/catalogmetadata/compare/compare.go
Outdated
Show resolved
Hide resolved
| // 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?
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 reason we don't have that right now is because declcfg.Bundle does not actually embed its own deprecation information. So we can't directly compare declcfg.Bundle along deprecation lines.
I suppose we could essentially combine ByVersionAndRelease and ByDeprecationFunc into a single comparison function, but:
- It still wouldn't be a method on
declcfg.Bundle - It would still require extra
declcfg.Deprecationmetadata to do the comparison.
internal/operator-controller/catalogmetadata/filter/bundle_predicates.go
Show resolved
Hide resolved
internal/operator-controller/catalogmetadata/filter/bundle_predicates.go
Show resolved
Hide resolved
|
This one seems related to the bug that @grokspawn has been looking on. |
b398c34 to
2cf7680
Compare
|
crd-diff is failing due to the change in the description of the I'm personally inclined to specifically override so that future description changes continue to be flagged as potentially breaking so that those changes get extra scrutiny. |
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.
/lgtm a few more functions could be documented.
| metadata (e.g., "1.0.0+20230101"). This ensures an exact match of both | ||
| the semver version and the release. If you specify a version without build | ||
| metadata (e.g., "1.0.0"), it will match all bundles with that version | ||
| regardless of their release information. |
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.
We'll need to update this once the bundle release version feature lands, since we will need to mention both approaches, including how one is preferred in future. Right now the bundle release version approach is to use [version]-[release] to express the attribute combo in a string (though the source of truth is always the discrete version and release fields in the olm.package property).
Perhaps this is better resolved in a doc where we can go into more depth?
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]>
2cf7680 to
72c3a34
Compare
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.
/lgtm
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: pedjak 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 |
| func NewLegacyRegistryV1VersionRelease(vStr string) (*VersionRelease, error) { | ||
| vers, err := bsemver.Parse(vStr) | ||
| if err != nil { | ||
| return nil, err |
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 is not back-compat. We should return a releaseless VersionRelease in this case.
…rove VersionRelease parsing This commit reverts the user-facing semantic changes to the ClusterExtension version field that were introduced to support exact version pinning with build metadata. The version field now ignores build metadata when matching versions, consistent with semver specification. Additionally, this commit modifies the VersionRelease parsing logic to be more tolerant of semver versions whose build metadata is not a valid release. When build metadata cannot be parsed as a release, the full version (including build metadata) is preserved in the Version field, with an empty Release field. Changes include: - Removed documentation about pinning to exact versions with build metadata - Removed exactVersionMatcher logic that enforced build metadata equality - Updated NewLegacyRegistryV1VersionRelease to tolerate non-release build metadata - Updated test expectations to reflect new behavior
|
New changes are detected. LGTM label has been removed. |
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
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| func compareErrors(err1 error, err2 error) int { | ||
| if err1 != nil && err2 == nil { | ||
| return 1 | ||
| return -1 |
Copilot
AI
Oct 23, 2025
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 comment on line 80 states 'The semantic is that errors are "less than" non-errors' but the implementation has been inverted from the original. The comment should be updated to match the new implementation or the implementation should be corrected to match the comment.
Copilot uses AI. Check for mistakes.
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
The bug this fixes was originally reported by Red Hat in https://issues.redhat.com/browse/OCPBUGS-60424
Reviewer Checklist