Fix panic when installed package uses digest reference#7293
Fix panic when installed package uses digest reference#7293AndrewCharlesHay wants to merge 4 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughfindDependencyVersionToUpdate now detects digest-style installed versions and avoids semver MustParse panics: digests produce a specific error when parent semver constraints exist; non-digest, non-semver identifiers return a wrapped "Invalid Semantic Version" error. Selection logic for semver upgrades is unchanged. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested reviewers
Thank you — would you like me to add a short note to the changelog entry or verify any specific error messages in the tests? 🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@internal/controller/pkg/resolver/reconciler.go`:
- Around line 560-581: The code currently calls semver.MustParse(insVer)
(creating currentVersion) which can panic for non-semver tags like "latest" or
"main"; replace the MustParse call with a non-panicking parse (e.g.,
semver.Parse/ParseTolerant/semver.NewVersion) and handle the returned error
gracefully: if parsing fails, log a debug/error with context (including
dep.Identifier() and parent constraints) and return a descriptive error (or
apply the same fallback logic used for digest refs) instead of panicking. Ensure
you update the currentVersion usage to work with the parsed value and
early-return on parse error.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fa37a8f2-a29d-402e-9a85-4810881d8dd5
📒 Files selected for processing (2)
internal/controller/pkg/resolver/reconciler.gointernal/controller/pkg/resolver/reconciler_test.go
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@internal/controller/pkg/resolver/reconciler.go`:
- Around line 581-583: The returned error when semver.NewVersion(insVer) fails
should include which dependency (e.g., the dependency name or ID available in
scope) and a concrete remediation step; update the error returned from the
semver parse failure (the semver.NewVersion call handling in reconciler.go that
sets currentVersion and insVer) to wrap the original err with a message like:
which dependency/version string failed validation, what operation was being
attempted, and a suggested next step (e.g., "ensure the installed dependency
version is a valid semantic version (vMAJOR.MINOR.PATCH) or use a digest;
correct the installed version or re-run the install"), preserving the original
error for debugging. Ensure you reference semver.NewVersion, insVer and
currentVersion when making the change so the context is clear.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fc7be7c8-9283-4cc3-9b54-69afc2832ba3
📒 Files selected for processing (2)
internal/controller/pkg/resolver/reconciler.gointernal/controller/pkg/resolver/reconciler_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
- internal/controller/pkg/resolver/reconciler_test.go
…igest reference When the installed package version is a digest (e.g. sha256:...) rather than a semver tag, findDependencyVersionToUpdate panics at semver.MustParse. This adds a check for digest-format installed versions before attempting semver parsing, returning the lowest available version that satisfies all parent constraints instead. Fixes crossplane#7006 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Andrew Hay <andrew.hay@benchmarkanalytics.com>
Addresses CodeRabbit review: insVer can also be a non-semver tag like "latest" or "main", not just a digest. Replace semver.MustParse with semver.NewVersion to return an error instead of panicking. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Andrew Hay <andrew.hay@benchmarkanalytics.com>
Addresses CodeRabbit review: include the dependency identifier and a concrete remediation suggestion in the error message so operators can self-remediate faster. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Andrew Hay <andrew.hay@benchmarkanalytics.com>
8360f56 to
99d2718
Compare
adamwg
left a comment
There was a problem hiding this comment.
I was sure I had reviewed a fix for this before, and I did, but the PR was later deleted - that unmerged fix is here. Thanks for picking this up given that the other PR disappeared!
That said, I don't think this fix is the correct behavior. If the installed version uses a digest, there are two possible reasons for that:
- The user explicitly installed it by digest.
- Another package (or packages) specified a dependency on it by digest.
I believe if we get past lines 518-519 in this method, then we're in the first case (since in the second case findDigestToUpdate will already have returned an error regarding the incompatible constraints). We can't know (without further work - see below) whether the installed (by digest) version is compatible with any given semver. I don't think it's correct to have the resolver switch from a digest pinned version to a semver.
The easy fix is to return an error if a package is installed by digest and a semver constraint is requested in a dep (i.e., the fix linked above). I'm in favor of doing it this way: it's intuitive that an upgrade will fail if a specific version is already pinned and a semver constraint is requested.
A more involved fix would be to check the digest of each available semver. If we find one that matches the installed digest, we could consider the dependency satisfied. We still shouldn't change the installed version but we could at least let dependency resolution move forward. I don't think this is worth doing given that it's kind of a corner case.
…emver Per review feedback: when the installed version is a digest reference (e.g. sha256:abc...), the package has been explicitly pinned — either by the user or via a digest-pinned parent constraint that was already resolved by findDigestToUpdate. Silently switching to the lowest semver that satisfies parent constraints violates operator intent and makes the resolver's behavior surprising. Return an actionable error instead, pointing the operator at the two valid resolutions: update the parent package(s) to request the same digest, or reinstall the package with a semver tag. The test case previously named SuccessDigestInstalledVersion is renamed to ErrorDigestInstalledVersionWithSemverConstraints and now asserts the error return rather than a synthesised semver. Signed-off-by: Andrew Hay <andrew.hay@benchmarkanalytics.com>
|
Thanks @adamwg — you're right, the silent-switch-to-semver was wrong behavior. Just pushed an update that takes the easy-fix path you outlined (and that the linked commit took): when the installed version is a digest and the dependency has a semver constraint, return an actionable error instead of synthesising a semver. Specifically:
Agreed on leaving the digest-comparison approach (matching semver tag digest vs installed digest) as a follow-up — happy to open a separate issue tracking that if you think it's worth doing. PTAL when you get a chance. |
adamwg
left a comment
There was a problem hiding this comment.
Thanks for the update! I like that this also handles the case where the installed version is neither a digest nor a semver.
One ordering suggestion, otherwise lgtm.
| // digest without loading every candidate manifest, and silently | ||
| // switching a digest-pinned package to a semver tag would violate the | ||
| // operator's intent. Surface the conflict as an actionable error. | ||
| if _, err := conregv1.NewHash(insVer); err == nil { |
There was a problem hiding this comment.
It would be better to move this check up above the ListVersions call so that we avoid doing the OCI call, version parsing, etc. when we know we can't use a semver.
Description of your changes
When the
EnableAlphaDependencyVersionUpgradesfeature flag is enabled and an installed package uses a digest reference (e.g.@sha256:...) instead of a semver tag,findDependencyVersionToUpdatepanics atsemver.MustParsebecause the digest string is not valid semver.This adds a check for digest-format installed versions before attempting semver parsing. When the installed version is a digest, the function returns the lowest available version that satisfies all parent constraints, allowing the upgrade to proceed.
Covered by a new
SuccessDigestInstalledVersiontest case inTestReconcilerFindDependencyVersionToUpgrade.Fixes #7006
I have:
Run./nix.sh flake checkto ensure this PR is ready for review.Added or updated e2e tests.Linked a PR or a docs tracking issue to document this change.Addedbackport release-x.ylabels to auto-backport this PR.Followed the API promotion workflow if this PR introduces, removes, or promotes an API.