Skip to content

Add changelog bundle description#3058

Open
lcawl wants to merge 8 commits intomainfrom
bundle-descriptions
Open

Add changelog bundle description#3058
lcawl wants to merge 8 commits intomainfrom
bundle-descriptions

Conversation

@lcawl
Copy link
Copy Markdown
Member

@lcawl lcawl commented Apr 8, 2026

This PR adds support for a description within changelog bundle files.

Summary

  • Add descriptions to bundles via CLI (--description) or configuration (bundle.description, bundle.profiles.<name>.description)
  • Use placeholders for dynamic content like release URLs in the bundle description within the changelog configuration file
  • Support rich multiline descriptions with lists, links, and multiple paragraphs
  • Render the bundle description in both {changelog} directive and changelog render output

Implementation details

Schema & Model Changes

  • Added Description field to Bundle and BundleDto types
  • Updated serialization mappings in ReleaseNotesSerialization
  • Added round-trip tests for proper YAML serialization

Configuration Support

  • Extended BundleConfiguration and BundleProfile with Description fields
  • Updated YAML DTOs and configuration parsing
  • Enhanced config/changelog.example.yml with description examples

CLI Integration

  • Added --description parameter to both changelog bundle and changelog gh-release
  • Implemented placeholder substitution for {version}, {lifecycle}, {owner}, {repo} so that they can be used in a reusable bundle description in the changelog configuration file
  • Added validation that placeholders can be resolved (fail command if not)
  • Created BundleDescriptionSubstitution helper for consistent placeholder handling

Rendering Pipeline

  • Updated {changelog} directive to display descriptions after release headings
  • Enhanced both Markdown and AsciiDoc renderers to include descriptions
  • Implemented MVP multi-bundle approach (warns when conflicts exist)
  • Modified bundle merging to concatenate descriptions with blank lines

Documentation

  • Updated all CLI documentation (docs/cli/changelog/bundle.md, docs/cli/changelog/gh-release.md)
  • Enhanced contribution guide (docs/contribute/changelog.md) with detailed description usage
  • Updated syntax documentation (docs/syntax/changelog.md) showing rendered output
  • Added explicit examples for:
    • YAML literal block scalars (|) for multiline descriptions
    • CLI shell escaping ($'...\n\n...') for multiline command-line usage
    • Placeholder usage in both profile and option-based modes

Steps to test

EDOT Java test

Try to create content like what appears in https://www.elastic.co/docs/release-notes/edot/sdks/java#edot-java-1-10-0-release-notes

  1. Run the following commands to prepare for local testing:

    ./build.sh clean
    ./build.sh publishbinaries
  2. Create a changelog configuration file. Or check out [DOCS] Test bundle descriptions elastic-otel-java#1046

  3. Create a changelog with a description that has links, bullets, etc. For example:

     /path/to/GitHub/docs-builder/.artifacts/publish/docs-builder/release/docs-builder changelog add \
     --description $'* opentelemetry-javaagent: [2.26.1](https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/tag/v2.26.1)\n* opentelemetry-sdk: [1.60.1](https://github.com/open-telemetry/opentelemetry-java/releases/tag/v1.60.1)\n* opentelemetry-semconv: [1.40.0](https://github.com/open-telemetry/semantic-conventions-java/releases/tag/v1.40.0)\n* opentelemetry-java-contrib: [1.54.0](https://github.com/open-telemetry/opentelemetry-java-contrib/releases/tag/v1.54.0)' \
     --title 'Update stream OpenTelemetry agent dependencies to 2.26.1' \
     --prs 1017
  4. Create a bundle for that changelog and add a description. For example:

    /path/to/GitHub/docs-builder/.artifacts/publish/docs-builder/release/docs-builder changelog bundle \
    --all \
    --description $'The 1.10.0 release contains fixes for potential security vulnerabilities. Refer to our [security advisory](https://discuss.elastic.co/t/elastic-otel-java-1-10-0-security-update-esa-2026-22-ghsa-xw7x-h9fj-p2c7/385700) for more details.' \
    --output-products 'edot-java 1.10.0' \
    --output ./docs/releases/1.10.0.yaml
  5. Add changelog directives to view the output then preview it locally. For example:

    image

ECCTL test

Try to create content like https://www.elastic.co/docs/release-notes/ecctl with URLs generated from variables in bundle profiles.

  1. Create a changelog configuration file. Or check out [DOCS] Test release note changelogs ecctl#765

  2. Create a changelog. For example:

     /path/to/GitHub/docs-builder/.artifacts/publish/docs-builder/release/docs-builder changelog add \
     --prs 669 \
     --products 'cloud-control-ecctl 1.14.1 ga' \
     --description 'The `platform instance-configuration show` command now also supports the `--config-version` and `--show-deleted` flags to show a specific instance configuration version and allow fetching deleted instance configurations, respectively.'
  3. Verify that the changelog configuration file has a profile that includes a description, for example:

    bundle:
      profiles:
        ecctl-release:
          products: "cloud-control-ecctl {version} *"
          output: "ecctl-{version}.yaml"
          output_products: "cloud-control-ecctl {version}"
          description: "Download the release binaries: https://github.com/{owner}/{repo}/releases/tag/v{version}"
  4. Create a bundle for that changelog. For example:

    /path/to/GitHub/docs-builder/.artifacts/publish/docs-builder/release/docs-builder \
    changelog bundle ecctl-release 1.14.1
  5. Verify that the URL in the description was resolved correctly in the bundle file. For example:

    products:
    - product: cloud-control-ecctl
      target: 1.14.1
      repo: ecctl
      owner: elastic
    description: 'Download the release binaries: https://github.com/elastic/ecctl/releases/tag/v1.14.1'
  6. Add changelog directives to view the output then preview it locally. For example:

    image

Generative AI disclosure

  1. Did you use a generative AI (GenAI) tool to assist in creating this contribution?
  • Yes
  • No
  1. If you answered "Yes" to the previous question, please specify the tool(s) and model(s) used (e.g., Google Gemini, OpenAI ChatGPT-4, etc.).

Tool(s) and model(s) used: claude-4-sonnet

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 8, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds optional bundle-level description and profile-level description to changelog configuration and DTOs; adds nullable Description on runtime models and render context; introduces --description CLI option for changelog bundle and changelog gh-release. Implements placeholder substitution for {version}, {lifecycle}, {owner}, and {repo} with validation rules when inputs are missing. Bundling merges group descriptions (concatenates multiple or warns) and rendering inserts a single description immediately after release headings in Markdown and Asciidoc. Includes unit tests for YAML round-trip and placeholder validation scenarios.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as "CLI (changelog cmd)"
    participant ConfigLoader as "Config Loader"
    participant Bundler as "Bundling Service"
    participant Renderer as "Rendering Service"
    participant Formatter as "Formatter (Markdown/Asciidoc)"

    User->>CLI: run changelog bundle --description "..."
    CLI->>ConfigLoader: load bundle config (bundle + profiles)
    ConfigLoader-->>CLI: parsed config (may include descriptions)
    CLI->>Bundler: BundleChangelogs(input with Description)
    Bundler->>Bundler: resolve description (CLI > profile > bundle)
    Bundler->>Bundler: validate & substitute placeholders ({version},{lifecycle},{owner},{repo})
    Bundler-->>Renderer: emit validated bundles with Description
    Renderer->>Renderer: collect descriptions (single, none, or multi -> warn/skip)
    Renderer->>Formatter: BuildRenderContext(description)
    Formatter->>Formatter: render header then description then entries
    Formatter-->>User: generated changelog output
Loading

Suggested labels

feature

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.21% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding description support to changelog bundles, which is the primary focus of the changeset.
Description check ✅ Passed The description is comprehensive and directly related to the changeset. It covers schema changes, configuration support, CLI integration, rendering pipeline updates, documentation, and testing steps.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch bundle-descriptions

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/tooling/docs-builder/Commands/ChangelogCommand.cs (2)

509-530: ⚠️ Potential issue | 🟠 Major

Reject --description in profile mode.

Line 516 adds the new flag, but the profile-mode gate never adds it to forbidden. That means bundle <profile> ... --description ... is accepted and then dropped when profile/config description resolution runs, so the flag becomes a silent no-op instead of an error.

Suggested fix
 			if (!string.IsNullOrWhiteSpace(directory))
 				forbidden.Add("--directory");
+			if (!string.IsNullOrWhiteSpace(description))
+				forbidden.Add("--description");

Also applies to: 591-622

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/tooling/docs-builder/Commands/ChangelogCommand.cs` around lines 509 -
530, The Bundle command currently accepts the --description flag in profile mode
but silently drops it during profile/config resolution; update the profile-mode
gate in the Bundle method to reject/forbid the "description" flag by adding
"description" to the forbidden list used when a profile (or
profileArg/profileReport) is supplied so the CLI returns an error instead of
silently ignoring the value; make the same change in the other profile-mode
guard later in the method (the second forbidden-list block around the
config/profile resolution logic) so both code paths consistently reject
--description in profile mode.

791-820: ⚠️ Potential issue | 🟠 Major

Validate the resolved description template, not just the CLI flag.

This guard misses bundle.description from changelog.yml, so option-based bundles can still bypass placeholder validation via config. It also rejects {owner}/{repo}-only descriptions even when --owner/--repo or config already make those values resolvable. The check should run against the final description after config defaults, and only require --output-products for {version} / {lifecycle} placeholders.

src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs (1)

431-470: ⚠️ Potential issue | 🟠 Major

Profile descriptions are substituted too early.

This expands {version} / {lifecycle} / {owner} / {repo} from filterResult and config values before the final outputProducts and bundle-product fallbacks exist. A profile invoked with only a report plus static output_products can still render unknown or empty values here, even though the common post-build path at Lines 352-367 could resolve them correctly. Keep the raw template here and let the shared substitution logic run once the bundle metadata is finalized.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/cli/changelog/bundle.md`:
- Around line 492-498: The example places profiles at the YAML root so the CLI
won't find them; move the profiles mapping under the bundle key (so the CLI
reads bundle.profiles) by nesting the existing "profiles:" block inside a
top-level "bundle:" mapping (preserving the same profile name
"elasticsearch-release" and fields like products, output_products, and
description) so the command can discover the profile.

---

Outside diff comments:
In `@src/tooling/docs-builder/Commands/ChangelogCommand.cs`:
- Around line 509-530: The Bundle command currently accepts the --description
flag in profile mode but silently drops it during profile/config resolution;
update the profile-mode gate in the Bundle method to reject/forbid the
"description" flag by adding "description" to the forbidden list used when a
profile (or profileArg/profileReport) is supplied so the CLI returns an error
instead of silently ignoring the value; make the same change in the other
profile-mode guard later in the method (the second forbidden-list block around
the config/profile resolution logic) so both code paths consistently reject
--description in profile mode.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 56f0beb5-514c-4f2b-b8e0-cd55f8918ab5

📥 Commits

Reviewing files that changed from the base of the PR and between e067148 and 013f543.

📒 Files selected for processing (21)
  • config/changelog.example.yml
  • docs/cli/changelog/bundle.md
  • docs/cli/changelog/gh-release.md
  • docs/contribute/changelog.md
  • docs/syntax/changelog.md
  • src/Elastic.Documentation.Configuration/Changelog/BundleConfiguration.cs
  • src/Elastic.Documentation.Configuration/ReleaseNotes/Bundle.cs
  • src/Elastic.Documentation.Configuration/ReleaseNotes/BundleLoader.cs
  • src/Elastic.Documentation.Configuration/ReleaseNotes/ReleaseNotesSerialization.cs
  • src/Elastic.Documentation/ReleaseNotes/Bundle.cs
  • src/Elastic.Markdown/Myst/Directives/Changelog/ChangelogInlineRenderer.cs
  • src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs
  • src/services/Elastic.Changelog/Configuration/ChangelogConfigurationLoader.cs
  • src/services/Elastic.Changelog/GithubRelease/GitHubReleaseChangelogService.cs
  • src/services/Elastic.Changelog/Rendering/Asciidoc/ChangelogAsciidocRenderer.cs
  • src/services/Elastic.Changelog/Rendering/ChangelogRenderContext.cs
  • src/services/Elastic.Changelog/Rendering/ChangelogRenderingService.cs
  • src/services/Elastic.Changelog/Rendering/Markdown/IndexMarkdownRenderer.cs
  • src/services/Elastic.Changelog/Serialization/ChangelogConfigurationYaml.cs
  • src/tooling/docs-builder/Commands/ChangelogCommand.cs
  • tests/Elastic.Changelog.Tests/Changelogs/BundleLoading/BundleLoaderTests.cs

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/contribute/changelog.md`:
- Around line 833-837: The docs overstate that option-based mode requires
`--output-products` for `{version}`/`{lifecycle}`; update the paragraph to match
actual behavior by changing the wording for option-based mode to state that if
`--output-products` is not provided the bundler will fall back to an empty
substitution (rather than failing), and keep the existing accurate guidance for
profile-based mode (mentioning `bundle profile` and `output_products`). Ensure
the text clearly references the placeholders `{version}` and `{lifecycle}`, the
flag `--output-products`, and the profile usage `bundle profile` so readers
understand the differing behaviors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a144fcbe-4797-4d58-a1bb-eb3bae592abe

📥 Commits

Reviewing files that changed from the base of the PR and between 013f543 and 96b506f.

📒 Files selected for processing (2)
  • docs/cli/changelog/bundle.md
  • docs/contribute/changelog.md
✅ Files skipped from review due to trivial changes (1)
  • docs/cli/changelog/bundle.md

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/Elastic.Changelog.Tests/Changelogs/BundleChangelogsTests.cs`:
- Line 5973: Multiple tests in BundleChangelogsTests.cs share the literal Output
= "bundle.yaml" (and a reader that expects that path), causing cross-test
contamination under parallel runs; change the tests to generate a unique
per-test output path (e.g., use TestContext.TestName or Guid.NewGuid() to
compose a filename like $"bundle_{Guid...}.yaml") and update the places that
read the file to use that generated path (look for the Output property
assignments and the reader call that opens "bundle.yaml" in the same file and
replace the hard-coded string with the test-local variable).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8db6792c-b0a7-4b26-a5ce-80c1af81f212

📥 Commits

Reviewing files that changed from the base of the PR and between 96b506f and c2f16d9.

📒 Files selected for processing (3)
  • src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs
  • src/tooling/docs-builder/Commands/ChangelogCommand.cs
  • tests/Elastic.Changelog.Tests/Changelogs/BundleChangelogsTests.cs
✅ Files skipped from review due to trivial changes (1)
  • src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/tooling/docs-builder/Commands/ChangelogCommand.cs

@coderabbitai coderabbitai bot added documentation Improvements or additions to documentation and removed feature labels Apr 9, 2026
@coderabbitai coderabbitai bot added feature and removed documentation Improvements or additions to documentation labels Apr 9, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/tooling/docs-builder/Commands/ChangelogCommand.cs (1)

774-781: ⚠️ Potential issue | 🟠 Major

--plan can falsely fail placeholder descriptions

Line 780 sets Description, but planInput does not include OutputProducts. With placeholder validation ({version}, etc.), --plan can reject valid calls that already passed --output-products.

Proposed fix
 		var planInput = new BundleChangelogsArguments
 		{
 			Output = processedOutput,
 			Profile = profile,
 			ProfileArgument = profileArg,
 			Config = config,
+			OutputProducts = outputProducts,
 			Description = description
 		};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/tooling/docs-builder/Commands/ChangelogCommand.cs` around lines 774 -
781, The plan input for the --plan flow builds a BundleChangelogsArguments
instance (planInput) but omits the OutputProducts property, so placeholder
validation (e.g., {version}) can reject valid runs that provided
--output-products; update the code that constructs planInput to copy the
OutputProducts from the existing config/arguments (the same source used for
processedOutput and profileArg) into planInput.OutputProducts so placeholder
validation sees the same products as the real run, ensuring --plan mirrors
--output-products behavior (modify the BundleChangelogsArguments construction
where planInput is created).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/tooling/docs-builder/Commands/ChangelogCommand.cs`:
- Around line 774-781: The plan input for the --plan flow builds a
BundleChangelogsArguments instance (planInput) but omits the OutputProducts
property, so placeholder validation (e.g., {version}) can reject valid runs that
provided --output-products; update the code that constructs planInput to copy
the OutputProducts from the existing config/arguments (the same source used for
processedOutput and profileArg) into planInput.OutputProducts so placeholder
validation sees the same products as the real run, ensuring --plan mirrors
--output-products behavior (modify the BundleChangelogsArguments construction
where planInput is created).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5d50bc92-3346-4045-86c9-a010c65929ea

📥 Commits

Reviewing files that changed from the base of the PR and between fbb2a67 and f6664c5.

📒 Files selected for processing (2)
  • config/changelog.example.yml
  • src/tooling/docs-builder/Commands/ChangelogCommand.cs
✅ Files skipped from review due to trivial changes (1)
  • config/changelog.example.yml

@github-actions github-actions bot requested a deployment to assembler-preview April 9, 2026 20:39 In progress
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants