fix(pkg): resolve --rpm-file packages per source package, not per name - #358
Draft
Andrew Phelps (anphel31) wants to merge 2 commits into
Draft
Andrew Phelps (anphel31) wants to merge 2 commits into
Andrew Phelps (anphel31) wants to merge 2 commits into
Conversation
Copilot started reviewing on behalf of
Andrew Phelps (anphel31)
September 18, 2026 18:50
View session
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Document the changed --rpm-file output contract and row uniqueness for scripting users.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Updates --rpm-file resolution to preserve multiple producers for the same binary package and resolve each by source component.
Changes:
- Deduplicates exact
(packageName, sourcePackageName)pairs. - Resolves RPM channels per source package.
- Adds multi-producer and order-independence tests.
File summaries
| File | Description |
|---|---|
internal/app/azldev/cmds/pkg/list.go |
Implements per-source RPM resolution and pair deduplication. |
internal/app/azldev/cmds/pkg/list_test.go |
Tests duplicate handling and multi-producer resolution. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Copilot started reviewing on behalf of
Andrew Phelps (anphel31)
September 18, 2026 19:58
View session
loadRPMFile kept the first mapping for a binary package name and discarded any later entry naming a different source package, warning that it had done so. The result was one entry per packageName, whose component - and therefore publish channel - depended on the order of entries in the file. A binary name produced by more than one component is legitimate. rubygem-bundler is emitted by both 'ruby' (rpm-base) and the standalone 'rubygem-bundler' component (rpm-sdk). A caller that listed both got a single answer chosen by position, so the same package resolved differently in different invocations depending on what else was in the map. That reached production. Control Tower builds its source map from an unordered collection, so its whole-corpus routing pass and its per-batch publish pass received different channels for rubygem-bundler. Publishing placed the RPMs in the repos that rpm-sdk maps to while the presence check expected the ones rpm-base maps to, so the component was re-queued every six hours for weeks, uploading nothing and reporting success. Each (packageName, sourcePackageName) pair is now preserved and reported, so a package with two producers yields one entry per producer, each resolved against its own component. The component is taken from the source package being expanded rather than looked up by name, which removes the order dependence entirely. resolvePackageListResult now receives an already-resolved component name, so both call paths state where the component came from. Only exact duplicate pairs are collapsed. The conflict warning and its TODO are gone: the condition it reported is handled rather than tolerated. Tests: the validation case that asserted first-mapping-wins now asserts one entry per source, and a new case checks that two producers resolve to their own channels and that reversing the order of the map does not change the result. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The change to report one row per (packageName, sourcePackageName) is user-visible: a binary name produced by several components now appears once per producer. A script keying results by package name alone silently drops a producer, and which one survives depends on iteration order - the same failure this change removes, reintroduced one layer up. Adds a 'Row uniqueness' section to the inspect-package-config how-to with a worked rubygem-bundler example, and corrects the Component-column note, which said Component never means 'the component whose spec produces this package' - true for -a and -p, but the opposite of what it means under --rpm-file. Also states the contract in the command's own help text, and regenerates docs/user/reference/cli/azldev_package_list.md from it. Raised in review. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Andrew Phelps (anphel31)
force-pushed
the
anphel/rpm-file-resolve-per-source
branch
from
September 18, 2026 20:14
5a4487e to
bdae30a
Compare
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
azldev package list --rpm-filenow reports one entry per(packageName, sourcePackageName)pair, instead of one entry per package name chosen by position in the file.The problem
loadRPMFilekept the first mapping for a binary package name and discarded any later entry naming a different source package:So the component — and therefore the publish channel — for such a name depended on the order of entries in the file.
A binary name produced by more than one component is legitimate, not a malformed input.
rubygem-bundleris emitted by bothruby(rpm-base) and the standalonerubygem-bundlercomponent (rpm-sdk). Listing both producers gave one answer, picked by position:Same question, two answers.
Why it mattered
Control Tower builds its RPM source map from an unordered collection, so entry order varies with the contents of the batch. Its whole-corpus routing pass and its per-batch publish pass therefore received different channels for the same package: publishing placed the RPMs in the repos that
rpm-sdkmaps to while the presence check expected the onesrpm-basemaps to. (In Azure Linux those are thebuilddepsandbasePMC repositories respectively — the channel name and the repository name differ, which is worth keeping straight when reading the logs.)The component never satisfied its own presence check and was re-queued every six hours for weeks — uploading nothing and reporting success each time. The warning above was emitted on every call and never surfaced, because the caller only logged subprocess stderr on a non-zero exit.
The change
(packageName, sourcePackageName)pair is preserved. A package with two producers yields one entry per producer, each resolved against its own component.resolveFromRPMFilealready iterates by source, so the producing component is known at the call site and the order dependence disappears.resolvePackageListResultnow takes an already-resolved component name. Both call paths state where the component came from:resolveComponentNamefor project-driven listings, the source package for--rpm-file.loadRPMFilereturns onlysrpmMap; therpmCompOfindex was the structure that could not represent two producers.TODOare removed — the condition it reported is now handled rather than tolerated.The existing sort in
listPackagesFromRPMFilealready tie-breaks onComponentfor entries sharing a package name, so output remains deterministic.Compatibility
Callers that send one producer per name see no change. Callers that send several now receive an entry per producer rather than one arbitrary entry, and must key results by
(packageName, sourcePackageName)rather than by name alone. That is the intent: a name alone is not a unique key.Tests
TestListPackages_RPMFile_MultipleProducersResolvePerSourcechecks that two producers of one name resolve to their own components' channels, and that reversing the order of the map does not change the result.go build ./...clean.go test ./internal/app/azldev/cmds/pkg/...passes.go test ./...has one unrelated failure ininternal/utils/fileutils(TestEmbedFSWithSubdir/ReadFileInSubdir, CRLF vs LF) which reproduces on an unmodified checkout — an artefact of checking the repo out on Windows, not of this change.golangci-lintwas not available in my environment;gofmtreports no diff on the changed files once CRLF line endings are normalised.Note
Filed as a draft. The behaviour change is small but it is a contract change for anyone consuming
--rpm-fileoutput, so it is worth an owner's read before it goes further.