build: install a pre-resolved package list from supplied contents - #2448
Conversation
InstallPackageContents installs exactly a caller-supplied, pre-settled package list from its contents — no index is consulted, no dependency resolution happens, and nothing is fetched; the package checksum is derived from each carrier's control section (its SHA1, by definition). The installed-database tail is shared with InstallPackages via recordInstalled, so both installers write the database through one code path. build.WithPreResolvedPackages exposes this to image builds as a third way to satisfy the configured world, beside the existing lockfile path and FixateWorld: the configuration's package list still names the requested world; the option settles how it is satisfied. Downstream callers can then carry package contents in forms of their own choosing without apko learning those forms.
| ) | ||
| if bc.o.Lockfile != "" { | ||
| switch { | ||
| case len(bc.o.PreResolvedPackages) > 0: |
There was a problem hiding this comment.
Could we distinguish an explicitly supplied empty set from an absent option here? WithPreResolvedPackages([]) promises to install precisely that set without consulting indexes, but len == 0 falls through to the lockfile or FixateWorld path. An empty resolved world therefore still fetches and resolves repositories (and can fail offline) instead of performing a zero-package install.
| // world (written to /etc/apk/world); this option settles how it is satisfied. | ||
| func WithPreResolvedPackages(contents []apk.PackageContents) Option { | ||
| return func(bc *Context) error { | ||
| bc.o.PreResolvedPackages = contents |
There was a problem hiding this comment.
What about NewMultiArch callers? It reuses this same option for every architecture, so one contents slice is installed into every target context. InstallPackageContents does not compare PackageInfo.Arch with the context architecture, which lets an x86_64 slice be installed into the aarch64 image without an error. Could we key these contents by architecture, or reject incompatible multi-architecture use?
|
I have claude looking into the comments to follow up, since this auto-merged. |
#2449) …h contents Two follow-ups to the pre-resolved install path (#2448): An explicitly empty set fell through to the lockfile or FixateWorld branch, so WithPreResolvedPackages([]) — a promise to install precisely nothing without consulting an index — still resolved repositories and could fail offline. The option now distinguishes set-but-empty from unset (nil normalizes to empty; the options field documents nil as unset), and buildImage branches on presence rather than length. The test proves it by contradiction: against a repository that cannot satisfy anything, the control build fails to resolve and the empty-set build succeeds with zero packages installed. A multi-arch build reuses one option set for every architecture context, so contents for the wrong architecture arrived at InstallPackageContents silently and installed foreign binaries without an error. The installer now refuses contents whose .PKGINFO architecture disagrees with the context (noarch and unstated architectures still install everywhere).
InstallPackageContents installs exactly a caller-supplied, pre-settled package list from its contents — no index is consulted, no dependency resolution happens, and nothing is fetched; the package checksum is derived from each carrier's control section (its SHA1, by definition). The installed-database tail is shared with InstallPackages via recordInstalled, so both installers write the database through one code path.
build.WithPreResolvedPackages exposes this to image builds as a third way to satisfy the configured world, beside the existing lockfile path and FixateWorld: the configuration's package list still names the requested world; the option settles how it is satisfied. Downstream callers can then carry package contents in forms of their own choosing without apko learning those forms.