feat(projectconfig): add package publish channel annotations to TOML schema#38
feat(projectconfig): add package publish channel annotations to TOML schema#38liunan-ms wants to merge 4 commits intomicrosoft:mainfrom
Conversation
…schema
Introduces a layered package-config resolution system that annotates each
built binary RPM with a publish channel derived from project config.
Schema additions:
- PackagePublishConfig { channel, description }
- PackageConfig { description, publish }
- PackageGroupConfig { description, package-patterns, default-package-config }
- ProjectConfig.DefaultPackageConfig — project-wide baseline (lowest priority)
- ProjectConfig.PackageGroups — named groups matched by binary package name globs
- ComponentConfig.DefaultPackageConfig, ComponentConfig.Packages
Build output enrichment:
- RPMResult struct with Path, PackageName, Channel
- ComponentBuildResults.RPMs and RPMChannels populated post-build
There was a problem hiding this comment.
Pull request overview
Adds layered per-binary-package publish configuration to projectconfig, and surfaces resolved publish channels in component build output.
Changes:
- Introduces package-level config types (
PackageConfig,PackageGroupConfig, publish channel) plus deterministic resolution/merge logic. - Extends project/component config loading and validation to support project defaults and
package-groups. - Enriches
azldev component buildresults with per-RPM package name + resolved publish channel.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/projectconfig/project.go | Adds project-level default-package-config and package-groups to ProjectConfig. |
| internal/projectconfig/package.go | Implements package config structs, validation, and config resolution order. |
| internal/projectconfig/package_test.go | Adds unit tests for group validation, merge behavior, and resolution precedence. |
| internal/projectconfig/loader.go | Merges project default package config and package groups while loading; adds duplicate-group error. |
| internal/projectconfig/configfile.go | Adds TOML fields for defaults/groups and validates group patterns during config-file validation. |
| internal/projectconfig/component.go | Adds component-level default package config and per-package overrides; ensures deep copy in path normalization. |
| internal/app/azldev/cmds/component/build.go | Adds RPM result enrichment (package name + resolved channel) to build results. |
Regenerate schemas/azldev.schema.json and scenario snapshots to include the new default-package-config and package-groups config keys introduced by the new package.go types.
- Use env.FS() in packageNameFromRPM instead of os.Open to stay consistent with the repo's filesystem abstraction and improve unit testability - Add docs/user/reference/config/package-groups.md with full reference for package-groups, PackageConfig, and the 4-layer resolution order - Update docs/user/reference/config/project.md to document default-package-config and package-groups top-level fields - Update docs/user/reference/config/components.md to document per-component default-package-config and packages overrides
| // Path is the absolute path to the RPM file. | ||
| Path string `json:"path" table:"Path"` | ||
|
|
||
| // PackageName is the binary package name extracted from the RPM filename (e.g., "curl-devel"). |
There was a problem hiding this comment.
The comment for RPMResult.PackageName says the name is extracted from the RPM filename, but the implementation populates it by reading the RPM header (Name tag). Please update the comment to match the behavior to avoid misleading consumers.
| // PackageName is the binary package name extracted from the RPM filename (e.g., "curl-devel"). | |
| // PackageName is the binary package name read from the RPM header Name tag (e.g., "curl-devel"). |
| // packageNameFromRPM extracts the binary package name from an RPM file by reading | ||
| // its headers. Reading the Name tag directly from the RPM metadata is authoritative and | ||
| // handles all valid package names regardless of naming conventions. | ||
| func packageNameFromRPM(fs opctx.FS, rpmPath string) (pkgName string, err error) { |
There was a problem hiding this comment.
packageNameFromRPM uses named return values (pkgName, err) but doesn't rely on deferred modification of returns or need named returns for readability. Consider switching to unnamed returns to match the repo’s usual style and keep return flow clearer.
| func packageNameFromRPM(fs opctx.FS, rpmPath string) (pkgName string, err error) { | |
| func packageNameFromRPM(fs opctx.FS, rpmPath string) (string, error) { |
| // Enrich each RPM with its binary package name and resolved publish channel. | ||
| results.RPMs, err = resolveRPMResults(env.FS(), results.RPMPaths, env.Config(), component.GetConfig()) | ||
| if err != nil { | ||
| return results, fmt.Errorf("failed to resolve publish channels for %q:\n%w", component.GetName(), err) | ||
| } |
There was a problem hiding this comment.
New behavior enriches build results with RPM package names/channels (RPMs/RPMChannels), but there are no unit tests exercising this path (e.g., that channels are resolved and populated, and that failures to read RPM metadata surface correctly). Adding focused tests here would prevent regressions; use the in-memory test environment FS and avoid spawning external processes.
| if err := mergeDefaultPackageConfig(resolvedCfg, loadedCfg); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| if err := mergePackageGroups(resolvedCfg, loadedCfg); err != nil { | ||
| return err | ||
| } |
There was a problem hiding this comment.
The loader now merges default-package-config and package-groups, but loader tests don’t appear to cover parsing/merging/duplicate detection for these new fields. Please add loader-level tests (similar to existing component-group/distro tests) to lock down TOML behavior and validation.
This PR introduces a layered package-config configuration for managing binary package publishing in the project. It adds support for per-package and per-group publish settings, allowing fine-grained control over how and where RPMs are published. Publish channel annotation is added into build results.
Schema additions
Publish Channel
channelis a free-form string — it can be any target name, tag, or pipeline-defined label (e.g., "rpm-base", "rpm-build-only", "none"). The build team defines its own channel vocabulary.Resolution order
For a given binary package name, the resolver applies config in priority order — later layers override earlier ones:
default-package-config— the project-wide baseline; lowest priority of allpackage-groups— applied in alphabetical group name order for determinism; later-named groups override earlier-named ones for the same fielddefault-package-config— overrides any group default for all packages of that componentpackages.<exact-name>— highest priority; overrides everything for one specific packageBuild output
Examples
packages.tomlwith the content below and imported inproject.toml: