apk: repo: prefer same-origin/same-version providers for virtual packages#2098
Draft
aborrero wants to merge 2 commits intochainguard-dev:mainfrom
Draft
apk: repo: prefer same-origin/same-version providers for virtual packages#2098aborrero wants to merge 2 commits intochainguard-dev:mainfrom
aborrero wants to merge 2 commits intochainguard-dev:mainfrom
Conversation
…resolution We have identified a situation in which apko dependency resolver doesn't correctly resolve virtual packages competing to satisfy the dependency tree. Take this scenario as example: * an image installs package-A and package-B * package-A depends on so:libfoo (unversioned) * package-B depends on so:libfoo-15 (versioned) * both so:libfoo and so:libfoo-15 can be satisfied by the libfoo-15 package * but there is also libfoo-16, which also provides so:libfoo (unversioned) In this scenario, before this patch, apko resolve will happily install libfoo-16 and thus break installation of package-B, resulting in an image build failure. This patch introduces a "backtracking" logic that re-evaluates the dependency three when this case is found. This is achieved with this strategy: * by introducing the notion of "retryable" errors in the resolver loop, and * snapshotting the resolver state when evaluating candidate packages * evaluate package candidates and if a retryable error is found, restore resolver state from the snapshot This change has been co-authored with Claude Code. Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero@chainguard.dev>
…ages
When selecting a provider for a virtual package, the resolver now gives
the highest priority to candidates that share both the origin and the
exact package version with an already-selected package.
This models the common pattern where a source package (e.g. postgresql)
produces multiple binary packages at the same version (e.g.
postgresql-15=15.3-r1 and libpq-15=15.3-r1). Packages from the same
source build are most likely to be mutually compatible, so they should
be preferred over a newer release of the same library from the same
origin.
The priority tiers in comparePackages are now:
1. exact package name+version already installed (existing)
2. same origin + same package version as installed (new)
3. same origin, any version (existing)
4. version comparison (existing)
Implementation details:
- existingOrigins changes from map[string]bool to
map[string]map[string]bool so that multiple versions from the
same origin (e.g. postgresql-14 and postgresql-15 installed
simultaneously) are all tracked correctly.
- addExistingOrigin() is a helper that populates the nested map
safely, guarding against empty-origin packages.
- cloneExistingOrigins() deep-clones the nested map for snapshots,
replacing the previous shallow maps.Clone() call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero@chainguard.dev>
xnox
reviewed
Feb 26, 2026
| if packageProvidesVersion(conflict, constraint.Name, constraint.Version) { | ||
| continue | ||
| } | ||
| return fmt.Errorf("selecting package %s conflicts with %s on %q", pkg.Filename(), conflict.Filename(), constraint.Name) |
Member
There was a problem hiding this comment.
Fun fact, in apk-tools file are deemed to be conflicts if they are different checksums. Othwerise, I believe two packages providing identical filenames is harmless.
Member
|
Ultimate tests if this:
Todo:
|
Author
Author
|
I have rebased the base patch at #2098 so this needs rebase. |
Member
|
This still automatically picks libpq-18 without any capping and pinning. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When selecting a provider for a virtual package, the resolver now gives
highest priority to candidates that share both the origin and the exact
package version with an already-selected package.
This models the common pattern where a single source package (e.g.
postgresql) produces multiple binary packages at the same version (e.g.postgresql-15=15.3-r1andlibpq-15=15.3-r1). Packages from the samesource build are most likely mutually compatible, so they should be preferred
over a newer release of the same library from the same origin.
The desired provider ordering for a virtual like
libpqwhenpostgresql-15=15.3-r1is already selected becomes:Implementation
existingOriginschanges frommap[string]booltomap[string]map[string]boolso that multiple packages from the sameorigin at different versions (e.g.
postgresql-14andpostgresql-15installed simultaneously) are all tracked correctly.
addExistingOrigin()populates the nested map safely, guarding againstempty-origin packages.
cloneExistingOrigins()deep-clones the nested map for snapshots,replacing the previous shallow
maps.Clone()call.comparePackagesbetween the existing"exact name+version already installed" and "same origin any version" tiers.
Priority tiers in
comparePackagesafter this changeTest plan
TestSameOriginVersionPreferredOverNewer— unit test viasortPackagesconfirming the new tier ranks the version-matched candidate first even when a newer version from the same origin existsTestSameOriginVersionEndToEnd— integration test throughGetPackagesWithDependenciesconfirming that whenpostgresql-15=15.3-r1is a top-level package,libpq-15=15.3-r1is selected overlibpq-15=15.4-r0🤖 Generated with Claude Code