Skip to content

Comments

Fix changelog directive and render command subsections with publishing rules#2752

Merged
lcawl merged 3 commits intomainfrom
changelog-area-logic
Feb 20, 2026
Merged

Fix changelog directive and render command subsections with publishing rules#2752
lcawl merged 3 commits intomainfrom
changelog-area-logic

Conversation

@lcawl
Copy link
Contributor

@lcawl lcawl commented Feb 20, 2026

Fixes #2751

The following summary comes from the AI plan that was implemented to address that issue.

Problem

GetComponent always returns entry.Areas[0], regardless of whether that area is excluded or not the preferred area under the active publish rules. This means entries can appear under an area that contradicts the configured rules.

Desired behavior

Given areas: [Search, Monitoring, Security] and a publish rule:

  • include_areas: [Security, Monitoring] → group under Monitoring (first area that is in the include list)
  • exclude_areas: [Search] → group under Monitoring (first area not in the exclude list)
  • No publish rule → group under Search (current behavior, unchanged)

Architecture overview

flowchart TD
    entry["ChangelogEntry\n(areas: [Search, Monitoring, Security])"]
    blocker["PublishBlocker\n(Areas, AreasMode)"]
    getPreferred["GetPreferredArea(entry, blocker)"]
    groupBy["GroupBy key"]

    entry --> getPreferred
    blocker --> getPreferred
    getPreferred --> groupBy
Loading

Changes

1. src/Elastic.Documentation/ReleaseNotes/PublishBlockerExtensions.cs

Add a new GetPreferredArea extension method. This is the core logic shared by both the directive and the CLI renderer:

public static string GetPreferredArea(this PublishBlocker? publishBlocker, ChangelogEntry entry)
{
    if (entry.Areas is not { Count: > 0 })
        return string.Empty;
    if (publishBlocker?.Areas is not { Count: > 0 })
        return entry.Areas[0];
    return publishBlocker.AreasMode switch
    {
        FieldMode.Include => entry.Areas.FirstOrDefault(a => IsAreaListed(publishBlocker, a)) ?? entry.Areas[0],
        FieldMode.Exclude => entry.Areas.FirstOrDefault(a => !IsAreaListed(publishBlocker, a)) ?? entry.Areas[0],
        _ => entry.Areas[0]
    };
}

private static bool IsAreaListed(PublishBlocker blocker, string area) =>
    blocker.Areas?.Any(l => l.Equals(area, StringComparison.OrdinalIgnoreCase)) ?? false;

2. src/Elastic.Markdown/Myst/Directives/Changelog/ChangelogInlineRenderer.cs

The directive already has a single resolved block.PublishBlocker — thread it through the call chain:

  • GetComponent(ChangelogEntry entry)GetComponent(ChangelogEntry entry, PublishBlocker? publishBlocker), which delegates to publishBlocker.GetPreferredArea(entry)
  • RenderEntriesByArea(...) → add PublishBlocker? publishBlocker parameter, pass to GetComponent
  • RenderDetailedEntries(...) → add PublishBlocker? publishBlocker parameter, pass to GetComponent (used when groupBySubtype == false)
  • GenerateMarkdown(...) → add PublishBlocker? publishBlocker parameter, pass to both render methods above
  • RenderSingleBundle(...) → already has publishBlocker, pass to GenerateMarkdown

3. src/services/Elastic.Changelog/Rendering/ChangelogRenderUtilities.cs

  • Replace GetComponent(ChangelogEntry entry) with GetComponent(ChangelogEntry entry, ChangelogRenderContext? context = null): when context is null, return entry.Areas?[0] ?? "" (current behavior); when context is provided, resolve the per-entry blocker via private GetPublishBlockerForEntry(entry, context) and return blocker.GetPreferredArea(entry). Keep GetPublishBlockerForProduct private.

4. CLI renderers (all use GetComponent for area grouping)

Update all call sites from GroupBy(ChangelogRenderUtilities.GetComponent) to GroupBy(e => ChangelogRenderUtilities.GetComponent(e, context)):

Renderer File
Index (features, fixes, docs, etc.) IndexMarkdownRenderer.cs
Highlights HighlightsMarkdownRenderer.cs, HighlightsAsciidocRenderer.cs
Known issues KnownIssuesMarkdownRenderer.cs, KnownIssuesAsciidocRenderer.cs
Deprecations DeprecationsMarkdownRenderer.cs, DeprecationsAsciidocRenderer.cs
Breaking changes BreakingChangesMarkdownRenderer.cs, BreakingChangesAsciidocRenderer.cs
Entries by area (asciidoc) EntriesByAreaAsciidocRenderer.cs

5. Tests

Add a new test class in tests/Elastic.Markdown.Tests/Directives/ChangelogSubsectionsTests.cs (or a companion file) covering:

  • Entry with multiple areas, include_areas rule → groups under first included area
  • Entry with multiple areas, exclude_areas rule → groups under first non-excluded area
  • Entry with multiple areas, no publish rule → unchanged (Areas[0] behavior)
  • Fallback: no area in entry matches include list → falls back to Areas[0]

Add matching tests in tests/Elastic.Documentation.Configuration.Tests/ReleaseNotes/PublishBlockerExtensionsTests.cs for the new GetPreferredArea method directly.

6. Verification

After implementation:

  • Ran dotnet build to ensure no compilation failures
  • Ran ./build.sh unit-test to validate tests
  • Ran dotnet format if the output contains formatting issues

7. Documentation

  • docs/syntax/changelog.md — expand the :subsections: option description (currently a single sentence) to explain area selection
  • docs/contribute/changelog.md — add a note after the publish rules example near the include_areas/exclude_areas coverage (~line 419) to explain that these rules also affect subsection display grouping when :subsections: or --subsections is enabled.
  • docs/cli/release/changelog-render.md — expand the --subsections option description to also note that when publish rules with include_areas or exclude_areas are configured, the area used for grouping is the first area from the entry's list that aligns with those rules (first included area, or first non-excluded area).

Screenshots

These screenshots show the behaviour with the content from elastic/docs-content#4880 which has the following info in the changelog configuration file:

rules:
  publish:
      'security':
        match_areas: any
        include_areas:
          - "Elastic Security solution"

Before

You can see some other areas appearing in the output, in particular for changelogs that had multiple areas:

image

After

The changelogs now show up in the desired areas:

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: composer-1.5, claude-4.6-sonnet-medium

@github-actions
Copy link

github-actions bot commented Feb 20, 2026

@lcawl lcawl marked this pull request as ready for review February 20, 2026 21:04
@lcawl lcawl requested review from a team as code owners February 20, 2026 21:04
@lcawl lcawl requested a review from reakaleek February 20, 2026 21:04
@lcawl lcawl merged commit f2b92a1 into main Feb 20, 2026
30 checks passed
@lcawl lcawl deleted the changelog-area-logic branch February 20, 2026 22:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request]: Make changelog directive subsections heed publishing rules

2 participants