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
13 changes: 6 additions & 7 deletions config/changelog.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -258,17 +258,18 @@ bundle:
# docs-builder changelog bundle elasticsearch-release 9.2.0
# docs-builder changelog remove elasticsearch-release 9.2.0
# When used with 'changelog remove', only the 'products' field is applied.
# The 'output', 'output_products', 'repo', 'owner', and 'hide_features' fields are
# The 'output_products', 'repo', 'owner', and 'hide_features' fields are
# bundle-specific and are ignored for removal.
# Bundle file names are derived by convention as '{product}-{version}.yaml' from the
# profile's primary output product; setting an explicit 'output' pattern is an error.
profiles:
# Example: Elasticsearch release profile (filter by changelog fields)
# elasticsearch-release:
# # Filter: which input changelogs to include ({version} and {lifecycle} are substituted at runtime)
# products: "elasticsearch {version} {lifecycle}"
# # Output filename ({version} is substituted at runtime)
# output: "elasticsearch-{version}.yaml"
# # Optional: override the products array written to the bundle output.
# # output_products: "elasticsearch {version}"
# # The bundle's products metadata; also determines the conventional output
# # file name ({product}-{version}.yaml from the first product).
# output_products: "elasticsearch {version}"
# # Optional: profile-specific description (overrides bundle.description)
# # description: |
# # Elasticsearch {version} includes:
Expand All @@ -285,12 +286,10 @@ bundle:
# source: github_release # Fetch PR list from GitHub release instead of filtering input changelogs
# repo: elasticsearch # GitHub repository (required if bundle.repo is not set)
# owner: elastic # GitHub owner (optional; defaults to bundle.owner or "elastic")
# output: "elasticsearch-{version}.yaml"
# output_products: "elasticsearch {version} {lifecycle}"

# Example: Serverless release profile (filter by promotion report, PR, or issue list)
# serverless-release:
# output: "serverless-{version}.yaml"
# output_products: "cloud-serverless {version}" # omit lifecycle
# # output_products: "cloud-serverless {version} {lifecycle}" # derive (ga for ISO dates)
# # output_products: "cloud-serverless {version} preview" # hardcode for exceptional releases
Expand Down
2 changes: 1 addition & 1 deletion docs/cli-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3140,7 +3140,7 @@
"name": "output",
"type": "string",
"required": false,
"summary": "Output path for the bundled changelog (directory or .yml/.yaml file). Uses config bundle.output_directory or defaults to \u0027changelog-bundle.yaml\u0027 in the input directory. This option is not supported in profile-based commands. The equivalent configuration option is bundle.profiles.\u003Cname\u003E.output."
"summary": "Output path for the bundled changelog (directory or .yml/.yaml file). Uses config bundle.output_directory or defaults to \u0027changelog-bundle.yaml\u0027 in the input directory. This option is not supported in profile-based commands, where bundle names are derived by convention as {product}-{version}.yaml from the profile\u0027s primary output product."
},
{
"role": "flag",
Expand Down
7 changes: 4 additions & 3 deletions docs/cli/changelog/cmd-bundle.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The second positional argument accepts:
- A plain-text URL list file (one fully-qualified GitHub PR or issue URL per line)
- A plain-text path list file (one changelog YAML path per line, ending in `.yaml` or `.yml`)

When your profile uses `{version}` in its output pattern and you also want to filter by a report or list file, pass both arguments (version first, then the filter file).
When your profile uses `{version}` in its `output_products` pattern (or you want the conventional `{product}-{version}.yaml` bundle name) and you also want to filter by a report or list file, pass both arguments (version first, then the filter file).

Example profile in `changelog.yml`:

Expand All @@ -33,10 +33,11 @@ bundle:
profiles:
elasticsearch-release:
products: "elasticsearch {version} {lifecycle}"
output: "elasticsearch/{version}.yaml"
output_products: "elasticsearch {version}"
```

The bundle's file name is derived by convention as `{product}-{version}.yaml` from the profile's primary output product and the version argument (for example, `docs/releases/elasticsearch-9.2.0.yaml`). Setting an explicit `output` pattern on a profile is a hard error, and no two profiles may share a primary output product — they would collide on the same conventional target.

## Option-based mode

Supply filter flags directly when you don't have a profile configured or need a one-off bundle.
Expand Down Expand Up @@ -96,7 +97,7 @@ Both refs are always required together — the start ref is never inferred from
- **PRs whose metadata cannot be fetched are reported as missing** with a warning.
4. Records the end ref in the bundle output as the `git_ref` metadata field.

Commit-range mode works in both profile-based and option-based commands and is mutually exclusive with every other filter. In profile-based commands the profile contributes output metadata only (`output_products`, `repo`, `owner`, `rules`, and so on) — it must not set a `products` pattern or `source: github_release`. When the profile has no explicit `output` pattern, the bundle name follows the `{product}-{version}.yaml` convention.
Commit-range mode works in both profile-based and option-based commands and is mutually exclusive with every other filter. In profile-based commands the profile contributes output metadata only (`output_products`, `repo`, `owner`, `rules`, and so on) — it must not set a `products` pattern or `source: github_release`. The bundle name follows the `{product}-{version}.yaml` convention.

Re-running the same range produces the same bundle content; bundling never overwrites changelog entries.

Expand Down
23 changes: 7 additions & 16 deletions docs/data/release-notes/bundle.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,14 @@ bundle:
owner: elastic
profiles:
serverless-report:
output: "serverless/{version}.yaml" <3>
output_products: "cloud-serverless {version}" <4>
output_products: "cloud-serverless {version}" <3>
elasticsearch-release:
output: "elasticsearch/{version}.yaml"
output_products: "elasticsearch {version} {lifecycle}"
```

1. The directory that contains changelog files.
2. The directory that contains changelog bundles.
3. If `output` is omitted, the default path and file names are used. This example shows how you can use a `{version}` variable to customize the bundle's filename.
4. The bundle's product metadata, which affects the rules that are applied and the product and version titles that ultimately appear in the documentation. If omitted, it's derived from all the changelogs in the bundle.
3. The bundle's product metadata, which affects the rules that are applied and the product and version titles that ultimately appear in the documentation. If omitted, it's derived from all the changelogs in the bundle. The first product also determines the bundle's file name, which is derived by convention as `{product}-{version}.yaml` under `output_directory`.

### Bundle by GitHub releases [profile-gh-release]

Expand All @@ -105,12 +102,11 @@ bundle:
source: github_release <1>
repo: apm-agent-dotnet
owner: elastic
output: "agent-{version}.yaml"
output_products: "apm-agent-dotnet {version} {lifecycle}" <2>
```

1. This profile fetches the PR list from the GitHub release notes for the version tag specified in the command.
2. For `source: github_release` profiles, the `{lifecycle}` placeholder in `output` and `output_products` is inferred from full release tag name. For example, if the release tag is `v1.34.1-preview.1` the lifecycle is `preview`. Refer to [](/cli/changelog/bundle.md#lifecycle-inference) for more details.
2. For `source: github_release` profiles, the `{lifecycle}` placeholder in `output_products` is inferred from full release tag name. For example, if the release tag is `v1.34.1-preview.1` the lifecycle is `preview`. Refer to [](/cli/changelog/bundle.md#lifecycle-inference) for more details.

### Bundle by git commit range [profile-git-range]

Expand All @@ -129,7 +125,7 @@ bundle:
```

1. The authoring repository whose commit range is resolved and whose entry pool is consulted.
2. Also applied to entries synthesized from PR metadata when the PR's labels map to no product. When the profile has no `output` pattern, the bundle is named `{product}-{version}.yaml` by convention.
2. Also applied to entries synthesized from PR metadata when the PR's labels map to no product. The bundle is named `{product}-{version}.yaml` by convention.

```sh
docs-builder changelog bundle serverless-release 2026-08-13 \
Expand Down Expand Up @@ -159,26 +155,22 @@ bundle:
# Collect all changelogs
release-all:
products: "* * *" <1>
output: "all.yaml"
# Find changelogs with any lifecycle and a partial date
serverless-monthly:
products: "cloud-serverless {version}-* *" <2>
output: "serverless-{version}.yaml"
output_products: "cloud-serverless {version}"
# Find changelogs with a specific lifecycle
elasticsearch-ga-only:
products: "elasticsearch {version} ga" <3>
output: "elasticsearch-{version}.yaml"
kibana-ga-only:
products: "kibana {version} ga" <3>
# Infer the lifecycle from the version
elasticsearch-with-lifecycle:
products: "elasticsearch {version} {lifecycle}" <4>
output: "elasticsearch-{version}.yaml"
output_products: "elasticsearch {version}"
```

1. This profile collects all changelogs from the `directory`.
2. This profile collects any changelogs that have `product: cloud-serverless`, any lifecycle, and the date partially specified in the command.
3. This profile collects any changelogs that have `product: elasticsearch`, `lifecycle: ga`, and the version specified in the command.
3. This profile collects any changelogs that have `product: kibana`, `lifecycle: ga`, and the version specified in the command. No two profiles may target the same primary product — they would collide on the same conventional `{product}-{version}.yaml` bundle name.
4. In this case, the lifecycle is inferred from the version specified in the command. For example, if the version is `9.2.0-beta.1` the lifecycle is `beta`. ISO date arguments (for example, `2026-07-21`) derive `ga`. Refer to [](/cli/changelog/bundle.md#lifecycle-inference).

For date-based and semver profiles, lifecycle is controlled only in the profile YAML: omit it from the pattern, use `{lifecycle}` to derive it, or hardcode `ga`, `beta`, or `preview`. Non-`ga` date-based releases are exceptional and should hardcode the lifecycle.
Expand Down Expand Up @@ -432,7 +424,6 @@ bundle:
owner: elastic
profiles:
serverless-report:
output: "serverless/{version}.yaml"
output_products: "cloud-serverless {version}"
hide_features: <1>
- feature-flag-1
Expand Down
8 changes: 3 additions & 5 deletions docs/data/release-notes/configure-ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,9 @@ These settings are located in the `bundle.profiles.<name>` section of the config
: When the bundle is rendered, entries with matching `feature-id` values are commented out.

`output`
: The output filename pattern for the bundle file.
: Supports `{version}` and `{lifecycle}` placeholders.
: When not set, the output path falls back in order to: `bundle.output_directory/changelog-bundle.yaml` (if `bundle.output_directory` is configured), then `changelog-bundle.yaml` in the input directory.
: Setting this is recommended so each profile produces a distinctly named file rather than overwriting the default.
: Example: `"elasticsearch/{version}.yaml"`
: Removed. Bundle output names are derived by convention as `{product}-{version}.yaml` from the profile's primary output product (the first product in `output_products`, or `products`) and the version argument. Setting `output` on any profile is a hard error at bundle time; remove the field.
: When no primary product or version resolves (for example, a promotion-report invocation without a version argument), the output path falls back in order to: `bundle.output_directory/changelog-bundle.yaml` (if `bundle.output_directory` is configured), then `changelog-bundle.yaml` in the input directory.
: No two profiles in the same configuration may share a primary output product — they would resolve to the same `{product}-{version}.yaml` target for any given version, which is also a hard error.

`output_products`
: The bundle's `products` metadata, which affects the bundle rules that are applied and the product and version titles that ultimately appear in documentation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,13 @@ public record BundleProfile
public string? Products { get; init; }

/// <summary>
/// Output filename pattern.
/// {version} is substituted at runtime.
/// Examples:
/// - "elasticsearch-{version}.yaml"
/// - "serverless-{version}.yaml"
/// Legacy output filename pattern. No longer supported: bundle output names are derived by
/// convention as <c>{product}-{version}.yaml</c> from the profile's primary output product
/// (elastic/docs-builder#3774). Any profile setting this is a hard error at bundle time; the
/// field remains parseable for one release cycle so authors get an actionable error rather
/// than a YAML parse failure.
/// </summary>
[Obsolete("No longer supported: bundle output names are derived by convention as '{product}-{version}.yaml' from the profile's output_products. Setting 'output' is a hard error at bundle time.")]
public string? Output { get; init; }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

also add `[Obsolete()] maybe?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 6ac9142 — added [Obsolete] with a message pointing at the convention, and suppressed CS0618 at the two intentional read sites (loader + hard-error validation) since warnings are errors here.


/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,9 @@ private static PivotConfiguration ConvertPivot(PivotConfigurationYaml yamlPivot)
: new BundleProfile
{
Products = kvp.Value.Products,
#pragma warning disable CS0618 // Output stays parseable for one release cycle so ValidateProfileOutputs can emit an actionable error
Output = kvp.Value.Output,
#pragma warning restore CS0618
OutputProducts = kvp.Value.OutputProducts,
Description = kvp.Value.Description,
Repo = kvp.Value.Repo,
Expand Down
Loading
Loading