Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7446e94
Add :subsections: property to the changelog directive
cotti Jan 27, 2026
7102002
Add date-based sorting for serverless in changelog directive
cotti Jan 27, 2026
7464782
Add :merge: property to the changelog directive
cotti Jan 27, 2026
f464f1b
Add a :config: property to the changelog directive.
cotti Jan 27, 2026
1376add
Add :hide-links: property to the changelog directive.
cotti Jan 27, 2026
5ee5496
Add support for :hide-features: for the changelog directive
cotti Jan 27, 2026
ba699a0
Update docs
cotti Jan 27, 2026
57d5aa9
Split changelog tests for readability
cotti Jan 27, 2026
9d93ad1
Merge branch 'main' into feature/changelog-directive-enhancements
cotti Jan 27, 2026
27c74fc
Merge branch 'main' into feature/changelog-directive-enhancements
cotti Jan 28, 2026
d0ae5de
Adjust formatting and hinting for changelog tests
cotti Jan 28, 2026
fcb83d9
Introduce bundle loading to Elastic.Changelog
cotti Jan 28, 2026
eb97846
Move functionality over to a dedicated service
cotti Jan 28, 2026
20757ea
Use BundleLoader service
cotti Jan 28, 2026
f441db0
Remove Path.Combine warnings, add extension method to IDirectoryInfo
cotti Jan 28, 2026
60a3b5d
Remove Path.Combine calls
cotti Jan 28, 2026
ab0eea1
Refactor and relocate several release notes data types to Elastic.Doc…
cotti Jan 29, 2026
8b9b5ad
Further unify data model usage for changelogs. Remove Mapperly depend…
cotti Jan 29, 2026
a362e40
Remove redundant tests
cotti Jan 29, 2026
01b2155
Fix AOT
cotti Jan 29, 2026
2909c30
Have a separate Deserializer for minimal changelog dtos
cotti Jan 29, 2026
3152fec
Collect ToC for changelog.
cotti Jan 29, 2026
8a138f4
Remove :merge:, keep it as default behavior
cotti Jan 29, 2026
a9e3165
Remove :hide-links:, use default inferred behavior
cotti Jan 29, 2026
1deddc4
Remove :hide-features: in favor of leveraging changelog data itself
cotti Jan 29, 2026
7e08e91
Add :types: parameter to support partial changelog displays
cotti Jan 29, 2026
09f2880
Add sub-pages for Release Notes example
cotti Jan 29, 2026
326a2b4
Fix tests on Windows
cotti Jan 30, 2026
efecc12
Merge branch 'main' into feature/changelog-directive-enhancements
cotti Jan 30, 2026
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
6 changes: 6 additions & 0 deletions docs/_docset.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
project: 'doc-builder'
max_toc_depth: 2
# indicates this documentation set is not linkable by assembler.
Expand Down Expand Up @@ -223,3 +223,9 @@
- folder: baz
children:
- file: qux.md
- folder: release-notes
children:
- file: index.md
- file: breaking-changes.md
- file: deprecations.md
- file: known-issues.md
191 changes: 191 additions & 0 deletions docs/syntax/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,197 @@ Or with a custom bundles folder:
:::
```

## Options

The directive supports the following options:

| Option | Description | Default |
|--------|-------------|---------|
| `:type: value` | Filter entries by type | Excludes separated types |
| `:subsections:` | Group entries by area/component | false |
| `:config: path` | Path to changelog.yml configuration | auto-discover |

### Example with options

```markdown
:::{changelog} /path/to/bundles
:type: all
:subsections:
:::
```

### Option details

#### `:type:`

Controls which entry types are displayed. By default, the directive excludes "separated types" (known issues, breaking changes, and deprecations) which are typically shown on their own dedicated pages.

| Value | Description |
|-------|-------------|
| (omitted) | Default: shows all types EXCEPT known issues, breaking changes, and deprecations |
| `all` | Shows all entry types including known issues, breaking changes, and deprecations |
| `breaking-change` | Shows only breaking change entries |
| `deprecation` | Shows only deprecation entries |
| `known-issue` | Shows only known issue entries |

This allows you to create separate pages for different entry types:

```markdown
# Release Notes

:::{changelog}
:::
```

```markdown
# Breaking Changes

:::{changelog}
:type: breaking-change
:::
```

```markdown
# Known Issues

:::{changelog}
:type: known-issue
:::
```

```markdown
# Deprecations

:::{changelog}
:type: deprecation
:::
```

To show all entries on a single page (previous default behavior):

```markdown
:::{changelog}
:type: all
:::
```

#### `:subsections:`

When enabled, entries are grouped by their area/component within each section. By default, entries are listed without area grouping (matching CLI behavior).

#### `:config:`

Explicit path to a `changelog.yml` configuration file. If not specified, the directive auto-discovers from:
1. `changelog.yml` in the docset root
2. `docs/changelog.yml` relative to docset root

The configuration can include publish blockers to filter entries by type or area.

## Filtering entries with publish blockers

You can filter changelog entries from the rendered output using the `block.publish` configuration in your `changelog.yml` file. This is useful for hiding entries that shouldn't appear in public documentation, such as internal changes or documentation-only updates.

### Configuration syntax

Create a `changelog.yml` file in your docset root (or `docs/changelog.yml`):

```yaml
block:
publish:
types:
- docs # Hide documentation entries
- regression # Hide regression entries
areas:
- Internal # Hide entries with "Internal" area
- Experimental # Hide entries with "Experimental" area
```

### Filtering by type

The `types` list filters entries based on their changelog entry type. Matching is **case-insensitive**.

| Type | Description |
|------|-------------|
| `feature` | New features |
| `enhancement` | Improvements to existing features |
| `security` | Security advisories and fixes |
| `bug-fix` | Bug fixes |
| `breaking-change` | Breaking changes |
| `deprecation` | Deprecated functionality |
| `known-issue` | Known issues |
| `docs` | Documentation changes |
| `regression` | Regressions |
| `other` | Other changes |

Example - hide documentation and regression entries:

```yaml
block:
publish:
types:
- docs
- regression
```

### Filtering by area

The `areas` list filters entries based on their area/component tags. An entry is blocked if **any** of its areas match a blocked area. Matching is **case-insensitive**.

Example - hide internal and experimental entries:

```yaml
block:
publish:
areas:
- Internal
- Experimental
- Testing
```

### Combining type and area filters

You can combine both `types` and `areas` filters. An entry is blocked if it matches **either** a blocked type **or** a blocked area.

```yaml
block:
publish:
types:
- docs
- deprecation
areas:
- Internal
```

This configuration will hide:
- All entries with type `docs` or `deprecation`
- All entries with the `Internal` area tag (regardless of type)

### Example: Cloud Serverless configuration

For Cloud Serverless releases where you want to hide certain entry types:

```yaml
# changelog.yml
block:
publish:
types:
- docs # Documentation changes handled separately
- deprecation # Deprecations shown on dedicated page
- known-issue # Known issues shown on dedicated page
```

## Private repository link hiding

PR and issue links are automatically hidden (commented out) for bundles from private repositories. This is determined by checking the `assembler.yml` configuration:

- Repositories marked with `private: true` in `assembler.yml` will have their links hidden
- For merged bundles (e.g., `elasticsearch+kibana`), links are hidden if ANY component repository is private
- In standalone builds without `assembler.yml`, all links are shown by default

## Bundle merging

Bundles with the same target version/date are automatically merged into a single section. This is useful for Cloud Serverless releases where multiple repositories (e.g., Elasticsearch, Kibana) contribute to a single dated release like `2025-08-05`.

## Default folder structure

The directive expects bundles in `changelog/bundles/` relative to the docset root:
Expand Down
5 changes: 5 additions & 0 deletions docs/testing/release-notes/breaking-changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Breaking Changes

:::{changelog}
:type: breaking-change
:::
5 changes: 5 additions & 0 deletions docs/testing/release-notes/deprecations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Deprecations

:::{changelog}
:type: deprecation
:::
4 changes: 4 additions & 0 deletions docs/testing/release-notes/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Release Notes

:::{changelog}
:::
5 changes: 5 additions & 0 deletions docs/testing/release-notes/known-issues.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Known Issues

:::{changelog}
:type: known-issue
:::
Original file line number Diff line number Diff line change
Expand Up @@ -2,63 +2,44 @@
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using Elastic.Documentation.ReleaseNotes;

namespace Elastic.Documentation.Configuration.Changelog;

/// <summary>
/// Combined block configuration for create and publish blockers
/// Combined block configuration for create and publish blockers.
/// </summary>
public record BlockConfiguration
{
/// <summary>
/// Global labels that block changelog creation
/// Global labels that block changelog creation.
/// </summary>
public IReadOnlyList<string>? Create { get; init; }

/// <summary>
/// Global configuration for blocking changelog entries from publishing based on type or area
/// Global configuration for blocking changelog entries from publishing based on type or area.
/// </summary>
public PublishBlocker? Publish { get; init; }

/// <summary>
/// Per-product block overrides (overrides global blockers, does not merge)
/// Keys are product IDs
/// Per-product block overrides (overrides global blockers, does not merge).
/// Keys are product IDs.
/// </summary>
public IReadOnlyDictionary<string, ProductBlockers>? ByProduct { get; init; }
}

/// <summary>
/// Product-specific blockers
/// Product-specific blockers.
/// </summary>
public record ProductBlockers
{
/// <summary>
/// Labels that block creation for this product (overrides global create blockers)
/// Labels that block creation for this product (overrides global create blockers).
/// </summary>
public IReadOnlyList<string>? Create { get; init; }

/// <summary>
/// Configuration for blocking changelog entries from publishing based on type or area
/// Configuration for blocking changelog entries from publishing based on type or area.
/// </summary>
public PublishBlocker? Publish { get; init; }
}

/// <summary>
/// Configuration for blocking changelog entries from publishing based on type or area
/// </summary>
public record PublishBlocker
{
/// <summary>
/// Entry types to block from publishing (e.g., "deprecation", "known-issue")
/// </summary>
public IReadOnlyList<string>? Types { get; init; }

/// <summary>
/// Entry areas to block from publishing (e.g., "Internal", "Experimental")
/// </summary>
public IReadOnlyList<string>? Areas { get; init; }

/// <summary>
/// Returns true if this blocker has any blocking rules configured
/// </summary>
public bool HasBlockingRules => (Types?.Count > 0) || (Areas?.Count > 0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,37 @@

using YamlDotNet.Serialization;

namespace Elastic.Changelog.Serialization;
namespace Elastic.Documentation.Configuration.ReleaseNotes;

/// <summary>
/// Internal DTO for YAML serialization of bundled changelog data.
/// DTO for YAML serialization of bundled changelog data.
/// Maps directly to the bundle YAML file structure.
/// </summary>
internal record BundleYaml
public sealed record BundleDto
{
public List<BundledProductYaml>? Products { get; set; }
public List<BundledEntryYaml>? Entries { get; set; }
public List<BundledProductDto>? Products { get; set; }
public List<BundledEntryDto>? Entries { get; set; }
}

/// <summary>
/// Internal DTO for bundled product info in YAML.
/// DTO for bundled product info in YAML.
/// </summary>
internal record BundledProductYaml
public sealed record BundledProductDto
{
public string? Product { get; set; }
public string? Target { get; set; }
public string? Lifecycle { get; set; }
}

/// <summary>
/// Internal DTO for bundled entry in YAML.
/// DTO for bundled entry in YAML.
/// </summary>
internal record BundledEntryYaml
public sealed record BundledEntryDto
{
public BundledFileYaml? File { get; set; }
public BundledFileDto? File { get; set; }
public string? Type { get; set; }
public string? Title { get; set; }
public List<ProductInfoYaml>? Products { get; set; }
public List<ProductInfoDto>? Products { get; set; }
public string? Description { get; set; }
public string? Impact { get; set; }
public string? Action { get; set; }
Expand All @@ -48,9 +48,9 @@ internal record BundledEntryYaml
}

/// <summary>
/// Internal DTO for bundled file info in YAML.
/// DTO for bundled file info in YAML.
/// </summary>
internal record BundledFileYaml
public sealed record BundledFileDto
{
public string? Name { get; set; }
public string? Checksum { get; set; }
Expand Down
Loading
Loading