Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion docs/cli/changelog/render.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,16 @@ The `render` command automatically discovers and merges `.amend-*.yaml` files wi
: Defaults to false.
: When enabled, entries are grouped by their area within each section. The first area from each entry's areas list is used for grouping.

`--dropdowns`
: Optional: Render separated types (breaking changes, deprecations, known issues, highlights) as MyST dropdowns.
: Defaults to false (flattened bulleted lists).
: When enabled, each entry in separated files is rendered as a collapsible dropdown section using MyST syntax (`::::{dropdown}`).
: When disabled (default), entries are rendered as flattened bulleted lists with PR/issue links inline and Impact/Action sections indented.
: This flag only affects markdown output; AsciiDoc output always uses its standard format.

`--title <string?>`
: Optional: The title to use for section headers, directories, and anchors in output files.
: Defaults to the version in the first bundle.
: Defaults to the version in the first bundle. When omitted, ISO date targets are formatted for display the same way as the `{changelog}` directive (e.g., `2026-05-04` becomes "May 4, 2026", `2026-05` becomes "May 2026"), while directory names and heading anchors continue to use the raw target slug.
: If the string contains spaces, they are replaced with dashes when used in directory names and anchors.

The `changelog render` command does **not** use `rules.publish` for filtering. Filtering must be done at bundle time using `rules.bundle`. For more information, refer to [](/contribute/publish-changelogs.md). For how the directive differs, see the [{changelog} directive syntax reference](/syntax/changelog.md).
Expand Down Expand Up @@ -141,3 +148,21 @@ docs-builder changelog render \
--input "./public-bundle.yaml|./changelog|elasticsearch|keep-links,./private-bundle.yaml|./private-changelog|internal-repo|hide-links" \
--output ./release-notes
```

### Render with dropdown format

```sh
docs-builder changelog render \
--input "./bundles/9.3.0.yaml|./changelog|elasticsearch" \
--dropdowns \
--output ./release-notes
```

### Render with subsections and flattened format (default)

```sh
docs-builder changelog render \
--input "./bundles/9.3.0.yaml|./changelog|elasticsearch" \
--subsections \
--output ./release-notes
```
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public record ChangelogRenderContext
public required string Owner { get; init; }
public required IReadOnlyDictionary<ChangelogEntryType, IReadOnlyCollection<ChangelogEntry>> EntriesByType { get; init; }
public required bool Subsections { get; init; }
public required bool Dropdowns { get; init; }
public required HashSet<string> FeatureIdsToHide { get; init; }
public required Dictionary<ChangelogEntry, HashSet<string>> EntryToBundleProducts { get; init; }
public required Dictionary<ChangelogEntry, string> EntryToRepo { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public record RenderChangelogsArguments
public string? Output { get; init; }
public string? Title { get; init; }
public bool Subsections { get; init; }
public bool Dropdowns { get; init; }
public string[]? HideFeatures { get; init; }
public string? Config { get; init; }
public ChangelogFileType FileType { get; init; } = ChangelogFileType.Markdown;
Expand Down Expand Up @@ -226,9 +227,23 @@ private OutputSetup SetupOutput(
if (string.IsNullOrWhiteSpace(input.Title) && version == "unknown")
collector.EmitWarning(string.Empty, "No --title option provided and bundle files do not contain 'target' values. Output folder and markdown titles will default to 'unknown'. Consider using --title to specify a custom title.");

// Use title from input or default to version
var title = input.Title ?? version;
var titleSlug = ChangelogTextUtilities.TitleToSlug(title);
// Determine title and slug
string title;
string titleSlug;

if (string.IsNullOrWhiteSpace(input.Title))
{
// Default title: format dates like the changelog directive
title = VersionOrDate.FormatDisplayVersion(version);
// Slug always uses raw version to maintain consistent paths/anchors
titleSlug = ChangelogTextUtilities.TitleToSlug(version);
}
else
{
// Explicit title provided: use as-is for both title and slug
title = input.Title;
titleSlug = ChangelogTextUtilities.TitleToSlug(input.Title);
}

return new OutputSetup(outputDir, title, titleSlug);
}
Expand Down Expand Up @@ -325,6 +340,7 @@ private static ChangelogRenderContext BuildRenderContext(
Owner = ownerForAnchors,
EntriesByType = entriesByType,
Subsections = input.Subsections,
Dropdowns = input.Dropdowns,
FeatureIdsToHide = featureIdsToHide,
EntryToBundleProducts = entryToBundleProducts,
EntryToRepo = entryToRepo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,58 @@ public override async Task RenderAsync(ChangelogRenderContext context, Cancel ct
_ = sb.AppendLine();
if (shouldHide)
_ = sb.AppendLine("<!--");
_ = sb.AppendLine(InvariantCulture, $"::::{{dropdown}} {ChangelogTextUtilities.Beautify(entry.Title)}");
_ = sb.AppendLine(entry.Description ?? "% Describe the functionality that changed");
_ = sb.AppendLine();
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks);

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Impact)
? "**Impact**<br>" + entry.Impact
: "% **Impact**<br>_Add a description of the impact_");

_ = sb.AppendLine();

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Action)
? "**Action**<br>" + entry.Action
: "% **Action**<br>_Add a description of the what action to take_");
if (context.Dropdowns)
{
// Dropdown rendering (current logic)
_ = sb.AppendLine(InvariantCulture, $"::::{{dropdown}} {ChangelogTextUtilities.Beautify(entry.Title)}");
_ = sb.AppendLine(entry.Description ?? "% Describe the functionality that changed");
_ = sb.AppendLine();
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks);

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Impact)
? "**Impact**<br>" + entry.Impact
: "% **Impact**<br>_Add a description of the impact_");

_ = sb.AppendLine();

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Action)
? "**Action**<br>" + entry.Action
: "% **Action**<br>_Add a description of the what action to take_");

_ = sb.AppendLine("::::");
}
else
{
// Flattened rendering
_ = sb.Append("* ");
_ = sb.Append(ChangelogTextUtilities.Beautify(entry.Title));
_ = sb.AppendLine();

// Description with proper indentation
if (!string.IsNullOrWhiteSpace(entry.Description))
{
_ = sb.AppendLine(ChangelogTextUtilities.Indent(entry.Description));
_ = sb.AppendLine();
}

// PR/Issue links with "For more information" pattern - indented for list continuation
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks, indentForListItem: true);

// Impact and Action sections - indented for list continuation
if (!string.IsNullOrWhiteSpace(entry.Impact))
{
_ = sb.AppendLine(ChangelogTextUtilities.Indent("**Impact:** " + entry.Impact));
_ = sb.AppendLine();
}

if (!string.IsNullOrWhiteSpace(entry.Action))
{
_ = sb.AppendLine(ChangelogTextUtilities.Indent("**Action:** " + entry.Action));
_ = sb.AppendLine();
}
}

_ = sb.AppendLine("::::");
if (shouldHide)
_ = sb.AppendLine("-->");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,58 @@ public override async Task RenderAsync(ChangelogRenderContext context, Cancel ct
_ = sb.AppendLine();
if (shouldHide)
_ = sb.AppendLine("<!--");
_ = sb.AppendLine(InvariantCulture, $"::::{{dropdown}} {ChangelogTextUtilities.Beautify(entry.Title)}");
_ = sb.AppendLine(entry.Description ?? "% Describe the functionality that was deprecated");
_ = sb.AppendLine();
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks);

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Impact)
? "**Impact**<br>" + entry.Impact
: "% **Impact**<br>_Add a description of the impact_");

_ = sb.AppendLine();

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Action)
? "**Action**<br>" + entry.Action
: "% **Action**<br>_Add a description of the what action to take_");
if (context.Dropdowns)
{
// Dropdown rendering (current logic)
_ = sb.AppendLine(InvariantCulture, $"::::{{dropdown}} {ChangelogTextUtilities.Beautify(entry.Title)}");
_ = sb.AppendLine(entry.Description ?? "% Describe the functionality that was deprecated");
_ = sb.AppendLine();
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks);

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Impact)
? "**Impact**<br>" + entry.Impact
: "% **Impact**<br>_Add a description of the impact_");

_ = sb.AppendLine();

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Action)
? "**Action**<br>" + entry.Action
: "% **Action**<br>_Add a description of the what action to take_");

_ = sb.AppendLine("::::");
}
else
{
// Flattened rendering
_ = sb.Append("* ");
_ = sb.Append(ChangelogTextUtilities.Beautify(entry.Title));
_ = sb.AppendLine();

// Description with proper indentation
if (!string.IsNullOrWhiteSpace(entry.Description))
{
_ = sb.AppendLine(ChangelogTextUtilities.Indent(entry.Description));
_ = sb.AppendLine();
}

// PR/Issue links with "For more information" pattern - indented for list continuation
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks, indentForListItem: true);

// Impact and Action sections - indented for list continuation
if (!string.IsNullOrWhiteSpace(entry.Impact))
{
_ = sb.AppendLine(ChangelogTextUtilities.Indent("**Impact:** " + entry.Impact));
_ = sb.AppendLine();
}

if (!string.IsNullOrWhiteSpace(entry.Action))
{
_ = sb.AppendLine(ChangelogTextUtilities.Indent("**Action:** " + entry.Action));
_ = sb.AppendLine();
}
}

_ = sb.AppendLine("::::");
if (shouldHide)
_ = sb.AppendLine("-->");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,34 @@ public override async Task RenderAsync(ChangelogRenderContext context, Cancel ct
_ = sb.AppendLine();
if (shouldHide)
_ = sb.AppendLine("<!--");
_ = sb.AppendLine(InvariantCulture, $"::::{{dropdown}} {ChangelogTextUtilities.Beautify(entry.Title)}");
_ = sb.AppendLine(entry.Description ?? "% Describe the highlight");
_ = sb.AppendLine();
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks);
_ = sb.AppendLine("::::");

if (context.Dropdowns)
{
// Dropdown rendering (current logic)
_ = sb.AppendLine(InvariantCulture, $"::::{{dropdown}} {ChangelogTextUtilities.Beautify(entry.Title)}");
_ = sb.AppendLine(entry.Description ?? "% Describe the highlight");
_ = sb.AppendLine();
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks);
_ = sb.AppendLine("::::");
}
else
{
// Flattened rendering
_ = sb.Append("* ");
_ = sb.Append(ChangelogTextUtilities.Beautify(entry.Title));
_ = sb.AppendLine();

// Description with proper indentation
if (!string.IsNullOrWhiteSpace(entry.Description))
{
_ = sb.AppendLine(ChangelogTextUtilities.Indent(entry.Description));
_ = sb.AppendLine();
}

// PR/Issue links with "For more information" pattern - indented for list continuation
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks, indentForListItem: true);
}

if (shouldHide)
_ = sb.AppendLine("-->");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,58 @@ public override async Task RenderAsync(ChangelogRenderContext context, Cancel ct
_ = sb.AppendLine();
if (shouldHide)
_ = sb.AppendLine("<!--");
_ = sb.AppendLine(InvariantCulture, $"::::{{dropdown}} {ChangelogTextUtilities.Beautify(entry.Title)}");
_ = sb.AppendLine(entry.Description ?? "% Describe the known issue");
_ = sb.AppendLine();
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks);

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Impact)
? "**Impact**<br>" + entry.Impact
: "% **Impact**<br>_Add a description of the impact_");

_ = sb.AppendLine();

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Action)
? "**Action**<br>" + entry.Action
: "% **Action**<br>_Add a description of the what action to take_");
if (context.Dropdowns)
{
// Dropdown rendering (current logic)
_ = sb.AppendLine(InvariantCulture, $"::::{{dropdown}} {ChangelogTextUtilities.Beautify(entry.Title)}");
_ = sb.AppendLine(entry.Description ?? "% Describe the known issue");
_ = sb.AppendLine();
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks);

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Impact)
? "**Impact**<br>" + entry.Impact
: "% **Impact**<br>_Add a description of the impact_");

_ = sb.AppendLine();

_ = sb.AppendLine(!string.IsNullOrWhiteSpace(entry.Action)
? "**Action**<br>" + entry.Action
: "% **Action**<br>_Add a description of the what action to take_");

_ = sb.AppendLine("::::");
}
else
{
// Flattened rendering
_ = sb.Append("* ");
_ = sb.Append(ChangelogTextUtilities.Beautify(entry.Title));
_ = sb.AppendLine();

// Description with proper indentation
if (!string.IsNullOrWhiteSpace(entry.Description))
{
_ = sb.AppendLine(ChangelogTextUtilities.Indent(entry.Description));
_ = sb.AppendLine();
}

// PR/Issue links with "For more information" pattern - indented for list continuation
RenderPrIssueLinks(sb, entry, entryRepo, entryOwner, entryHideLinks, indentForListItem: true);

// Impact and Action sections - indented for list continuation
if (!string.IsNullOrWhiteSpace(entry.Impact))
{
_ = sb.AppendLine(ChangelogTextUtilities.Indent("**Impact:** " + entry.Impact));
_ = sb.AppendLine();
}

if (!string.IsNullOrWhiteSpace(entry.Action))
{
_ = sb.AppendLine(ChangelogTextUtilities.Indent("**Action:** " + entry.Action));
_ = sb.AppendLine();
}
}

_ = sb.AppendLine("::::");
if (shouldHide)
_ = sb.AppendLine("-->");
}
Expand Down
Loading
Loading