Open
Conversation
…dd output_products, repo, owner profile fields Phase 1: - Bundle command: reject all filter/output options (--all, --input-products, --output-products, --prs, --issues, --output, --repo, --owner, --resolve, --no-resolve, --hide-features, --config, --directory) when a profile argument is given. - Remove command: reject all options except --dry-run and --force when a profile argument is given. - Profile-based commands now discover changelog.yml automatically (./changelog.yml then ./docs/changelog.yml) and return a helpful error if neither is found, rather than silently falling back to defaults. An explicit config path is still accepted when passed directly to the service layer (used by tests). - ChangelogRemoveArguments.Directory changed from required to nullable; ApplyConfigDefaults follows the same null-coalescing pattern as the bundle service. - Fixes a silent bug where --output was ignored in profile mode. Phase 2: - Add output_products, repo, and owner fields to BundleProfileYaml, BundleProfile, and the config loader mapping. - ProcessProfile applies these fields when building the bundled output: output_products overrides the products array with version/lifecycle substitution; repo and owner are stored on each product entry for correct PR/issue link generation. - MergeHideFeatures removed; profile mode now uses only the profile's hide_features (CLI --hide-features is rejected at the command layer). - Update changelog.example.yml and docs to document all new profile fields and the mutual exclusivity requirement. Made-with: Cursor
🔍 Preview links for changed docs |
- Add 7 new unit tests for bundle/remove profile features:
- output_products overrides products array in bundle
- repo from profile is written to bundle product entries
- no repo/owner in profile preserves existing fallback behaviour
- missing config in profile mode returns error with advice (bundle + remove)
- changelog.yml discovered from CWD (./changelog.yml)
- changelog.yml discovered from docs/ subdir (./docs/changelog.yml)
- Update docs/contribute/changelog.md:
- Document mutual exclusivity of profile-based vs option-based bundle usage
- Add new "Profile-based bundling" section with full field reference table
- Document config auto-discovery behaviour for profile mode
- Update "Removal with profiles" to document mutual exclusivity,
allowed --dry-run/--force exceptions, and which profile fields are ignored
Made-with: Cursor
3 tasks
lcawl
commented
Feb 26, 2026
Adds repo and owner as top-level fields under bundle: in changelog.yml, providing a default that applies to all profiles. Profile-level values override the bundle-level default when set; otherwise the bundle-level value is used. This avoids repeating the same repo/owner in every profile when all profiles share the same repository. Also adds two tests verifying the fallback and override behaviour. Made-with: Cursor
Extends ApplyConfigDefaults in both ChangelogBundlingService and ChangelogRemoveService to fall back to bundle.repo and bundle.owner from config when --repo/--owner are not supplied on the CLI. This mirrors the existing behaviour for profile-based commands and means repo and owner rarely need to be specified on the command line when a changelog.yml with bundle-level defaults is present. Precedence: explicit CLI flag > bundle.repo/owner config > nothing (renderer falls back to product ID at render time). Adds four tests covering the config fallback and CLI-override paths for the bundle command. Made-with: Cursor
Updates all three places that describe --repo/--owner behaviour: - CLI param XML docs (bundle and remove): clarify both are optional and fall back to bundle.repo/bundle.owner in changelog.yml - changelog-bundle.md: expand --repo/--owner option descriptions; rewrite "Repository name in bundles" section to show the three-level precedence (CLI > profile > bundle config) with YAML examples; update profile fields table and the examples section to demonstrate bundle-level defaults with per-profile overrides - changelog.md: add a note that --repo/--owner fall back to config in option-based bundling; expand profile fields table to include bundle-level repo/owner defaults; update the --prs and --issues callout text to mention the config fallback Made-with: Cursor
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
2 tasks
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
This pull request implements the first two phases of an effort to get the profile-based
docs-builder changelog bundleanddocs-builder changelog removeinvocations to parity with the command-line-option method.Design Principles
changelog bundle <profile> <arg>orchangelog remove <profile> <arg>), any filter- or output-related command options must be rejected with an error. Profile config provides all such values.--dry-runand--forcemay be used with profiles. No other CLI options are allowed when using a profile.docs/changelog.yml):bundle.directory): The directory containing changelog YAML files for both bundle and remove.bundle.output_directory): For remove, the directory scanned for bundle dependencies. No--configor--directoryoverride — profile invocations rely on the config file.Phase 1: Mutual Exclusivity and Bug Fix
1.1 Reject extra options when using profile mode
Files: ChangelogCommand.cs
For both
BundleandRemove:isProfileModeis true, after validating profileArg is present, add a single check that rejects any of the following if specified:--all,--input-products,--output-products,--prs,--issues,--output,--repo,--owner,--resolve,--no-resolve,--hide-features,--config,--directory--all,--products,--prs,--issues,--repo,--owner,--config,--directory,--bundles-dir--dry-runand--force. For bundle, no CLI options allowed."When using a profile, do not specify --<option>. Paths and filters come from the changelog configuration. Allowed options with profiles (remove only): --dry-run, --force."Outcome: This fixes the incidental bug (silent
--outputdiscard) and enforces mutual exclusivity.1.2 Derive paths from config in profile mode
When using a profile, the changelog configuration file supplies all paths. Profile-based commands require the config file to exist; if it cannot be found, return an error.
Config discovery for profile mode:
./changelog.yml, then./docs/changelog.yml(relative to current working directory).my-custom/path/changelog.yml— run frommy-custom/path/to find it).--configoverride in profile mode.If config not found: Return an error (do not fall back to defaults). Error message should advise:
docs-builder changelog init, orchangelog.ymlexists (e.g. if the config is indocs/, run from the project root; if the config is inmy-folder/, run frommy-folder/).Path derivation from config:
bundle.directoryfrom config. EnsureChangelogBundlingService.ApplyConfigDefaultsandChangelogRemoveService.ApplyConfigDefaultsuse config when CLI did not supply--directory(which will always be the case in profile mode).bundle.output_directoryfrom config for the dependency check. EnsureChangelogRemoveService.ResolveBundlesDirectoryuses config whenBundlesDirwas not supplied (always in profile mode).Implementation note:
ChangelogConfigurationLoader.LoadChangelogConfigurationcurrently returnsChangelogConfiguration.Defaultwith a warning when the file is missing. For profile mode, the caller (or loader when invoked with profile context) must treat a missing config as a hard error and emit the advice above.1.3 Bundle-specific validation
processedOutputis computed from--output, since we will now error on--outputin profile mode.Output = nullso it uses the profile's output pattern (no need to merge CLI output anymore).Phase 2: Profile Config Enhancements (Changelog Bundle)
2.1 Add
output_productsto profile configFiles:
OutputProducts(string?) toBundleProfileYaml.OutputProducts(string?) toBundleProfile.OutputProductsfrom YAML to domain inParseBundleConfiguration.ProcessProfile, when a profile hasoutput_products, parse it viaProfileFilterResolver.ParseProfileProducts(or reuseProductInfoParser) and setOutputProductson the returned input.Config example:
2.2 Add
repoandownerto profile configFiles: Same YAML/domain/config-loader files as above.
Repo(string?) andOwner(string?) toBundleProfileYamlandBundleProfile.ProcessProfile, when the profile definesrepoorowner, set them on the returned input.repofield — the same state that already exists without--repoin option-based mode. The existing render-time fallback (product ID used as repo) applies, which may produce broken links when product ID ≠ GitHub repo name. Users who need correct links must setrepoin the profile config.No automatic derivation: Unlike option-based mode where
--repois explicit, profile mode has no--repoflag. Theproducts.ymlrepositoryfield is not a reliable source for automatic derivation, because its absence is ambiguous — some products genuinely share their name with their GitHub repo (e.g.elasticsearch), while others do not but have norepositoryfield recorded (e.g.cloud-serverless, whose GitHub repo iscloud). Attempting to derive repo fromproduct.Repository ?? productIdwould silently produce broken links for the latter case.For option-based mode: No change.
--repoand--ownerare already explicit; existing behavior is unchanged.Future improvement (out of scope): Populating missing
repositoryfields inproducts.ymlfor products where product ID ≠ GitHub repo name (such ascloud-serverless→cloud) would improve render-time link resolution for both modes. This is a separate cleanup task.2.2.1 Implementation changes
NOTE: This plan changed over the course of the PR, since I decided to add a "default"
bundle.repoandbundle.ownerthat can be optionally overridden at the profile level. These values can then serve as the default for the--repoand--ownerin the non-profile scenario too.The change affected:
ChangelogBundlingService.ApplyConfigDefaults— addsRepo = input.Repo ?? config.Bundle.RepoandOwner = input.Owner ?? config.Bundle.OwnerChangelogRemoveService.ApplyConfigDefaults— samePrecedence for both services and both modes:
So for a repo like
cloudwherecloud-serverlessis the product ID, you can now set it once inchangelog.yml:...and never need
--repo cloud --owner elasticon the command line again, whether you're using option-based or profile-based commands.Phase 5: Documentation and Examples
This pull request also includes the following pieces of phase 5:
Tests
(7 new tests across 2 files):
BundleChangelogsTests.cs:BundleChangelogs_WithProfile_OutputProducts_OverridesProductsArray— verifies thatoutput_productsin a profile replaces the products array in the bundle output (using wildcard lifecycle to match preview changelogs while advertisinggain the output)BundleChangelogs_WithProfile_RepoAndOwner_WritesValuesToProductEntries— verifies thatrepofrom a profile is written to the bundle product entries (owneris for normalization only, not persisted in the bundle)BundleChangelogs_WithProfile_NoRepoOwner_PreservesExistingFallbackBehavior— verifies that a profile withoutrepo/ownerproduces clean output with norepo:fieldBundleChangelogs_WithProfileMode_MissingConfig_ReturnsErrorWithAdvice— verifies error with advice when nochangelog.ymlis foundBundleChangelogs_WithProfileMode_ConfigAtCurrentDir_LoadsSuccessfully— verifies auto-discovery of./changelog.ymlBundleChangelogs_WithProfileMode_ConfigAtDocsSubdir_LoadsSuccessfully— verifies auto-discovery of./docs/changelog.ymlChangelogRemoveTests.cs:Remove_WithProfileMode_MissingConfig_ReturnsErrorWithAdvice— verifies that the remove command also returns a clear error when no config is discoverableDocumentation
(
docs/contribute/changelog.md):products,output,output_products,repo,owner,hide_features) with example config--dry-run/--forceexceptions, config auto-discovery, and which profile fields are ignored during removalSteps to test
bundle.directoryandbundle.output_directorysettings.Reviewer notes
I identified that this new
output_productsoption doesn't currently work with the promotion report option. The AI analysis indicated that's better to address in phase 3, which already planned to make changes to the promotion report functionality (so that it worked as a command option too).Generative AI disclosure
Tool(s) and model(s) used: composer-1.5, claude-4.6-sonnet-medium