Skip to content

✨ Support explicit pkg.Release field with build metadata fallback for bundle comparison#2543

Open
rashmigottipati wants to merge 7 commits intooperator-framework:mainfrom
rashmigottipati:oprun-4277-implementation
Open

✨ Support explicit pkg.Release field with build metadata fallback for bundle comparison#2543
rashmigottipati wants to merge 7 commits intooperator-framework:mainfrom
rashmigottipati:oprun-4277-implementation

Conversation

@rashmigottipati
Copy link
Copy Markdown
Member

@rashmigottipati rashmigottipati commented Mar 6, 2026

Description

Summary

Implements hybrid bundle comparison that supports both registry+v1 bundles (build metadata) and new bundle formats (explicit pkg.Release field).

Uses Bundle.Compare() from operator-registry to read pkg.Release from olm.package property, falling back to build metadata parsing when comparison returns equal. This enables re-release upgrades (e.g., 1.0.0+11.0.0+2).

Changes

  • Added CompositeVersionComparison feature gate (alpha, disabled by default)
  • Updated ByVersionAndRelease() to use Bundle.Compare() with build metadata fallback
  • Updated SuccessorsOf() to include SameVersionHigherRelease predicate when feature gate enabled
  • Added comprehensive tests for both bundle formats

Feature Gate Behavior

Disabled (default): Backward compatible - uses build metadata only

Enabled: Hybrid approach

  • Tries Bundle.Compare() first (reads explicit pkg.Release)
  • Falls back to build metadata if equal
  • Allows same-version higher-release upgrades

Reviewer Checklist

  • API Go Documentation
  • Tests: Unit Tests
  • Comprehensive Commit Messages
  • Links to related GitHub Issue(s)

Link to Github Issue: #2495
Epic: #2479

Copilot AI review requested due to automatic review settings March 6, 2026 16:37
@openshift-ci openshift-ci bot requested review from joelanford and perdasilva March 6, 2026 16:37
@netlify
Copy link
Copy Markdown

netlify bot commented Mar 6, 2026

Deploy Preview for olmv1 ready!

Name Link
🔨 Latest commit a66d732
🔍 Latest deploy log https://app.netlify.com/projects/olmv1/deploys/69d00ee54f73cf00085ec4ba
😎 Deploy Preview https://deploy-preview-2543--olmv1.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@openshift-ci
Copy link
Copy Markdown

openshift-ci bot commented Mar 6, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign kevinrizza for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copy link
Copy Markdown
Contributor

Copilot AI left a 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 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 ReleaseVersionPriority feature gate (Alpha, default disabled).
  • Added SameVersionHigherRelease() predicate and integrated it into SuccessorsOf() behind the feature gate.
  • Added unit tests for SameVersionHigherRelease() and for SuccessorsOf() 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
Copy link
Copy Markdown

codecov bot commented Mar 6, 2026

Codecov Report

❌ Patch coverage is 83.33333% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.18%. Comparing base (985d23a) to head (a66d732).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...ator-controller/catalogmetadata/compare/compare.go 63.63% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2543      +/-   ##
==========================================
- Coverage   68.89%   63.18%   -5.71%     
==========================================
  Files         139      139              
  Lines        9910     9931      +21     
==========================================
- Hits         6827     6275     -552     
- Misses       2572     3157     +585     
+ Partials      511      499      -12     
Flag Coverage Δ
e2e 37.48% <12.50%> (-0.10%) ⬇️
experimental-e2e 11.09% <4.16%> (-41.11%) ⬇️
unit 53.55% <79.16%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI review requested due to automatic review settings March 6, 2026 17:34
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 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.

@joelanford
Copy link
Copy Markdown
Member

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?

const testPackageName = "test-package"

// Expected bundle version 2.0.0+1
expect, err := bundle.NewLegacyRegistryV1VersionRelease("2.0.0+1")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd suggest putting the expect value in the test case, and adding cases that start from different values. For example: from a version without a release.

Also related: do we need to add code that knows how to parse the new Release field of the olm.package property (around here:

vr, err := bundle.NewLegacyRegistryV1VersionRelease(pkg.Version)
)?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

iirc, @grokspawn's design called for a specific precedence when handling both release and build metadata that we will need to account for.

Comment on lines +38 to +40
// If release version priority is enabled, also consider bundles
// with the same semantic version but higher release as valid successors.
// This allows upgrades to re-released bundles (e.g., 2.0.0+1 -> 2.0.0+2).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What if the re-release version is already in the explicit upgrade graph? In that case, should we ignore it and let its explicit channel entry take precedence? That would preserve existing behavior.

func SameVersionHigherRelease(expect bundle.VersionRelease) filter.Predicate[declcfg.Bundle] {
return func(b declcfg.Bundle) bool {
actual, err := bundleutil.GetVersionAndRelease(b)
if err != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

could failing silently here lead to some hard to spot bugs?

@grokspawn
Copy link
Copy Markdown
Contributor

grokspawn commented Mar 9, 2026

We discussed earlier today. I think the first step is to essentially revert #2273 so that we're not attempting to interpret build metadata as release info anymore. Any catalogs built with tooling that supports release versioning will automagically propagate the build metadata into the CSV's spec.release field anyway, so regardless of whether the operator author used the old build metadata approach or the new spec.release approach, they would still have spec.release here.

The next step is to ensure that we're sorting successors using the CompositeVersion, which is easily performed if using the Bundle comparator during the sort.

This will prefer version+release over version.

#2273 makes the claim that future bundle types will drop this approach, not that registry+v1 bundles should. So that's my bad.
From the perspective of fulfilling handling precedents for registry+v1 bundles, we need to retain the ability to differentiate/order them by build metadata. :(

@grokspawn
Copy link
Copy Markdown
Contributor

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?

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.

@joelanford
Copy link
Copy Markdown
Member

I think the first step is to essentially revert #2273 so that we're not attempting to interpret build metadata as release info anymore.

That would be a regression of a bug fix that #2273 made though, right?

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.

Yeah, agreed. I reached the same conclusion after thinking about this more.

So if I understand correctly now:

  1. The existing code on main already honors the upgrade graph and orders "same version, different release" correctly when parsing from build metadata
  2. The existing code on main knows nothing about the new release field.

So the change we need now is "look for release in the olm.package property, and if present, prefer it over build metadata"?

Copilot AI review requested due to automatic review settings March 12, 2026 19:55
@rashmigottipati rashmigottipati force-pushed the oprun-4277-implementation branch from 5681488 to 8dcab49 Compare March 12, 2026 20:00
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 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.

// Legacy registry+v1 bundles embed the release value inside their versions as build metadata
// (in violation of the semver spec). If/when we add explicit release metadata to bundles and/or
// we support a new bundle format, we need to revisit the assumption that all bundles are
// registry+v1 and embed release in build metadata.
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

This error should wrap the underlying error with %w instead of formatting it with %v, so callers can unwrap/inspect it consistently (and it matches the %w usage elsewhere in this function).

Suggested change
return nil, fmt.Errorf("failed to get composite version for installed bundle %q: %w", installedBundle.Name, err)

Copilot uses AI. Check for mistakes.
Comment on lines +76 to +78
// Expected bundle version 2.0.0+1
expect, err := bundle.NewLegacyRegistryV1VersionRelease("2.0.0+1")
require.NoError(t, err)
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

SameVersionHigherRelease now takes a declcfg.CompositeVersion, but this test builds expect via bundle.NewLegacyRegistryV1VersionRelease(...) (type *bundle.VersionRelease) and passes *expect into SameVersionHigherRelease, which will not compile. Construct expect as a declcfg.CompositeVersion (e.g., by creating a declcfg.Bundle with the expected package property and calling CompositeVersion()), and remove the dependency on the internal bundle type here.

Copilot uses AI. Check for mistakes.
Comment on lines 11 to 18
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

resolve.Resolver / resolve.Func now return *declcfg.CompositeVersion instead of *bundle.VersionRelease. This change requires updating all resolver implementations and test fakes/mocks; for example, internal/operator-controller/controllers/clusterextension_controller_test.go still defines resolve.Func(...)(*declcfg.Bundle, *bundle.VersionRelease, ...), which will no longer compile. Please update those call sites to return *declcfg.CompositeVersion (and adjust any code that relied on AsLegacyRegistryV1Version()).

Copilot uses AI. Check for mistakes.
Comment on lines 34 to +43
successorsPredicate,
ExactVersionRelease(*installedVersionRelease),
), nil
}

// If release version priority is enabled, also consider bundles
// with the same semantic version but higher release as valid successors.
// This allows upgrades to re-released bundles (e.g., 2.0.0+1 -> 2.0.0+2).
if features.OperatorControllerFeatureGate.Enabled(features.ReleaseVersionPriority) {
predicates = append(predicates, SameVersionHigherRelease(*installedVersionRelease))
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

SuccessorsOf is described/tested as feature-gated to allow same-semver higher-release bundles, but the implementation currently never checks features.ReleaseVersionPriority and never composes SameVersionHigherRelease(...) into the returned predicate. As a result, enabling/disabling the new gate has no effect and the new gate tests cannot pass. Add a gate check and OR in SameVersionHigherRelease(*installedCompositeVersion) when the feature is enabled.

Copilot uses AI. Check for mistakes.
@grokspawn
Copy link
Copy Markdown
Contributor

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.
From the perspective of registry+v1 bundles, this is precedent and we should support the new case with .spec.release is available, otherwise falling back on the 'is it bundle metadata' ordering logic.

Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
…hen comparison returns equal

Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
@rashmigottipati rashmigottipati force-pushed the oprun-4277-implementation branch from a2e5062 to 1e9cded Compare April 2, 2026 20:52
Copilot AI review requested due to automatic review settings April 2, 2026 20:52
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 7 out of 7 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 19 to 23
HelmChartSupport featuregate.Feature = "HelmChartSupport"
BoxcutterRuntime featuregate.Feature = "BoxcutterRuntime"
DeploymentConfig featuregate.Feature = "DeploymentConfig"
BoxcutterRuntime featuregate.Feature = "BoxcutterRuntime"
DeploymentConfig featuregate.Feature = "DeploymentConfig"
CompositeVersionComparison featuregate.Feature = "CompositeVersionComparison"
)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

PR title/description reference a ReleaseVersionPriority feature gate, but this code introduces and checks CompositeVersionComparison instead (and there are no references to ReleaseVersionPriority in the repo). Please align the feature gate name across the PR metadata and implementation (either rename the gate in code or update the PR title/description) so operators know which flag to set.

Copilot uses AI. Check for mistakes.
Comment on lines +249 to +254
// Explicitly disable the feature gate for this test
prevEnabled := features.OperatorControllerFeatureGate.Enabled(features.CompositeVersionComparison)
require.NoError(t, features.OperatorControllerFeatureGate.Set(fmt.Sprintf("%s=false", features.CompositeVersionComparison)))
t.Cleanup(func() {
require.NoError(t, features.OperatorControllerFeatureGate.Set(fmt.Sprintf("%s=%t", features.CompositeVersionComparison, prevEnabled)))
})
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

These tests mutate the global features.OperatorControllerFeatureGate via Set(...). Unit tests run with go test ... across packages in parallel (and with -race), so this can create cross-package interference/flakes when another package’s tests toggle the same gate concurrently. Consider adding a mutex-protected helper in the features package for temporarily setting gates in tests (shared across packages), or refactor the code under test to accept an injected featuregate.FeatureGate so tests can use an isolated instance.

Copilot uses AI. Check for mistakes.
Comment on lines +206 to +214
prevEnabled := features.OperatorControllerFeatureGate.Enabled(features.CompositeVersionComparison)
t.Cleanup(func() {
require.NoError(t, features.OperatorControllerFeatureGate.Set(fmt.Sprintf("%s=%t", features.CompositeVersionComparison, prevEnabled)))
})

t.Run("feature gate disabled - uses build metadata", func(t *testing.T) {
require.NoError(t, features.OperatorControllerFeatureGate.Set(fmt.Sprintf("%s=false", features.CompositeVersionComparison)))
result := compare.ByVersionAndRelease(registryV1_b1, registryV1_b2)
assert.Greater(t, result, 0, "should sort by build metadata: 1.0.0+2 > 1.0.0+1")
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

This test toggles the process-global features.OperatorControllerFeatureGate. Because make test-unit runs go test over many packages in parallel (and with -race), this can race with other packages’ tests that also set CompositeVersionComparison, leading to nondeterministic failures. Please guard gate mutations with a shared lock/helper in the features package or use an injected/local FeatureGate instance for the code under test.

Copilot uses AI. Check for mistakes.
Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
@rashmigottipati rashmigottipati changed the title ✨ Add ReleaseVersionPriority feature gate for re-release upgrade support ✨ Support explicit pkg.Release field with build metadata fallback for bundle comparison Apr 2, 2026
@rashmigottipati
Copy link
Copy Markdown
Member Author

@grokspawn @joelanford Updated based on your feedback.

PR now implements the hybrid approach: uses Bundle.Compare() to read explicit pkg.Release from olm.package, falling back to build metadata when comparison returns equal. This supports both registry+v1 bundles and new bundle formats.

Added feature gate CompositeVersionComparison (alpha, disabled by default) for backward compatibility.

Ready for re-review when you have a chance. Thanks!

Signed-off-by: Rashmi Gottipati <rgottipa@redhat.com>
Copilot AI review requested due to automatic review settings April 3, 2026 19:02
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 7 out of 7 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +55 to +67
func SameVersionHigherRelease(expect bundle.VersionRelease) filter.Predicate[declcfg.Bundle] {
return func(b declcfg.Bundle) bool {
actual, err := bundleutil.GetVersionAndRelease(b)
if err != nil {
return false
}

if expect.Version.Compare(actual.Version) != 0 {
return false
}

return expect.Release.Compare(actual.Release) < 0
}
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

SameVersionHigherRelease() relies on bundleutil.GetVersionAndRelease(), which currently only parses legacy registry+v1 "release" from semver build metadata (see bundleutil/bundle.go TODO). With CompositeVersionComparison enabled, bundles that use an explicit pkg.Release field (and a clean semver Version like "1.0.0") will never be recognized as higher-release successors. Consider updating the version/release extraction used here to understand pkg.Release (e.g., via declcfg.Bundle.Compare/CompositeVersion or by parsing the olm.package property’s release field) so successor detection works for the new bundle format.

Copilot uses AI. Check for mistakes.
require.NoError(t, features.OperatorControllerFeatureGate.Set(fmt.Sprintf("%s=true", features.CompositeVersionComparison)))
result := compare.ByVersionAndRelease(b1, b2)
assert.Positive(t, result, "Bundle.Compare() returns 0, fallback to build metadata: 1.0.0+2 > 1.0.0+1")
})
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

The new feature-gated comparison test only exercises the registry+v1 fallback case where Bundle.Compare() returns 0 and build metadata breaks ties. There’s no unit test demonstrating that, with CompositeVersionComparison enabled, bundles with the same pkg.Version but different explicit pkg.Release values sort correctly. Adding a test case for explicit pkg.Release ordering would help prevent regressions and validate the new behavior described in the PR.

Suggested change
})
})
t.Run("feature gate enabled - explicit release orders bundles with the same version", func(t *testing.T) {
withLowerRelease := declcfg.Bundle{
Name: "package1.v1.0.0-r1",
Properties: []property.Property{
{Type: property.TypePackage, Value: json.RawMessage(`{"packageName": "package1", "version": "1.0.0", "release": "1"}`)},
},
}
withHigherRelease := declcfg.Bundle{
Name: "package1.v1.0.0-r2",
Properties: []property.Property{
{Type: property.TypePackage, Value: json.RawMessage(`{"packageName": "package1", "version": "1.0.0", "release": "2"}`)},
},
}
require.NoError(t, features.OperatorControllerFeatureGate.Set(fmt.Sprintf("%s=true", features.CompositeVersionComparison)))
result := compare.ByVersionAndRelease(withLowerRelease, withHigherRelease)
assert.Positive(t, result, "with CompositeVersionComparison enabled, bundles with the same version should sort by explicit release: release 2 > release 1")
})

Copilot uses AI. Check for mistakes.
Comment on lines +246 to +322
// TestSuccessorsOf_WithCompositeVersionComparison_FeatureGateDisabled verifies higher releases
// are NOT successors when CompositeVersionComparison gate is disabled (testing the default behavior).
func TestSuccessorsOf_WithCompositeVersionComparison_FeatureGateDisabled(t *testing.T) {
// Explicitly disable the feature gate for this test
prevEnabled := features.OperatorControllerFeatureGate.Enabled(features.CompositeVersionComparison)
require.NoError(t, features.OperatorControllerFeatureGate.Set(fmt.Sprintf("%s=false", features.CompositeVersionComparison)))
t.Cleanup(func() {
require.NoError(t, features.OperatorControllerFeatureGate.Set(fmt.Sprintf("%s=%t", features.CompositeVersionComparison, prevEnabled)))
})

channel := declcfg.Channel{
Entries: []declcfg.ChannelEntry{
{Name: "test-package.v1.0.0+1"},
{
Name: "test-package.v2.0.0",
Replaces: "test-package.v1.0.0+1",
},
},
}
installedBundle := ocv1.BundleMetadata{
Name: "test-package.v1.0.0+1",
Version: "1.0.0+1",
}

higherRelease := declcfg.Bundle{
Name: "test-package.v1.0.0+2",
Package: "test-package",
Properties: []property.Property{
property.MustBuildPackage("test-package", "1.0.0+2"),
},
}

predicate, err := SuccessorsOf(installedBundle, channel)
require.NoError(t, err)

// Higher release should NOT match without feature gate
assert.False(t, predicate(higherRelease), "1.0.0+2 should NOT be a successor of 1.0.0+1 when feature gate disabled")
}

// TestSuccessorsOf_WithCompositeVersionComparison_FeatureGateEnabled verifies higher releases
// as valid successors when CompositeVersionComparison gate is enabled.
func TestSuccessorsOf_WithCompositeVersionComparison_FeatureGateEnabled(t *testing.T) {
// Enable the feature gate for this test
prevEnabled := features.OperatorControllerFeatureGate.Enabled(features.CompositeVersionComparison)
require.NoError(t, features.OperatorControllerFeatureGate.Set(fmt.Sprintf("%s=true", features.CompositeVersionComparison)))
t.Cleanup(func() {
require.NoError(t, features.OperatorControllerFeatureGate.Set(fmt.Sprintf("%s=%t", features.CompositeVersionComparison, prevEnabled)))
})

channel := declcfg.Channel{
Entries: []declcfg.ChannelEntry{
{Name: "test-package.v1.0.0+1"},
{
Name: "test-package.v2.0.0",
Replaces: "test-package.v1.0.0+1",
},
},
}
installedBundle := ocv1.BundleMetadata{
Name: "test-package.v1.0.0+1",
Version: "1.0.0+1",
}

higherRelease := declcfg.Bundle{
Name: "test-package.v1.0.0+2",
Package: "test-package",
Properties: []property.Property{
property.MustBuildPackage("test-package", "1.0.0+2"),
},
}

predicate, err := SuccessorsOf(installedBundle, channel)
require.NoError(t, err)

// Higher release should match when feature gate is enabled
assert.True(t, predicate(higherRelease), "1.0.0+2 should be a successor of 1.0.0+1 when feature gate enabled")
}
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

These SuccessorsOf feature-gate tests only cover legacy registry+v1 bundles where release is embedded in the version build metadata. Since CompositeVersionComparison is intended to support bundles with an explicit pkg.Release field, it would be good to add a test that constructs a bundle with pkg.Version "1.0.0" and pkg.Release set, and verifies SameVersionHigherRelease/SuccessorsOf behavior when the gate is enabled.

Copilot uses AI. Check for mistakes.
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.

5 participants