diff --git a/config/changelog.example.yml b/config/changelog.example.yml index 82c75e76c..7a104d852 100644 --- a/config/changelog.example.yml +++ b/config/changelog.example.yml @@ -150,7 +150,7 @@ pivot: # - Comma-separated string: "value1, value2, value3" # - YAML list: [value1, value2, value3] # -# For details and examples, refer to the [rules documentation](https://github.com/elastic/docs-builder/blob/main/docs/contribute/changelog.md#rules-for-creation-and-bundling). +# For details and examples, refer to the [rules documentation](https://github.com/elastic/docs-builder/blob/main/docs/contribute/configure-changelogs.md#rules). rules: # match: any @@ -169,7 +169,7 @@ rules: # exclude: "ILM" # Bundle — filtering applied during 'changelog bundle' and 'changelog gh-release'. - # See docs/contribute/changelog.md → "Bundle rule modes" for Mode 1 / 2 / 3 behavior. + # See https://github.com/elastic/docs-builder/blob/main/docs/contribute/configure-changelogs.md#bundle-rule-modes for Mode 1 / 2 / 3 behavior. # # Mode 2 (global content): use global lists only — no `products` key, or `products: {}`. # Example — include changelogs that list elasticsearch OR kibana (evaluated per changelog): @@ -213,7 +213,7 @@ bundle: # Whether to resolve (copy contents) by default resolve: true # Optional: default description text for bundles. Supports {version}, {lifecycle}, {owner}, and {repo} placeholders. - # Use YAML literal block scalar (|) for multiline descriptions. See docs/contribute/changelog.md for examples. + # Use YAML literal block scalar (|) for multiline descriptions. # description: | # This release includes new features and bug fixes. # diff --git a/docs/_docset.yml b/docs/_docset.yml index 51e6514e5..b76855fdb 100644 --- a/docs/_docset.yml +++ b/docs/_docset.yml @@ -69,6 +69,11 @@ toc: - file: add-repo.md - file: release-new-version.md - file: changelog.md + children: + - file: configure-changelogs.md + - file: create-changelogs.md + - file: bundle-changelogs.md + - file: publish-changelogs.md - hidden: locally.md - hidden: on-the-web.md - folder: building-blocks diff --git a/docs/cli/changelog/add.md b/docs/cli/changelog/add.md index db17e19e3..23fe870fe 100644 --- a/docs/cli/changelog/add.md +++ b/docs/cli/changelog/add.md @@ -1,7 +1,7 @@ # changelog add Create a changelog file that describes a single item in the release documentation. -For details and examples, go to [](/contribute/changelog.md). +For details and examples, go to [](/contribute/create-changelogs.md). ## Usage @@ -169,3 +169,19 @@ When you run the `changelog add` command without the `--products` option, it res 5. **Error** — if none of the above resolves to at least one product, an error is raised. Product-specific `rules.create` rules are evaluated *after* products are resolved from labels, so label-derived products correctly participate in per-product create rule checks. + +## Configuration checks + +By default, the command checks the following path for a configuration file: `docs/changelog.yml`. +You can specify a different path with the `--config` command option. + +If a configuration file exists, the command validates its values before generating changelog files: + +- If the configuration file contains `lifecycles`, `products`, `subtype`, or `type` values that don't match the values in `ChangelogEntryType.cs`, `ChangelogEntrySubtype.cs`, or `Lifecycle.cs`, validation fails. +- If the configuration file contains `areas` values and they don't match what you specify in the `--areas` command option, validation fails. +- If the configuration file contains `lifecycles` or `products` values that are a subset of the available values and you try to create a changelog with values outside that subset, validation fails. + +In each of these cases where validation fails, a changelog file is not created. + +If the configuration file contains `rules.create` definitions and a PR or issue has a blocking label, that PR is skipped and no changelog file is created for it. +For more information, refer to [Rules for creation and publishing](/contribute/configure-changelogs.md#rules). diff --git a/docs/cli/changelog/bundle-amend.md b/docs/cli/changelog/bundle-amend.md index f32c740e0..03ccb615b 100644 --- a/docs/cli/changelog/bundle-amend.md +++ b/docs/cli/changelog/bundle-amend.md @@ -4,7 +4,7 @@ Amend a bundle with additional changelog entries. Amend bundles follow a specific naming convention: `{parent-bundle-name}.amend-{N}.yaml` where `{N}` is a sequence number. To create a bundle, use [](/cli/changelog/bundle.md). -For details and examples, go to [](/contribute/changelog.md). +For details and examples, go to [](/contribute/bundle-changelogs.md). ## Usage diff --git a/docs/cli/changelog/bundle.md b/docs/cli/changelog/bundle.md index 2a62695af..1fa907213 100644 --- a/docs/cli/changelog/bundle.md +++ b/docs/cli/changelog/bundle.md @@ -93,7 +93,7 @@ You must choose one method for determining what's in the bundle (`--all`, `--inp `--input-products ?>` : Filter by products in the format "product target lifecycle, ...". -: For more information about the valid product and lifecycle values, go to [Product format](/contribute/changelog.md#product-format). +: For more information about the valid product and lifecycle values, go to [Product format](/contribute/create-changelogs.md#product-format). : When specified, all three parts (product, target, lifecycle) are required but can be wildcards (`*`). Multiple comma-separated values are combined with OR: a changelog is included if it matches any of the specified product/target/lifecycle combinations. For example: - `"cloud-serverless 2025-12-02 ga, cloud-serverless 2025-12-06 beta"` — include changelogs for either cloud-serverless 2025-12-02 ga or cloud-serverless 2025-12-06 beta @@ -103,7 +103,7 @@ You must choose one method for determining what's in the bundle (`--all`, `--inp - `"* * *"` - match all changelogs (equivalent to `--all`) :::{note} -The `--input-products` option determines which changelog files are gathered for consideration. **`rules.bundle` is not disabled** when you use `--input-products` — global `include_products` / `exclude_products`, type/area rules, and (when configured) per-product rules still run **after** matching, unless your configuration is in [no-filtering mode](/contribute/changelog.md#bundle-rule-modes). The only “mutually exclusive” pairing on this command is **profile-based** bundling versus **option-based** flags (see [Usage](#usage)), not `--input-products` versus `rules.bundle`. +The `--input-products` option determines which changelog files are gathered for consideration. **`rules.bundle` is not disabled** when you use `--input-products` — global `include_products` / `exclude_products`, type/area rules, and (when configured) per-product rules still run **after** matching, unless your configuration is in [no-filtering mode](/contribute/configure-changelogs.md#bundle-rule-modes). The only “mutually exclusive” pairing on this command is **profile-based** bundling versus **option-based** flags (see [Usage](#usage)), not `--input-products` versus `rules.bundle`. ::: `--issues ` @@ -122,7 +122,7 @@ The `--input-products` option determines which changelog files are gathered for `--output-products ?>` : Optional: Explicitly set the products array in the output file in format "product target lifecycle, ...". : This value replaces information that would otherwise be derived from changelogs. -: When `rules.bundle.products` per-product overrides are configured, `--output-products` also supplies the product IDs used to choose the **rule context product** (first alphabetically) for Mode 3. To use a different product's rules, run a separate bundle with only that product in `--output-products`. For details, refer to [Single-product rule resolution algorithm](/contribute/changelog.md#changelog-bundle-rule-resolution). +: When `rules.bundle.products` per-product overrides are configured, `--output-products` also supplies the product IDs used to choose the **rule context product** (first alphabetically) for Mode 3. To use a different product's rules, run a separate bundle with only that product in `--output-products`. For details, refer to [Product-specific bundle rules](/contribute/configure-changelogs.md#rules-bundle-products). `--owner ` : Optional: The GitHub repository owner, required when pull requests or issues are specified as numbers. @@ -243,7 +243,7 @@ This may result in broken links if the product ID doesn't match the GitHub repos The `rules.bundle` section in the changelog configuration file lets you filter entries during bundling. It applies to both `changelog bundle` and `changelog gh-release`, after entries are matched by the primary filter (`--prs`, `--issues`, `--all`, **`--input-products`**, and so on) and before the bundle is written. -Which `rules.bundle` fields take effect depends on the [bundle rule modes](/contribute/changelog.md#bundle-rule-modes) (no filtering, global rules against each changelog’s content, or per-product rule context). Input stage (gathering entries) and bundle filtering stage (filtering for output) are conceptually separate. +Which `rules.bundle` fields take effect depends on the [bundle rule modes](/contribute/configure-changelogs.md#bundle-rule-modes) (no filtering, global rules against each changelog’s content, or per-product rule context). Input stage (gathering entries) and bundle filtering stage (filtering for output) are conceptually separate. The following fields are supported: @@ -272,7 +272,7 @@ The following fields are supported: : Match mode for the area filter (`any`, `all`, or `conjunction`). Inherits from `rules.match` when not specified. `products` -: Per-product filter overrides for **all filter types** (product, type, area). Keys are product IDs (or comma-separated lists). When this map is **non-empty**, the bundler uses **per-product rule context** mode: global `rules.bundle` product/type/area fields are **not** used for filtering (repeat constraints under each product key if you still need them). For details, refer to [Bundle rule modes](/contribute/changelog.md#bundle-rule-modes) and [Single-product rule resolution (Mode 3 only)](/contribute/changelog.md#changelog-bundle-rule-resolution). +: Per-product filter overrides for **all filter types** (product, type, area). Keys are product IDs (or comma-separated lists). When this map is **non-empty**, the bundler uses **per-product rule context** mode: global `rules.bundle` product/type/area fields are **not** used for filtering (repeat constraints under each product key if you still need them). For details, refer to [Bundle rule modes](/contribute/configure-changelogs.md#bundle-rule-modes) and [Product-specific bundle rules](/contribute/configure-changelogs.md#rules-bundle-products). ```yaml rules: @@ -448,7 +448,7 @@ If your configuration file defines a standard profile (that is to say, not a Git | `9.2.0-alpha.1` | `preview` | | `9.2.0-preview.1` | `preview` | -For more information about acceptable product and lifecycle values, go to [Product format](/contribute/changelog.md#product-format). +For more information about acceptable product and lifecycle values, go to [Product format](/contribute/create-changelogs.md#product-format). You can invoke those profiles with commands like this: diff --git a/docs/cli/changelog/gh-release.md b/docs/cli/changelog/gh-release.md index 0c36ec80a..b48020ce3 100644 --- a/docs/cli/changelog/gh-release.md +++ b/docs/cli/changelog/gh-release.md @@ -58,9 +58,9 @@ The product, target version, and lifecycle are inferred automatically from the r ## Configuration The `rules.bundle` section of your `changelog.yml` applies to bundles created by this command (after changelog files are gathered from the release). -Which fields take effect depends on [bundle rule modes](/contribute/changelog.md#bundle-rule-modes). +Which fields take effect depends on [bundle rule modes](/contribute/configure-changelogs.md#bundle-rule-modes). For details, refer to [Rules for filtered bundles](/cli/changelog/bundle.md#changelog-bundle-rules). -If you use per-product rule overrides, refer to [Single-product rule resolution (Mode 3 only)](/contribute/changelog.md#changelog-bundle-rule-resolution). +If you use per-product rule overrides, refer to [Product-specific bundle rules](/contribute/configure-changelogs.md#rules-bundle-products). ## Examples diff --git a/docs/cli/changelog/remove.md b/docs/cli/changelog/remove.md index 77a58fd40..ddaa310ac 100644 --- a/docs/cli/changelog/remove.md +++ b/docs/cli/changelog/remove.md @@ -11,7 +11,7 @@ These modes are mutually exclusive. You can't combine a profile argument with th Before deleting anything, the command checks whether any of the matching files are referenced by unresolved bundles, to prevent silently breaking the `{changelog}` directive. -For more context, go to [](/contribute/changelog.md#changelog-remove). +For more context, go to [](/contribute/bundle-changelogs.md#changelog-remove). ## Usage diff --git a/docs/cli/changelog/render.md b/docs/cli/changelog/render.md index 81c756e27..9ad7ac343 100644 --- a/docs/cli/changelog/render.md +++ b/docs/cli/changelog/render.md @@ -3,7 +3,7 @@ Generate markdown or asciidoc files from changelog bundle files. To create the bundle files, use [](/cli/changelog/bundle.md). -For details and examples, go to [](/contribute/changelog.md). +For details and examples, go to [](/contribute/publish-changelogs.md). ## Usage @@ -60,7 +60,7 @@ The `render` command automatically discovers and merges `.amend-*.yaml` files wi : Defaults to the version in the first bundle. : 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/changelog.md). For how the directive differs, see the [{changelog} directive syntax reference](/syntax/changelog.md). +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). ## Output formats diff --git a/docs/contribute/bundle-changelogs.md b/docs/contribute/bundle-changelogs.md new file mode 100644 index 000000000..2086735c3 --- /dev/null +++ b/docs/contribute/bundle-changelogs.md @@ -0,0 +1,596 @@ +# Bundle changelogs + +You can use the `docs-builder changelog bundle` command to create a YAML file that lists multiple changelogs. +The command has two modes of operation: you can specify all the command options or you can define "profiles" in the changelog configuration file. +The latter is more convenient and consistent for repetitive workflows. +For up-to-date details, use the `-h` option or refer to [](/cli/changelog/bundle.md). + +The command supports two mutually exclusive usage modes: + +- **Option-based** — you provide filter and output options directly on the command line. +- **Profile-based** — you specify a named profile from your `changelog.yml` configuration file. + +You cannot mix these two modes: when you use a profile name, no filter or output options are accepted on the command line. + +:::{tip} +Alternatively, if you already have automated release notes for GitHub releases, you can use the `docs-builder changelog gh-release` command to create changelog files and a bundle from your GitHub release notes. Refer to [](/cli/changelog/gh-release.md). +::: + +## Option-based bundling [changelog-bundle-options] + +You can specify only one of the following filter options: + +- `--all`: Include all changelogs from the directory. +- `--input-products`: Include changelogs for the specified products. Refer to [Filter by product](#changelog-bundle-product). +- `--prs`: Include changelogs for the specified pull request URLs, or a path to a newline-delimited file. When using a file, every line must be a fully-qualified GitHub URL such as `https://github.com/owner/repo/pull/123`. Go to [Filter by pull requests](#changelog-bundle-pr). +- `--issues`: Include changelogs for the specified issue URLs, or a path to a newline-delimited file. When using a file, every line must be a fully-qualified GitHub URL such as `https://github.com/owner/repo/issues/123`. Go to [Filter by issues](#changelog-bundle-issues). +- `--release-version`: Bundle changelogs for the pull requests in GitHub release notes. Refer to [Bundle by GitHub release](#changelog-bundle-release-version). +- `--report`: Include changelogs whose pull requests appear in a promotion report. Accepts a URL or a local file path to an HTML report. + +`rules.bundle` in `changelog.yml` is **not** mutually exclusive with these options: it runs as a **second stage** after the primary filter matches entries (for example, `--input-products` gathers changelogs, then global or per-product bundle rules may exclude some). The only mutually exclusive pairing is **profile-based** versus **option-based** invocation. See [bundle rule modes](/contribute/configure-changelogs.md#bundle-rule-modes). + +By default, the output file contains only the changelog file names and checksums. +To change this behavior, set `bundle.resolve` to `true` in the changelog configuration file or use the `--resolve` command option. + +:::{tip} +If you plan to use [changelog directives](/contribute/publish-changelogs.md#changelog-directive), it is recommended to pull all of the content from each changelog into the bundle; otherwise you can't delete your changelogs. +If you likewise want to regenerate your [Asciidoc or Markdown files](/contribute/publish-changelogs.md#render-changelogs) after deleting your changelogs, it's only possible if you have "resolved" bundles. +::: + + + +## Profile-based bundling [changelog-bundle-profile] + +If your `changelog.yml` configuration file defines `bundle.profiles`, you can run a bundle by profile name instead of supplying individual options: + +```sh +docs-builder changelog bundle +``` + +The second argument accepts a version string, a promotion report URL/path, or a URL list file (a plain-text file with one fully-qualified GitHub URL per line). When your profile uses `{version}` in its `output` or `output_products` pattern and you also want to filter by a report, pass both. +For example: + +```sh +# Standard profile: lifecycle is inferred from the version string +docs-builder changelog bundle elasticsearch-release 9.2.0 # {lifecycle} → "ga" +docs-builder changelog bundle elasticsearch-release 9.2.0-beta.1 # {lifecycle} → "beta" + +# Standard profile: filter by a promotion report (version used for {version}) +docs-builder changelog bundle elasticsearch-release ./promotion-report.html +docs-builder changelog bundle elasticsearch-release 9.2.0 ./promotion-report.html +``` + + + +Top-level `bundle` fields: + +| Field | Description | +|---|---| +| `repo` | Default GitHub repository name applied to all profiles. Falls back to product ID if not set at any level. | +| `owner` | Default GitHub repository owner applied to all profiles. | +| `resolve` | When `true`, embeds full changelog entry content in the bundle (same as `--resolve`). Required when `link_allow_repos` is set. | +| `link_allow_repos` | When set (including an empty list), only PR/issue links whose resolved repository is in this `owner/repo` list are kept; others are rewritten to `# PRIVATE:` sentinels in bundle YAML. When absent, no link filtering is applied. Requires `resolve: true`. Refer to [PR and issue link allowlist](/cli/changelog/bundle.md#link-allowlist). | + +Profile configuration fields in `bundle.profiles`: + +| Field | Description | +|---|---| +| `source` | Optional. Set to `github_release` to fetch the PR list from a GitHub release. Mutually exclusive with `products`. Requires `repo` at the profile or `bundle` level. | +| `products` | Product filter pattern with `{version}` and `{lifecycle}` placeholders. Used to match changelog files. Required when filtering by product metadata. Not used when the filter comes from a promotion report, URL list file, or `source: github_release`. | +| `output` | Output file path pattern with `{version}` and `{lifecycle}` placeholders. | +| `output_products` | Optional override for the products array written to the bundle. Useful when the bundle should have a single product ID though it's filtered from many or have a different lifecycle or version than the filter. With multiple product IDs, Mode 3 rule resolution uses the first alphabetically; use separate profiles or bundle runs with a single product in `output_products` when you need a different rule context. | +| `repo` | Optional. Overrides `bundle.repo` for this profile only. Required when `source: github_release` is used and no `bundle.repo` is set. | +| `owner` | Optional. Overrides `bundle.owner` for this profile only. | +| `hide_features` | List of feature IDs to embed in the bundle as hidden. | + +Example profile configuration: + +```yaml +bundle: + repo: elasticsearch # The default repository for PR and issue links. + owner: elastic # The default repository owner for PR and issue links. + directory: docs/changelog # The directory that contains changelog files. + output_directory: docs/releases # The directory that contains changelog bundles. + # Optional: Default bundle description with placeholder support + description: | + This release includes new features and bug fixes. + + For more information, see the [release notes](https://www.elastic.co/docs/release-notes/elasticsearch#elasticsearch-{version}). + profiles: + elasticsearch-release: + products: "elasticsearch {version} {lifecycle}" + output: "elasticsearch/{version}.yaml" + output_products: "elasticsearch {version}" + # Profile-specific description overrides bundle.description + description: | + Elasticsearch {version} includes: + - Performance improvements + - Bug fixes and stability enhancements + + Download the release binaries: https://github.com/{owner}/{repo}/releases/tag/v{version} + hide_features: + - feature:experimental-api + serverless-release: + products: "cloud-serverless {version} *" + output: "serverless/{version}.yaml" + output_products: "cloud-serverless {version}" + # inherits repo: elasticsearch and owner: elastic from bundle level + # Multi-product profile: rule context for Mode 3 is the first product alphabetically (here: kibana). + # For security-specific rules only, use a separate profile with output_products listing only security. + kibana-security-release: + products: "kibana {version} {lifecycle}, security {version} {lifecycle}" + output: "kibana-security/{version}.yaml" + output_products: "kibana {version}, security {version}" +``` + +### Bundle changelogs from a GitHub release [changelog-bundle-profile-github-release] + +Set `source: github_release` on a profile to make `changelog bundle` fetch the PR list directly from a published GitHub release. + +This is equivalent to running `changelog bundle --release-version `, but fully configured in `changelog.yml` so you don't have to remember command-line flags. + +```yaml +bundle: + owner: elastic + profiles: + agent-gh-release: + source: github_release + repo: apm-agent-dotnet + output: "my-agents-{version}.yaml" + output_products: "apm-agent-dotnet {version} {lifecycle}" +``` + +Invoke the profile with a version tag or `latest`: + +```sh +docs-builder changelog bundle agent-gh-release 1.34.0 +docs-builder changelog bundle agent-gh-release latest +``` + +The `{version}` placeholder is substituted with the clean base version extracted from the release tag (for example, `v1.34.0` → `1.34.0`, `v1.34.0-beta.1` → `1.34.0`). The `{lifecycle}` placeholder is inferred from the **release tag** returned by GitHub, not from the argument you pass to the command: + +| Release tag | `{version}` | `{lifecycle}` | +|-------------|-------------|---------------| +| `v1.2.3` | `1.2.3` | `ga` | +| `v1.2.3-beta.1` | `1.2.3` | `beta` | +| `v1.2.3-preview.1` | `1.2.3` | `preview` | + +This differs from standard profiles, where `{lifecycle}` is inferred from the version string you type at the command line. + +### Bundle descriptions + +You can add introductory text to bundles using the `description` field. This text appears at the top of rendered changelogs, after the release heading but before the entry sections. + +**Configuration locations:** + +- `bundle.description`: Default description for all profiles +- `bundle.profiles..description`: Profile-specific description (overrides the default) + +**Placeholder support:** + +Bundle descriptions support these placeholders: + +- `{version}`: The resolved version string +- `{lifecycle}`: The resolved lifecycle (ga, beta, preview, etc.) +- `{owner}`: The GitHub repository owner +- `{repo}`: The GitHub repository name + +**Important**: When using `{version}` or `{lifecycle}` placeholders, you must ensure predictable substitution values: + +- **Option-based mode**: Requires `--output-products` when using placeholders +- **Profile-based mode**: Requires either a version argument (e.g., `bundle profile 9.2.0`) OR an `output_products` pattern in the profile configuration when using placeholders. If you invoke a profile with only a promotion report (e.g., `bundle profile ./report.html`), placeholders will fail unless `output_products` is configured. + +**Multiline descriptions in YAML:** + +For complex descriptions with multiple paragraphs, lists, and links, use YAML literal block scalars with the `|` (pipe) syntax: + +```yaml +bundle: + description: | + This release includes significant improvements: + + - Enhanced performance + - Bug fixes and stability improvements + - New features for better user experience + + For security updates, go to [security announcements](https://example.com/docs). + + Download the release binaries: https://github.com/{owner}/{repo}/releases/tag/v{version} +``` + +The `|` (pipe) preserves line breaks and is ideal for Markdown-formatted text. Avoid using `>` (greater than) for descriptions as it folds line breaks into spaces, making lists and paragraphs difficult to format correctly. + +**Command line usage:** + +For simple descriptions, use the `--description` option with regular quotes: + +```sh +docs-builder changelog bundle --all --description "This release includes new features." +``` + +For multiline descriptions on the command line, use ANSI-C quoting (`$'...'`) with `\n` for line breaks: + +```sh +docs-builder changelog bundle --all --description $'Enhanced release:\n\n- Performance improvements\n- Bug fixes' +``` + +`output_products` is optional. When omitted, the bundle products array is derived from the matched changelog files' own `products` fields — the same fallback used by all other profile types. Set `output_products` when you want a single clean product entry that reflects the release identity rather than the diverse metadata across individual changelog files, or to hardcode a lifecycle that cannot be inferred from the tag format: + +```yaml +# Produce one authoritative product entry instead of inheriting from changelog files +agent-gh-release: + source: github_release + repo: apm-agent-dotnet + output: "apm-agent-dotnet-{version}.yaml" + output_products: "apm-agent-dotnet {version} {lifecycle}" + +# Or hardcode the lifecycle when the tag format doesn't encode it +agent-gh-release-preview: + source: github_release + repo: apm-agent-dotnet + output: "apm-agent-dotnet-{version}-preview.yaml" + output_products: "apm-agent-dotnet {version} preview" +``` + +`source: github_release` is mutually exclusive with `products`, and a third positional argument (promotion report or URL list) is not accepted by this profile type. + +## Filter by product [changelog-bundle-product] + +You can use the `--input-products` option to create a bundle of changelogs that match the product details. +When using `--input-products`, you must provide all three parts: product, target, and lifecycle. +Each part can be a wildcard (`*`) to match any value. + +:::{tip} +If you use profile-based bundling, provide this information in the `bundle.profiles..products` field. +::: + +```sh +docs-builder changelog bundle \ + --input-products "cloud-serverless 2025-12-02 ga, cloud-serverless 2025-12-06 beta" <1> +``` + +1. Include all changelogs that have the `cloud-serverless` product identifier with target dates of either December 2 2025 (lifecycle `ga`) or December 6 2025 (lifecycle `beta`). For more information about product values, refer to [Product format](/contribute/create-changelogs.md#product-format). + +You can use wildcards in any of the three parts: + +```sh +# Bundle any changelogs that have exact matches for either of these clauses +docs-builder changelog bundle --input-products "cloud-serverless 2025-12-02 ga, elasticsearch 9.3.0 beta" + +# Bundle all elasticsearch changelogs regardless of target or lifecycle +docs-builder changelog bundle --input-products "elasticsearch * *" + +# Bundle all cloud-serverless 2025-12-02 changelogs with any lifecycle +docs-builder changelog bundle --input-products "cloud-serverless 2025-12-02 *" + +# Bundle any cloud-serverless changelogs with target starting with "2025-11-" and "ga" lifecycle +docs-builder changelog bundle --input-products "cloud-serverless 2025-11-* ga" + +# Bundle all changelogs (equivalent to --all) +docs-builder changelog bundle --input-products "* * *" +``` + +If you have changelog files that reference those product details, the command creates a file like this: + +```yaml +products: <1> +- product: cloud-serverless + target: 2025-12-02 +- product: cloud-serverless + target: 2025-12-06 +entries: +- file: + name: 1765495972-fixes-enrich-and-lookup-join-resolution-based-on-m.yaml + checksum: 6c3243f56279b1797b5dfff6c02ebf90b9658464 +- file: + name: 1765507778-break-on-fielddata-when-building-global-ordinals.yaml + checksum: 70d197d96752c05b6595edffe6fe3ba3d055c845 +``` + +1. By default these values match your `--input-products` (even if the changelogs have more products). +To specify different product metadata, use the `--output-products` option. + +## Filter by pull requests [changelog-bundle-pr] + +You can use the `--prs` option to create a bundle of the changelogs that relate to those pull requests. +You can provide either a comma-separated list of PRs (`--prs "https://github.com/owner/repo/pull/123,12345"`) or a path to a newline-delimited file (`--prs /path/to/file.txt`). +In the latter case, the file should contain one PR URL or number per line. + +Pull requests can be identified by a full URL (such as `https://github.com/owner/repo/pull/123`), a short format (such as `owner/repo#123`), or just a number (in which case you must also provide `--owner` and `--repo` options). + +```sh +docs-builder changelog bundle --prs "108875,135873,136886" \ <1> + --repo elasticsearch \ <2> + --owner elastic \ <3> + --output-products "elasticsearch 9.2.2 ga" <4> +``` + +1. The comma-separated list of pull request numbers to seek. +2. The repository in the pull request URLs. Not required when using full PR URLs, or when `bundle.repo` is set in the changelog configuration. +3. The owner in the pull request URLs. Not required when using full PR URLs, or when `bundle.owner` is set in the changelog configuration. +4. The product metadata for the bundle. If it is not provided, it will be derived from all the changelog product values. + +In Mode 3, the **rule context product** is the first alphabetically from `--output-products` (or from aggregated changelog products if omitted). To apply a different product's per-product rules, use a bundle whose `output_products` contains only that product (separate command or profile). + +If you have changelog files that reference those pull requests, the command creates a file like this: + +```yaml +products: +- product: elasticsearch + target: 9.2.2 + lifecycle: ga +entries: +- file: + name: 1765507819-fix-ml-calendar-event-update-scalability-issues.yaml + checksum: 069b59edb14594e0bc3b70365e81626bde730ab7 +- file: + name: 1765507798-convert-bytestransportresponse-when-proxying-respo.yaml + checksum: c6dbd4730bf34dbbc877c16c042e6578dd108b62 +- file: + name: 1765507839-use-ivf_pq-for-gpu-index-build-for-large-datasets.yaml + checksum: 451d60283fe5df426f023e824339f82c2900311e +``` + +## Filter by issues [changelog-bundle-issues] + +You can use the `--issues` option to create a bundle of changelogs that relate to those GitHub issues. +Provide either a comma-separated list of issues (`--issues "https://github.com/owner/repo/issues/123,456"`) or a path to a newline-delimited file (`--issues /path/to/file.txt`). +Issues can be identified by a full URL (such as `https://github.com/owner/repo/issues/123`), a short format (such as `owner/repo#123`), or just a number (in which case `--owner` and `--repo` are required — or set via `bundle.owner` and `bundle.repo` in the configuration). + +```sh +docs-builder changelog bundle --issues "12345,12346" \ + --repo elasticsearch \ + --owner elastic \ + --output-products "elasticsearch 9.2.2 ga" +``` + +## Filter by pull request or issue file [changelog-bundle-file] + +If you have a file that lists pull requests (such as PRs associated with a GitHub release), you can pass it to `--prs`. +For example, if you have a file that contains full pull request URLs like this: + +```txt +https://github.com/elastic/elasticsearch/pull/108875 +https://github.com/elastic/elasticsearch/pull/135873 +https://github.com/elastic/elasticsearch/pull/136886 +https://github.com/elastic/elasticsearch/pull/137126 +``` + +You can use the `--prs` option with the file path to create a bundle of the changelogs that relate to those pull requests. +You can also combine multiple `--prs` options: + +```sh +./docs-builder changelog bundle \ + --prs "https://github.com/elastic/elasticsearch/pull/108875,135873" \ <1> + --prs test/9.2.2.txt \ <2> + --output-products "elasticsearch 9.2.2 ga" <3> + --resolve <4> +``` + +1. Comma-separated list of pull request URLs or numbers. +2. The path for the file that lists the pull requests. If the file contains only PR numbers, you must add `--repo` and `--owner` command options. +3. The product metadata for the bundle. If it is not provided, it will be derived from all the changelog product values. +4. Optionally include the contents of each changelog in the output file. + +:::{tip} +You can use these files with profile-based bundling too. Refer to [](/cli/changelog/bundle.md). +::: + +If you have changelog files that reference those pull requests, the command creates a file like this: + +```yaml +products: +- product: elasticsearch + target: 9.2.2 + lifecycle: ga +entries: +- file: + name: 1765507778-break-on-fielddata-when-building-global-ordinals.yaml + checksum: 70d197d96752c05b6595edffe6fe3ba3d055c845 + type: bug-fix + title: Break on FieldData when building global ordinals + products: + - product: elasticsearch + areas: + - Aggregations + prs: + - https://github.com/elastic/elasticsearch/pull/108875 +... +``` + +:::{note} +When a changelog matches multiple `--input-products` filters, it appears only once in the bundle. This deduplication applies even when using `--all` or `--prs`. +::: + +## Filter by GitHub release notes [changelog-bundle-release-version] + +If you have GitHub releases with automated release notes (the default format or [Release Drafter](https://github.com/release-drafter/release-drafter) format), you can use the `--release-version` option to derive the PR list from those release notes. +For example: + +```sh +docs-builder changelog bundle \ + --release-version v1.34.0 \ + --repo apm-agent-dotnet --owner elastic <1> +``` + +1. The repo and repo owner are used to fetch the release and follow these rules of precedence: + +- Repo: `--repo` flag > `bundle.repo` in `changelog.yml` (one source is required) +- Owner: `--owner` flag > `bundle.owner` in `changelog.yml` > `elastic` + +This command creates a bundle of changelogs that match the list of PRs found in the `v1.34.0` GitHub release notes. + +The bundle's product metadata is inferred automatically from the release tag and repository name; you can override that behavior with the `--output-products` option. + +:::{tip} +If you are not creating changelogs when you create your pull requests, consider the `docs-builder changelog gh-release` command as a one-shot alternative to the `changelog add` and `changelog bundle` commands. +It parses the release notes, creates one changelog file per pull request found, and creates a `changelog-bundle.yaml` file — all in a single step. Refer to [](/cli/changelog/gh-release.md) +::: + +## Hide features [changelog-bundle-hide-features] + +You can use the `--hide-features` option to embed feature IDs that should be hidden when the bundle is rendered. This is useful for features that are not yet ready for public documentation. + +```sh +docs-builder changelog bundle \ + --input-products "elasticsearch 9.3.0 *" \ + --hide-features "feature:hidden-api,feature:experimental" \ <1> + --output /path/to/bundles/9.3.0.yaml +``` + +1. Feature IDs to hide. Changelogs with matching `feature-id` values will be commented out when rendered. + + + +The bundle output will include a `hide-features` field: + +```yaml +products: +- product: elasticsearch + target: 9.3.0 +hide-features: + - feature:hidden-api + - feature:experimental +entries: +- file: + name: 1765495972-new-feature.yaml + checksum: 6c3243f56279b1797b5dfff6c02ebf90b9658464 +``` + +When this bundle is rendered (either via the `changelog render` command or the `{changelog}` directive), changelogs with `feature-id` values matching any of the listed features will be commented out in the output. + +:::{note} +The `--hide-features` option on the `render` command and the `hide-features` field in bundles are **combined**. If you specify `--hide-features` on both the `bundle` and `render` commands, all specified features are hidden. The `{changelog}` directive automatically reads `hide-features` from all loaded bundles and applies them. +::: + +## Hide private links + +A changelog can reference multiple pull requests and issues in the `prs` and `issues` array fields. + +To comment out links that are not in your allowlist in all changelogs in your bundles, refer to [changelog bundle](/cli/changelog/bundle.md#link-allowlist). + +If you are working in a private repo and do not want any pull request or issue links to appear (even if they target a public repo), you also have the option to configure link visibiblity in the [changelog directive](/syntax/changelog.md) and [changelog render](/cli/changelog/render.md) command. + +:::{tip} +You must run the `docs-builder changelog bundle` command with the `--resolve` option or set `bundle.resolve` to `true` in the changelog configuration file (so that bundle files are self-contained) in order to hide the private links. +::: + +## Amend bundles [changelog-bundle-amend] + +When you need to add changelogs to an existing bundle without modifying the original file, you can use the `docs-builder changelog bundle-amend` command to create amend bundles. +Amend bundles follow a specific naming convention: `{parent-bundle-name}.amend-{N}.yaml` where `{N}` is a sequence number. + +When bundles are loaded (either via the `changelog render` command or the `{changelog}` directive), amend files are **automatically merged** with their parent bundles. +The changelogs from all matching amend files are combined with the parent bundle's changelogs and the result is rendered as a single release. + +:::{warning} +If you explicitly list the amend bundles in the `--input` option of the `docs-builder changelog render` command, you'll get duplicate entries in the output files. List only the original bundles. +::: + +For more details and examples, go to [](/cli/changelog/bundle-amend.md). + +## Remove changelog files [changelog-remove] + +A single changelog file might be applicable to multiple releases (for example, it might be delivered in both Stack and {{serverless-short}} releases or {{ech}} and Enterprise releases on different timelines). +After it has been included in all of the relevant bundles, it is reasonable to delete the changelog to keep your repository clean. + +:::{important} +If you create docs with changelog directives, run the `docs-builder changelog bundle` command with the `--resolve` option or set `bundle.resolve` to `true` in the changelog configuration file (so that bundle files are self-contained). +Otherwise, the build will fail if you remove changelogs that the directive requires. + +Likewise, the `docs-builder changelog render` command fails for "unresolved" bundles after you delete the changelogs. +::: + +You can use the `docs-builder changelog remove` command to remove changelogs. +It supports the same two modes as `changelog bundle`: you can specify all the command options or you can define "profiles" in the changelog configuration file. +In the command option mode, exactly one filter option must be specified: `--all`, `--products`, `--prs`, `--issues`, `--release-version`, or `--report`. + +Before deleting, the command automatically scans for bundles that still hold unresolved (`file:`) references to the matching changelog files. +If any are found, the command reports an error for each dependency. +This check prevents the `{changelog}` directive from failing at build time with missing file errors. +To proceed with removal even when unresolved bundle dependencies exist, use `--force`. + +To preview what would be removed without deleting anything, use `--dry-run`. +Bundle dependency conflicts are also reported in dry-run mode. + +### Removal with profiles [changelog-remove-profile] + +If your `changelog.yml` configuration file defines `bundle.profiles`, you can use those profiles with `changelog remove`. +This is the easiest way to remove exactly the changelogs that were included in a profile-based bundle. +The command syntax is: + +```sh +docs-builder changelog remove +``` + +For example, if you bundled with: + +```sh +docs-builder changelog bundle elasticsearch-release 9.2.0 +``` + +You can remove the same changelogs with: + +```sh +docs-builder changelog remove elasticsearch-release 9.2.0 --dry-run +``` + +The command automatically discovers `changelog.yml` by checking `./changelog.yml` then `./docs/changelog.yml` relative to your current directory. +If no configuration file is found, the command returns an error with advice to create one or to run from the directory where the file exists. + +The `output`, `output_products`, `hide_features`, `link_allow_repos`, and `resolve` fields are bundle-specific and are always ignored for removal (along with other bundle-only settings that do not affect which changelog files match the filter). +Which other fields are used depends on the profile type: + +- Standard profiles: only the `products` field is used. The `repo` and `owner` fields are ignored (they only affect bundle output metadata). +- GitHub release profiles (`source: github_release`): `source`, `repo`, and `owner` are all used. The command fetches the PR list from the GitHub release identified by the version argument and removes changelogs whose `prs` field matches. + +For example, given a GitHub release profile: + +```sh +docs-builder changelog remove agent-gh-release v1.34.0 --dry-run +``` + +This fetches the PR list from the `v1.34.0` release (using the profile's `repo`/`owner` settings) and removes matching changelogs. + +:::{note} +`source: github_release` profiles require a `GITHUB_TOKEN` or `GH_TOKEN` environment variable (or an active `gh` login) to fetch release details from the GitHub API. +::: + +Profile-based removal is mutually exclusive with command options. +The only options allowed alongside a profile name are `--dry-run` and `--force`. + +You can also pass a promotion report URL, file path, or URL list file as the second argument, and the command removes changelogs whose pull request or issue URLs appear in the report: + +```sh +docs-builder changelog remove elasticsearch-release https://buildkite.../promotion-report.html +docs-builder changelog remove serverless-release 2026-02 ./promotion-report.html +docs-builder changelog remove serverless-release 2026-02 ./prs.txt +``` + +### Removal with command options [changelog-remove-raw] + +You can alternatively remove changelogs based on their issues, pull requests, product metadata, or remove all changelogs from a folder. +Exactly one filter option must be specified: `--all`, `--products`, `--prs`, `--issues`, `--release-version` or `--report`. +When using a file for `--prs` or `--issues`, every line must be a fully-qualified GitHub URL. + +```sh +docs-builder changelog remove --products "elasticsearch 9.3.0 *" --dry-run +``` + +For full option details, go to [](/cli/changelog/remove.md). diff --git a/docs/contribute/changelog.md b/docs/contribute/changelog.md index 0bc27acfa..984e07a29 100644 --- a/docs/contribute/changelog.md +++ b/docs/contribute/changelog.md @@ -1,1416 +1,13 @@ -# Create and bundle changelogs +# Create release notes from changelogs -By adding a file for each notable change and grouping them into bundles, you can ultimately generate release documention with a consistent layout for all your products. - -The changelogs use the following schema: - -:::{dropdown} Changelog schema -::::{include} /contribute/_snippets/changelog-fields.md -:::: -::: - -:::{important} -Some of the fields in the schema accept only a specific set of values: - -- Product values must exist in [products.yml](https://github.com/elastic/docs-builder/blob/main/config/products.yml). Invalid products will cause the `docs-builder changelog add` command to fail. -- Type, subtype, and lifecycle values must match the available values defined in [ChangelogEntryType.cs](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/ChangelogEntryType.cs), [ChangelogEntrySubtype.cs](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/ChangelogEntrySubtype.cs), and [Lifecycle.cs](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/Lifecycle.cs) respectively. Invalid values will cause the `docs-builder changelog add` command to fail. -::: +By adding a file for each notable change in your GitHub repository and grouping the files into bundles, you can ultimately generate release documentation with a consistent layout for all your products. To use the `docs-builder changelog` commands in your development workflow: -1. Ensure that your products exist in [products.yml](https://github.com/elastic/docs-builder/blob/main/config/products.yml). -1. Add labels to your GitHub pull requests that map to [changelog types](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/ChangelogEntryType.cs). At a minimum, create labels for the `feature`, `bug-fix`, and `breaking-change` types. -1. Optional: Choose areas or components that your changes affect and add labels to your GitHub pull requests (such as `:Analytics/Aggregations`). -1. Optional: Add labels to your GitHub pull requests to indicate that they are not notable and should not generate changelogs. For example, `non-issue` or `release_notes:skip`. Alternatively, you can assume that all PRs are *not* notable unless a specific label is present (for example, `@Public`). -1. [Configure changelog settings](#changelog-settings) to correctly interpret your PR labels. -1. [Create changelogs](#changelog-add) with the `docs-builder changelog add` command. +1. [Configure changelogs](/contribute/configure-changelogs.md): Create a configuration file, map labels, and define rules for creation and bundling. +1. [Create changelogs](/contribute/create-changelogs.md) with the `docs-builder changelog add` command. - Alternatively, if you already have automated release notes for GitHub releases, you can use the `docs-builder changelog gh-release` command to create changelog files and a bundle from your GitHub release notes. Refer to [](/cli/changelog/gh-release.md). -1. [Create changelog bundles](#changelog-bundle) with the `docs-builder changelog bundle` command. For example, create a bundle for the pull requests that are included in a product release. -1. [Create documentation](#render-changelogs) with the `docs-builder changelog render` command. - -For more information about running `docs-builder`, go to [Contribute locally](https://www.elastic.co/docs/contribute-docs/locally). - -:::{note} -This command is associated with an ongoing release docs initiative. -Additional workflows are still to come for updating and generating documentation from changelogs. -::: - -## Create a changelog configuration file [changelog-settings] - -You can use the `docs-builder changelog init` command to create the changelog configuration file and folder structure automatically. -The command uses an existing docs folder (with or without `docset.yml`) when found, or creates `{path}/docs` when it does not exist. -It places `changelog.yml` in the `docs` folder and creates sub-folders for the changelog and bundle files. -Alternatively, you can create the file and folders manually. - -You can create a configuration file to: - -- define the acceptable product, type, subtype, and lifecycle values. -- prevent the creation of changelogs when certain PR labels are present. -- set default options, such as whether to extract issues and release note text from pull requests. -- create profiles for simplified bundle creation - -Refer to [changelog.example.yml](https://github.com/elastic/docs-builder/blob/main/config/changelog.example.yml). - -By default, the changelog commands check the following path: `docs/changelog.yml`. -You can specify a different path with the `--config` command option. - -If a configuration file exists, the command validates its values before generating changelog files: - -- If the configuration file contains `lifecycles`, `products`, `subtype`, or `type` values that don't match the values in `ChangelogEntryType.cs`, `ChangelogEntrySubtype.cs`, or `Lifecycle.cs`, validation fails. -- If the configuration file contains `areas` values and they don't match what you specify in the `--areas` command option, validation fails. -- If the configuration file contains `lifecycles` or `products` values are a subset of the available values and you try to create a changelog with values outside that subset, validation fails. - -In each of these cases where validation fails, a changelog file is not created. - -### GitHub label mappings - -When you run the `docs-builder changelog add` command with the `--prs` or `--issues` options, it can use label mappings in the changelog configuration file to infer the changelog `type`, `areas`, and `products` fields from your GitHub labels. - -Refer to the file layout in [changelog.example.yml](https://github.com/elastic/docs-builder/blob/main/config/changelog.example.yml) and an [example usage](#example-map-label). - -### Rules for creation and bundling - -If you have pull request labels that indicate a changelog is not required (such as `>non-issue` or `release_note:skip`), you can declare these in the `rules.create` section of the changelog configuration. - -When you run the `docs-builder changelog add` command with the `--prs` or `--issues` options and the pull request or issue has one of the identified labels, the command does not create a changelog. - -Likewise, if you want to exclude changelogs with certain products, areas, or types from the release bundles, you can declare these in the `rules.bundle` section of the changelog configuration. -For example, you might choose to omit `other` or `docs` changelogs. -Or you might want to omit all autoscaling-related changelogs from the Cloud Serverless release bundles. - -The `changelog render` command does **not** apply `rules.publish`; filtering must be done at bundle time via `rules.bundle`. -[Changelog directives](#changelog-directive) also do not apply `rules.publish`. - -:::{warning} -`rules.publish` is deprecated and no longer used by the `changelog render` command. Move your type/area filtering to `rules.bundle` so it applies at bundle time. Using `rules.publish` emits a deprecation warning during configuration loading. -::: - -Each field supports **exclude** (block if matches) or **include** (block if doesn't match) semantics. You cannot mix both for the same field. - -For multi-valued fields (labels, areas), you can control the matching mode: -- `any` (default): match if ANY item matches the list -- `all`: match only if ALL items match the list - -:::{note} -You can define rules at the global level (applies to all products) or for specific products. -Product-specific rules **override** the global rules entirely—they do not merge. -If you define a product-specific `publish` rule, you must re-state any global rules that you also want applied for that product. -For `rules.bundle`, global versus per-product behavior is described under [bundle rule modes](#bundle-rule-modes). -::: - -Refer to [changelog.example.yml](https://github.com/elastic/docs-builder/blob/main/config/changelog.example.yml) and an [example usage](#example-block-label). - -### Rules reference - -The `rules:` section supports the following options: - -#### `rules.match` - -Global match default for multi-valued fields (labels, areas). Inherited by `create`, `publish`, and all product overrides. - -| Value | Description | -|-------|-------------| -| `any` (default) | Match if ANY item in the relevant changelog field matches an item in the configured list | -| `all` | Match only if ALL items in the relevant changelog field match items in the configured list (subset semantics; see product/area tables) | -| `conjunction` | Match only if EVERY item in the configured list appears in the relevant changelog field (logical AND over the list) | - -#### `rules.create` - -Filters the pull requests or issues that can generate changelogs. -Evaluated when running `docs-builder changelog add` with `--prs` or `--issues`. - -| Option | Type | Description | -|--------|------|-------------| -| `exclude` | string | Comma-separated labels that prevent changelog creation. A PR with any matching label is skipped. | -| `include` | string | Comma-separated labels required for changelog creation. A PR without any matching label is skipped. | -| `match` | string | Override `rules.match` for create rules. Values: `any`, `all`, `conjunction`. | -| `products` | map | Product-specific create rules (see below). | - -You cannot specify both `exclude` and `include`. - -##### Product-specific create rules (`rules.create.products`) - -Product keys can be a single product ID or a comma-separated list of product IDs (for example, `'elasticsearch, kibana'`). -Each product override supports the same `exclude`, `include`, and `match` options. -Product-specific rules **override** the global create rules entirely. - -```yaml -rules: - create: - exclude: ">non-issue" - products: - 'elasticsearch, kibana': - exclude: ">test" - cloud-serverless: - exclude: ">non-issue, ILM" -``` - -#### `rules.bundle` - -Filters the changelogs that are included in a bundle file. -Applied during `docs-builder changelog bundle` and `docs-builder changelog gh-release` after the primary filter (`--prs`, `--issues`, `--all`) has matched entries. - -Input stage (gathering entries) and bundle filtering stage (filtering for output) are conceptually separate. -Which global fields take effect depends on the [bundle rule mode](#bundle-rule-modes). - -##### Bundle rule modes [bundle-rule-modes] - -The bundler chooses one of three modes from your parsed `rules.bundle` configuration: - -| Mode | When it applies | Filtering behavior | -|------|-----------------|-------------------| -| **1 — No filtering** | There is no effective bundle rule: no `exclude_products` / `include_products`, no type/area blocker, and no non-empty `products` map. | No product, type, or area filtering from `rules.bundle`. | -| **2 — Global content** | At least one global filter or blocker is set, and **`products` is absent or empty** (including `products: {}`). | Global lists are evaluated against **each changelog’s own** `products`, `type`, and `areas`. There is **no** single rule-context product and **no** disjoint exclusion. Changelogs with **missing or empty** `products` are **included** with a warning; product include/exclude lists are skipped for those entries. Type/area rules still apply. | -| **3 — Per-product context** | **`products` has at least one key** with a rule block. | **Global** `exclude_products`, `include_products`, `match_products`, and global type/area fields under `rules.bundle` are **not used for filtering** — configure what you need under each product key (or use Mode 2 by removing product keys). The bundle uses a **single rule-context product**, **disjoint** changelogs are excluded, and **missing/empty** `products` are excluded with a warning. If the rule-context product has no per-product block, the entry **passes through** without global fallback. | - -Configuration loading may emit a **hint** when both global bundle fields and a non-empty `products` map are present, because global keys are ignored in Mode 3. - -##### Product filtering - -| Option | Type | Description | -|--------|------|-------------| -| `exclude_products` | string or list | Product IDs to exclude from the bundle. Cannot be combined with `include_products`. | -| `include_products` | string or list | Only these product IDs are included; all others are excluded. Cannot be combined with `exclude_products`. | -| `match_products` | string | Override `rules.match` for product matching. Values: `any`, `all`, `conjunction`. | - -##### Type and area filtering - -| Option | Type | Description | -|--------|------|-------------| -| `exclude_types` | string or list | Changelog types to exclude from the bundle. | -| `include_types` | string or list | Only changelogs with these types are kept; all others are excluded. | -| `exclude_areas` | string or list | Changelog areas to exclude from the bundle. | -| `include_areas` | string or list | Only changelogs with these areas are kept; all others are excluded. | -| `match_areas` | string | Override `rules.match` for area matching. Values: `any`, `all`, `conjunction`. | -| `products` | map | Per-product type/area filter overrides (see below). | - -You cannot specify both `exclude_products` and `include_products`, both `exclude_types` and `include_types`, or both `exclude_areas` and `include_areas`. You can mix exclude and include across different fields (for example, `exclude_types` with `include_areas`). - -When a changelog is excluded by `rules.bundle`, the bundling service emits a warning with a `[-bundle-exclude]`, `[-bundle-include]`, `[-bundle-type-area]`, or mode-specific prefix such as `[-bundle-global]`. - -:::{important} -In **Mode 3** (non-empty `rules.bundle.products`), per-product `include_products` can **only** affect changelogs that already contain the rule context product. -It cannot pull in changelogs that are disjoint from that context. -Under **Mode 2** (global-only `rules.bundle`), `match_products: any` with `include_products` is meaningful: each changelog is evaluated on its own, so OR-style inclusion (for example, elasticsearch **or** kibana) works without per-product blocks. -::: - -##### Product-specific bundle rules (`rules.bundle.products`) - -This section applies to **Mode 3 — Per-product context** (at least one key under `rules.bundle.products` with rules). - -Product keys can be a single product ID or a comma-separated list. -Each product override supports: - -- **Product filtering**: `include_products`, `exclude_products`, `match_products` — controls which changelog entries are included based on their product IDs -- **Type/area filtering**: `exclude_types`, `include_types`, `exclude_areas`, `include_areas`, `match_areas` — controls which entries are included based on their type and area fields - -When a per-product rule applies to an entry, it is used **instead of** any global `rules.bundle` filters (**global bundle keys are not applied** in Mode 3). If a filter type is omitted in that per-product block, it is not inherited from global `rules.bundle` — repeat the constraint under the product key if you still need it. - -If the changelog contains the rule context product but **no** block exists for that product ID, the entry is **included** without applying global bundle filters (**pass-through**). - -**Example (Mode 3): per-product rule replaces global keys for matching entries** - -```yaml -rules: - bundle: - exclude_types: [docs] - exclude_areas: [Internal] - products: - kibana: - include_areas: [UI] -``` - -**Result** when the rule context product is `kibana`: - -- Elasticsearch-only entries: **excluded** as disjoint (they never use the `kibana` block). -- Kibana entries: only the `kibana` block applies — global `exclude_types` / `exclude_areas` do not apply. Add `exclude_types` under `kibana` if you still need to drop `docs` entries. - -###### Single-product rule resolution (Mode 3 only) [changelog-bundle-rule-resolution] - -**Mode 3** uses a **single rule-context product** for each bundle: - -1. **Rule context product**: - - **With `--output-products`** (CLI) or profile **`output_products`**: First product alphabetically from that list - - **Without** those: First product alphabetically from all products aggregated from matched changelog entries (regardless of input method: `--all`, `--prs`, `--issues`, etc.) - -2. **For each changelog**: - - **Contains rule context product** and a per-product block exists for that product: apply that block (product rules, then type/area for that block). - - **Contains rule context product** and **no** per-product block for that product: **include** without applying global `rules.bundle` filters (pass-through). - - **Disjoint** from rule context: **exclude** the changelog. - - **No products** in the changelog: emit a warning and **exclude** the changelog. - -**Input method independence**: Bundle filtering still applies regardless of how entries were gathered (`--input-products`, `--prs`, `--all`, etc.). - -For example, with `--output-products "kibana 9.3.0, security 9.3.0"` (rule context: `kibana`): - -| Changelog `products` | Contains `kibana`? | Result (Mode 3) | -|--------------------|-------------------|---------| -| `[kibana]` | Yes | Use `kibana` per-product rules if defined; otherwise pass-through | -| `[security]` | No | **Excluded** (disjoint) | -| `[kibana, security]` | Yes | Use `kibana` per-product rules if defined; otherwise pass-through | -| `[elasticsearch]` | No | **Excluded** (disjoint) | -| `[]` (empty/missing) | No | **Excluded** with warning | - -**Multi-product bundles**: For release notes that need different rule behavior per product, run **separate** `changelog bundle` invocations with a **single** product in `--output-products` (or a profile whose `output_products` resolves to one product), or use **Mode 2** (global-only `rules.bundle`) when you need OR-style product inclusion without disjoint exclusion. - -#### `rules.publish` - -:::{warning} -`rules.publish` is deprecated and **no longer used by the `changelog render` command**. The command now only supports `rules.bundle` for type/area filtering at bundle time. Using `rules.publish` emits a deprecation warning during configuration loading. -::: - -`rules.publish` is ignored by the `changelog render` command and will be removed in a future release. If you have `rules.publish` configured, move your type/area filtering to `rules.bundle` so it applies at bundle time. - -**Deprecated (no longer used):** - -```yaml -rules: - publish: - exclude_types: docs - exclude_areas: - - Internal -``` - -**Use instead:** - -```yaml -rules: - bundle: - exclude_types: docs - exclude_areas: - - Internal -``` - -#### Match inheritance - -The `match` setting cascades from global to section to product: - -``` -rules.match (global default, "any" if omitted) - ├─ rules.create.match → rules.create.products.{id}.match - ├─ rules.bundle.match_products - ├─ rules.bundle.match_areas → rules.bundle.products.{id}.match_areas - └─ rules.publish.match_areas → rules.publish.products.{id}.match_areas (deprecated) -``` - -If a lower-level `match` or `match_areas` is specified, it overrides the inherited value. - -#### Product matching behavior - -The following applies to **global** `rules.bundle` product lists (**Mode 2**). In **Mode 3**, product matching uses the per-product block for the rule context product instead. - -With `match_products`, the behavior differs depending on the mode. The keyword **`conjunction`** means *every product ID in the config list must appear on the changelog* (logical AND). It does not refer to the `include_products` / `exclude_products` field names — those choose **which** list and **include vs exclude**; `match_products` chooses **how** that list is interpreted. - -| Config | Changelog `products` | `match_products` | Result | -|--------|----------------|----------------|--------| -| `exclude_products: [cloud-enterprise]` | `[cloud-enterprise, kibana]` | `any` | **Excluded** ("cloud-enterprise" matches) | -| `exclude_products: [cloud-enterprise]` | `[cloud-enterprise, kibana]` | `all` | **Included** (not all products are in the exclude list) | -| `exclude_products: [kibana, observability]` | `[kibana]` | `conjunction` | **Included** (not every listed exclude ID is on the changelog) | -| `exclude_products: [kibana, observability]` | `[kibana, observability]` | `conjunction` | **Excluded** (every listed exclude ID is on the changelog) | -| `include_products: [elasticsearch]` | `[elasticsearch, kibana]` | `any` | **Included** ("elasticsearch" matches) | -| `include_products: [elasticsearch]` | `[elasticsearch, kibana]` | `all` | **Excluded** ("kibana" is not in the include list) | -| `include_products: [elasticsearch, security]` | `[elasticsearch, security, kibana]` | `conjunction` | **Included** (every listed include ID is on the changelog) | -| `include_products: [elasticsearch, security]` | `[elasticsearch]` | `conjunction` | **Excluded** ("security" is missing from the changelog) | - -In practice, most changelogs have a single product, so `any` (the default) and `all` behave identically for them. -The difference only matters for changelogs with multiple products. - -#### Area matching behavior - -With `match_areas` (applies to both `rules.bundle` and `rules.publish`), the behavior differs depending on the mode. As with products, **`conjunction`** means every area in the config list must appear on the changelog. - -| Config | Changelog `areas` | `match_areas` | Result | -|--------|------------|-------------|--------| -| `exclude_areas: [Internal]` | `[Search, Internal]` | `any` | **Excluded** ("Internal" matches) | -| `exclude_areas: [Internal]` | `[Search, Internal]` | `all` | **Included** (not all areas are in the exclude list) | -| `exclude_areas: [Search, Internal]` | `[Search]` | `conjunction` | **Included** ("Internal" is not on the changelog) | -| `exclude_areas: [Search, Internal]` | `[Search, Internal, Monitoring]` | `conjunction` | **Excluded** (every listed exclude area is on the changelog) | -| `include_areas: [Search]` | `[Search, Internal]` | `any` | **Included** ("Search" matches) | -| `include_areas: [Search]` | `[Search, Internal]` | `all` | **Excluded** ("Internal" is not in the include list) | -| `include_areas: [Search, Internal]` | `[Search, Internal]` | `conjunction` | **Included** (every listed include area is on the changelog) | -| `include_areas: [Search, Internal]` | `[Search]` | `conjunction` | **Excluded** ("Internal" is missing from the changelog) | - -#### Validation - -The following configurations cause validation errors: - -| Condition | Error | -|-----------|-------| -| Old `block:` key found | `'block' is no longer supported. Rename to 'rules'. See changelog.example.yml.` | -| Both `exclude` and `include` in create | `rules.create: cannot have both 'exclude' and 'include'. Use one or the other.` | -| Both `exclude_types` and `include_types` in bundle | `rules.bundle: cannot have both 'exclude_types' and 'include_types'. Use one or the other.` | -| Both `exclude_areas` and `include_areas` in bundle | `rules.bundle: cannot have both 'exclude_areas' and 'include_areas'. Use one or the other.` | -| Both `exclude_products` and `include_products` in bundle | `rules.bundle: cannot have both 'exclude_products' and 'include_products'. Use one or the other.` | -| Both `exclude_types` and `include_types` in publish | `rules.publish: cannot have both 'exclude_types' and 'include_types'. Use one or the other.` | -| Both `exclude_areas` and `include_areas` in publish | `rules.publish: cannot have both 'exclude_areas' and 'include_areas'. Use one or the other.` | -| `rules.publish` present | Deprecation warning: `rules.publish is deprecated. Move type/area filtering to rules.bundle.` | -| Invalid match value | `rules.match: '{value}' is not valid. Use 'any', 'all', or 'conjunction'.` | -| Unknown product ID in bundle | `rules.bundle.exclude_products: '{id}' is not in the list of available products.` | -| Unknown product ID | `rules.create.products: '{id}' not in available products.` | - -## Create changelog files [changelog-add] - -You can use the `docs-builder changelog add` command to create a changelog file. - -If you specify `--prs` or `--issues`, the command tries to fetch information from GitHub. It derives the changelog `title` from the pull request or issue title, maps labels to areas, products, and type (if configured), and extracts linked references. -With `--issues`, it extracts linked PRs from the issue body (for example, "Fixed by #123"). -With `--prs`, it extracts linked issues from the PR body (for example, "Fixes #123"). - -When `--repo`, `--owner`, or `--output` are not specified, the command reads them from the `bundle` section of `changelog.yml` (`bundle.repo`, `bundle.owner`, `bundle.directory`). This applies to all modes — `--prs`, `--issues`, and `--release-version` alike. If no config value is available, `--owner` defaults to `elastic` and `--output` defaults to the current directory. - -:::{tip} -Ideally this task will be automated such that it's performed by a bot or GitHub action when you create a pull request. -If you run it from the command line, you must precede any special characters (such as backquotes) with a backslash escape character (`\`). -::: - -### CI two-step flow - -When automated via the [changelog GitHub Actions](https://github.com/elastic/docs-actions/tree/main/changelog), changelog creation is a two-step process: - -1. **`changelog evaluate-pr`** inspects the PR (title, labels, body) and produces outputs such as `title`, `type`, `description`, and `products`. -2. **`changelog add`** reads those outputs from `CHANGELOG_*` environment variables and generates the changelog YAML file. - -The `description` output from step 1 contains the release note extracted from the PR body (when `extract.release_notes` is enabled). If extraction is disabled — either by setting `extract.release_notes: false` in `changelog.yml` or by passing `--no-extract-release-notes` to `changelog add` — the `CHANGELOG_DESCRIPTION` environment variable is ignored and the extracted description is not written to the changelog. - -Refer to [CI auto-detection](/cli/changelog/add.md#ci-auto-detection) for the full list of environment variables and precedence rules. - -For up-to-date command usage information, use the `-h` option or refer to [](/cli/changelog/add.md). - -### Authorization - -If you use the `--prs`, `--issues`, or `--release-version` options, the `docs-builder changelog add` command interacts with GitHub services. -The `--release-version` option on the `docs-builder changelog add`, `bundle`, and `remove` commands also interacts with GitHub services. -Log into GitHub or set the `GITHUB_TOKEN` (or `GH_TOKEN` ) environment variable with a sufficient personal access token (PAT). -Otherwise, there will be fetch failures when you access private repositories and you might also encounter GitHub rate limiting errors. - -For example, to create a new token with the minimum authority to read pull request details: - -1. Go to **GitHub Settings** > **Developer settings** > **Personal access tokens** > [Fine-grained tokens](https://github.com/settings/personal-access-tokens). -2. Click **Generate new token**. -3. Give your token a descriptive name (such as "docs-builder changelog"). -4. Under **Resource owner** if you're an Elastic employee, select **Elastic**. -5. Set an expiration date. -6. Under **Repository access**, select **Only select repositories** and choose the repositories you want to access. -7. Under **Permissions** > **Repository permissions**, set **Pull requests** to **Read-only**. If you want to be able to read issue details, do the same for **Issues**. -8. Click **Generate token**. -9. Copy the token to a safe location and use it in the `GITHUB_TOKEN` environment variable. - -### Product format - -The `docs-builder changelog add` has a `--products` option and the `docs-builder changelog bundle` has `--input-products` and `--output-products` options that all use the same format. - -They accept values with the format `"product target lifecycle, ..."` where: - -- `product` is the product ID from [products.yml](https://github.com/elastic/docs-builder/blob/main/config/products.yml) (required) -- `target` is the target version or date (optional) -- `lifecycle` is one of: `preview`, `beta`, or `ga` (optional) - -Examples: - -- `"kibana 9.2.0 ga"` -- `"cloud-serverless 2025-08-05"` -- `"cloud-enterprise 4.0.3, cloud-hosted 2025-10-31"` - -### Filenames - -The `docs-builder changelog add` command names generated files according to the `filename` strategy in `changelog.yml`: - -| Strategy | Example filename | Description | -|---|---|---| -| `timestamp` (default) | `1735689600-fixes-enrich-and-lookup-join-resolution.yaml` | Uses a Unix timestamp with a sanitized title slug. | -| `pr` | `137431.yaml` | Uses the PR number. | -| `issue` | `2571.yaml` | Uses the issue number. | - -Set the strategy in your changelog configuration file: - -```yaml -filename: timestamp -``` - -Refer to [changelog.example.yml](https://github.com/elastic/docs-builder/blob/main/config/changelog.example.yml) for full documentation. - -You can override the configured strategy per invocation with the `--use-pr-number` or `--use-issue-number` CLI flags: - -```sh -docs-builder changelog add \ - --prs https://github.com/elastic/elasticsearch/pull/137431 \ - --products "elasticsearch 9.2.3" \ - --use-pr-number - -docs-builder changelog add \ - --issues https://github.com/elastic/docs-builder/issues/2571 \ - --products "elasticsearch 9.3.0" \ - --config docs/changelog.yml \ - --use-issue-number -``` - -:::{important} -`--use-pr-number` and `--use-issue-number` are mutually exclusive; specify only one. Each requires `--prs` or `--issues`. The numbers are extracted from the URLs or identifiers you provide, or from linked references in the issue or PR body when extraction is enabled. - -**Precedence**: CLI flags (`--use-pr-number` / `--use-issue-number`) > `filename` in `changelog.yml` > default (`timestamp`). -::: - -### Examples - -#### Create a changelog for multiple products [example-multiple-products] - -```sh -docs-builder changelog add \ - --title "Fixes enrich and lookup join resolution based on minimum transport version" \ <1> - --type bug-fix \ <2> - --products "elasticsearch 9.2.3, cloud-serverless 2025-12-02" \ <3> - --areas "ES|QL" - --prs "https://github.com/elastic/elasticsearch/pull/137431" <4> -``` - -1. This option is required only if you want to override what's derived from the PR title. -2. The type values are defined in [ChangelogEntryType.cs](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/ChangelogEntryType.cs). -3. The product values are defined in [products.yml](https://github.com/elastic/docs-builder/blob/main/config/products.yml). -4. The `--prs` value can be a full URL (such as `https://github.com/owner/repo/pull/123`), a short format (such as `owner/repo#123`), just a number (in which case you must also provide `--owner` and `--repo` options), or a path to a file containing newline-delimited PR URLs or numbers. Multiple PRs can be provided comma-separated, or you can specify a file path. You can also mix both formats by specifying `--prs` multiple times. One changelog file will be created for each PR. - -#### Create a changelog with PR label mappings [example-map-label] - -You can configure label mappings in your changelog configuration file: - -```yaml -pivot: - # Keys are type names, values can be: - # - simple string: comma-separated label list (e.g., ">bug, >fix") - # - empty/null: no labels for this type - # - object: { labels: "...", subtypes: {...} } for breaking-change type only - types: - # Example mappings - customize based on your label naming conventions - breaking-change: - labels: ">breaking, >bc" - bug-fix: ">bug" - enhancement: ">enhancement" - - # Area definitions with labels - # Keys are area display names, values are label strings - # Multiple labels can be comma-separated - areas: - # Example mappings - customize based on your label naming conventions - Autoscaling: ":Distributed Coordination/Autoscaling" - "ES|QL": ":Search Relevance/ES|QL" - - # Product definitions with labels (optional) - # Keys are product spec strings; values are label strings or lists. - # A product spec string is: " [] []" - products: - 'elasticsearch': - - ":stack/elasticsearch" - 'kibana': - - ":stack/kibana" - # Include a target version if known: - # 'cloud-serverless 2025-06 ga': - # - ":cloud/serverless" -``` - -When you use the `--prs` option to derive information from a pull request, it can make use of those mappings. Similarly, when you use the `--issues` option (without `--prs`), the command derives title, type, areas, and products from the GitHub issue labels using the same mappings. - -The following example omits `--products`, so the command derives them from the PR labels: - -```sh -docs-builder changelog add \ - --prs https://github.com/elastic/elasticsearch/pull/139272 \ - --config test/changelog.yml \ - --strip-title-prefix -``` - -In this case, the changelog file derives the title, type, areas, and products from the pull request. If none of the PR's labels match `pivot.products`, the command falls back to `products.default` or repository name inference from `--repo` (refer to [Products resolution](/cli/changelog/add.md#products-resolution) for more details). -The command also looks for patterns like `Fixes #123`, `Closes owner/repo#456`, `Resolves https://github.com/.../issues/789` in the pull request to derive its issues. Similarly, when using `--issues`, the command extracts linked PRs from the issue body (for example, "Fixed by #123"). You can turn off this behavior in either case with the `--no-extract-issues` flag or by setting `extract.issues: false` in the changelog configuration file. The `extract.issues` setting applies to both directions: issues extracted from PR bodies (when using `--prs`) and PRs extracted from issue bodies (when using `--issues`). - -The `--strip-title-prefix` option in this example means that if the PR title has a prefix in square brackets (such as `[ES|QL]` or `[Security]`), it is automatically removed from the changelog title. Multiple square bracket prefixes are also supported (for example `[Discover][ESQL] Title` becomes `Title`). If a colon follows the closing bracket, it is also removed. - -By default, `--strip-title-prefix` is disabled. You can enable it globally by setting `extract.strip_title_prefix: true` in the changelog configuration file, which will apply the prefix stripping to all `changelog add` and `changelog gh-release` commands without requiring the CLI flag. The CLI flag `--strip-title-prefix` overrides the configuration setting. - -:::{note} -The `--strip-title-prefix` option only applies when the title is derived from the PR (when `--title` is not explicitly provided). If you specify `--title` explicitly, that title is used as-is without any prefix stripping. -::: - -#### Extract release notes from PR descriptions [example-extract-release-notes] - -When you use the `--prs` option, by default the `docs-builder changelog add` command automatically extracts text from the PR descriptions and use it in your changelog. - -In particular, it looks for content in these formats in the PR description: - -- `Release Notes: This is the extracted sentence.` -- `Release-Notes: This is the extracted sentence.` -- `release notes: This is the extracted sentence.` -- `Release Note: This is the extracted sentence.` -- `Release Notes - This is the extracted sentence.` -- `## Release Note` (as a markdown header) - -How the extracted text is used: - -- **Release note found**: The extracted text is used as the changelog description (only if `--description` is not explicitly provided). The changelog title comes from `--title` or the PR title, not from the release note section. -- **No release note found**: No description is filled from the PR body; the title still comes from `--title` or the PR title as usual. - -:::{note} -If you explicitly provide `--title` or `--description`, those values take precedence over extracted release notes. -You can turn off the release note extraction in the changelog configuration file or by using the `--no-extract-release-notes` option. -::: - -#### Control changelog creation [example-block-label] - -You can prevent changelog creation for certain PRs based on their labels. - -If you run the `docs-builder changelog add` command with the `--prs` option and a PR has a blocking label for any of the resolved products (from `--products`, `pivot.products` label mapping, or `products.default`), that PR will be skipped and no changelog file will be created for it. -A warning message will be emitted indicating which PR was skipped and why. - -For example, your configuration file can contain a `rules` section like this: - -```yaml -rules: - # Global match default for multi-valued fields (labels, areas). - # any (default) = match if ANY item matches the list - # all = match only if ALL items match the list - # match: any - - # Create — controls which PRs generate changelogs. - create: - # Labels that block changelog creation (comma-separated string) - exclude: ">non-issue" - # Product-specific overrides - products: - 'cloud-serverless': - exclude: ">non-issue, >test" -``` - -Those settings affect commands with the `--prs` or `--issues` options, for example: - -```sh -docs-builder changelog add --prs "1234, 5678" \ - --products "cloud-serverless" \ - --owner elastic --repo elasticsearch \ - --config test/changelog.yml -``` - -If PR 1234 has the `>non-issue` or `>test` labels, it will be skipped and no changelog will be created. -If PR 5678 does not have any blocking labels, a changelog is created. - -You can also use **include** mode instead of **exclude** mode. -For example, to only create changelogs for PRs with specific labels: - -```yaml -rules: - create: - include: "@Public, @Notable" -``` - -#### Create changelogs from a file [example-file-add] - -You can create multiple changelogs in a single command by providing a newline-delimited file that contains pull requests or issues. -For example: - -```sh -# Create a file with PRs (one per line) -cat > prs.txt << EOF -https://github.com/elastic/elasticsearch/pull/1234 -https://github.com/elastic/elasticsearch/pull/5678 -EOF - -# Use the file with --prs -docs-builder changelog add --prs prs.txt \ - --products "elasticsearch 9.2.0 ga" \ - --config test/changelog.yml -``` - -In this example, the command creates one changelog for each pull request in the list. - -#### Create changelogs from GitHub release notes [changelog-add-release-version] - -If you have GitHub releases with automated release notes (the default format or [Release Drafter](https://github.com/release-drafter/release-drafter) format), the changelog commands can derive the PR list from those release notes with the `--release-version` option. -For example: - -```sh -docs-builder changelog add \ - --release-version v1.34.0 \ - --repo apm-agent-dotnet --owner elastic -``` - -This command creates one changelog file per PR found in the `v1.34.0` GitHub release notes. -The product, target version, and lifecycle in each changelog are inferred automatically from the release tag and the repository name. -For example, a tag of `v1.34.0` in the `apm-agent-dotnet` repo creates changelogs with `product: apm-agent-dotnet`, `target: 1.34.0`, and `lifecycle: ga`. - -:::{note} -`--release-version` requires `--repo` (or `bundle.repo` set in `changelog.yml`) and is mutually exclusive with `--prs` and `--issues`. -The option precedence is: CLI option > `changelog.yml` bundle section > built-in default. This applies to `--repo`, `--owner`, and `--output` for all `changelog add` modes. -::: - -You can use the `docs-builder changelog gh-release` command as a one-shot alternative to `changelog add` and `changelog bundle` commands. -The command parses the release notes, creates one changelog file per pull request found, and creates a `changelog-bundle.yaml` file — all in a single step. Refer to [](/cli/changelog/gh-release.md) - -:::{note} -This command requires a `GITHUB_TOKEN` or `GH_TOKEN` environment variable (or an active `gh` login) to fetch release details from the GitHub API. Refer to [Authorization](#authorization) for details. -::: - -## Create bundles [changelog-bundle] - -You can use the `docs-builder changelog bundle` command to create a YAML file that lists multiple changelogs. -The command has two modes of operation: you can specify all the command options or you can define "profiles" in the changelog configuration file. -The latter is more convenient and consistent for repetitive workflows. -For up-to-date details, use the `-h` option or refer to [](/cli/changelog/bundle.md). - -The command supports two mutually exclusive usage modes: - -- **Option-based** — you provide filter and output options directly on the command line. -- **Profile-based** — you specify a named profile from your `changelog.yml` configuration file. - -You cannot mix these two modes: when you use a profile name, no filter or output options are accepted on the command line. - -### Option-based bundling [changelog-bundle-options] - -You can specify only one of the following filter options: - -- `--all`: Include all changelogs from the directory. -- `--input-products`: Include changelogs for the specified products. Refer to [Filter by product](#changelog-bundle-product). -- `--prs`: Include changelogs for the specified pull request URLs, or a path to a newline-delimited file. When using a file, every line must be a fully-qualified GitHub URL such as `https://github.com/owner/repo/pull/123`. Go to [Filter by pull requests](#changelog-bundle-pr). -- `--issues`: Include changelogs for the specified issue URLs, or a path to a newline-delimited file. When using a file, every line must be a fully-qualified GitHub URL such as `https://github.com/owner/repo/issues/123`. Go to [Filter by issues](#changelog-bundle-issues). -- `--release-version`: Bundle changelogs for the pull requests in GitHub release notes. Refer to [Bundle by GitHub release](#changelog-bundle-release-version). -- `--report`: Include changelogs whose pull requests appear in a promotion report. Accepts a URL or a local file path to an HTML report. - -`rules.bundle` in `changelog.yml` is **not** mutually exclusive with these options: it runs as a **second stage** after the primary filter matches entries (for example, `--input-products` gathers changelogs, then global or per-product bundle rules may exclude some). The only mutually exclusive pairing is **profile-based** versus **option-based** invocation. See [bundle rule modes](#bundle-rule-modes). - -By default, the output file contains only the changelog file names and checksums. -To change this behavior, set `bundle.resolve` to `true` in the changelog configuration file or use the `--resolve` command option. - -:::{tip} -If you plan to use [changelog directives](#changelog-directive), it is recommended to pull all of the content from each changelog into the bundle; otherwise you can't delete your changelogs. -If you likewise want to regenerate your [Asciidoc or Markdown files](#render-changelogs) after deleting your changelogs, it's only possible if you have "resolved" bundles. -::: - - - -### Profile-based bundling [changelog-bundle-profile] - -If your `changelog.yml` configuration file defines `bundle.profiles`, you can run a bundle by profile name instead of supplying individual options: - -```sh -docs-builder changelog bundle -``` - -The second argument accepts a version string, a promotion report URL/path, or a URL list file (a plain-text file with one fully-qualified GitHub URL per line). When your profile uses `{version}` in its `output` or `output_products` pattern and you also want to filter by a report, pass both. -For example: - -```sh -# Standard profile: lifecycle is inferred from the version string -docs-builder changelog bundle elasticsearch-release 9.2.0 # {lifecycle} → "ga" -docs-builder changelog bundle elasticsearch-release 9.2.0-beta.1 # {lifecycle} → "beta" - -# Standard profile: filter by a promotion report (version used for {version}) -docs-builder changelog bundle elasticsearch-release ./promotion-report.html -docs-builder changelog bundle elasticsearch-release 9.2.0 ./promotion-report.html -``` - - - -Top-level `bundle` fields: - -| Field | Description | -|---|---| -| `repo` | Default GitHub repository name applied to all profiles. Falls back to product ID if not set at any level. | -| `owner` | Default GitHub repository owner applied to all profiles. | -| `resolve` | When `true`, embeds full changelog entry content in the bundle (same as `--resolve`). Required when `link_allow_repos` is set. | -| `link_allow_repos` | When set (including an empty list), only PR/issue links whose resolved repository is in this `owner/repo` list are kept; others are rewritten to `# PRIVATE:` sentinels in bundle YAML. When absent, no link filtering is applied. Requires `resolve: true`. Refer to [PR and issue link allowlist](/cli/changelog/bundle.md#link-allowlist). | - -Profile configuration fields in `bundle.profiles`: - -| Field | Description | -|---|---| -| `source` | Optional. Set to `github_release` to fetch the PR list from a GitHub release. Mutually exclusive with `products`. Requires `repo` at the profile or `bundle` level. | -| `products` | Product filter pattern with `{version}` and `{lifecycle}` placeholders. Used to match changelog files. Required when filtering by product metadata. Not used when the filter comes from a promotion report, URL list file, or `source: github_release`. | -| `output` | Output file path pattern with `{version}` and `{lifecycle}` placeholders. | -| `output_products` | Optional override for the products array written to the bundle. Useful when the bundle should have a single product ID though it's filtered from many or have a different lifecycle or version than the filter. With multiple product IDs, Mode 3 rule resolution uses the first alphabetically; use separate profiles or bundle runs with a single product in `output_products` when you need a different rule context. | -| `repo` | Optional. Overrides `bundle.repo` for this profile only. Required when `source: github_release` is used and no `bundle.repo` is set. | -| `owner` | Optional. Overrides `bundle.owner` for this profile only. | -| `hide_features` | List of feature IDs to embed in the bundle as hidden. | - -Example profile configuration: - -```yaml -bundle: - repo: elasticsearch # The default repository for PR and issue links. - owner: elastic # The default repository owner for PR and issue links. - directory: docs/changelog # The directory that contains changelog files. - output_directory: docs/releases # The directory that contains changelog bundles. - # Optional: Default bundle description with placeholder support - description: | - This release includes new features and bug fixes. - - For more information, see the [release notes](https://www.elastic.co/docs/release-notes/elasticsearch#elasticsearch-{version}). - profiles: - elasticsearch-release: - products: "elasticsearch {version} {lifecycle}" - output: "elasticsearch/{version}.yaml" - output_products: "elasticsearch {version}" - # Profile-specific description overrides bundle.description - description: | - Elasticsearch {version} includes: - - Performance improvements - - Bug fixes and stability enhancements - - Download the release binaries: https://github.com/{owner}/{repo}/releases/tag/v{version} - hide_features: - - feature:experimental-api - serverless-release: - products: "cloud-serverless {version} *" - output: "serverless/{version}.yaml" - output_products: "cloud-serverless {version}" - # inherits repo: elasticsearch and owner: elastic from bundle level - # Multi-product profile: rule context for Mode 3 is the first product alphabetically (here: kibana). - # For security-specific rules only, use a separate profile with output_products listing only security. - kibana-security-release: - products: "kibana {version} {lifecycle}, security {version} {lifecycle}" - output: "kibana-security/{version}.yaml" - output_products: "kibana {version}, security {version}" -``` - -#### Bundle changelogs from a GitHub release [changelog-bundle-profile-github-release] - -Set `source: github_release` on a profile to make `changelog bundle` fetch the PR list directly from a published GitHub release. - -This is equivalent to running `changelog bundle --release-version `, but fully configured in `changelog.yml` so you don't have to remember command-line flags. - -```yaml -bundle: - owner: elastic - profiles: - agent-gh-release: - source: github_release - repo: apm-agent-dotnet - output: "my-agents-{version}.yaml" - output_products: "apm-agent-dotnet {version} {lifecycle}" -``` - -Invoke the profile with a version tag or `latest`: - -```sh -docs-builder changelog bundle agent-gh-release 1.34.0 -docs-builder changelog bundle agent-gh-release latest -``` - -The `{version}` placeholder is substituted with the clean base version extracted from the release tag (for example, `v1.34.0` → `1.34.0`, `v1.34.0-beta.1` → `1.34.0`). The `{lifecycle}` placeholder is inferred from the **release tag** returned by GitHub, not from the argument you pass to the command: - -| Release tag | `{version}` | `{lifecycle}` | -|-------------|-------------|---------------| -| `v1.2.3` | `1.2.3` | `ga` | -| `v1.2.3-beta.1` | `1.2.3` | `beta` | -| `v1.2.3-preview.1` | `1.2.3` | `preview` | - -This differs from standard profiles, where `{lifecycle}` is inferred from the version string you type at the command line. - -#### Bundle descriptions - -You can add introductory text to bundles using the `description` field. This text appears at the top of rendered changelogs, after the release heading but before the entry sections. - -**Configuration locations:** - -- `bundle.description`: Default description for all profiles -- `bundle.profiles..description`: Profile-specific description (overrides the default) - -**Placeholder support:** - -Bundle descriptions support these placeholders: - -- `{version}`: The resolved version string -- `{lifecycle}`: The resolved lifecycle (ga, beta, preview, etc.) -- `{owner}`: The GitHub repository owner -- `{repo}`: The GitHub repository name - -**Important**: When using `{version}` or `{lifecycle}` placeholders, you must ensure predictable substitution values: - -- **Option-based mode**: Requires `--output-products` when using placeholders -- **Profile-based mode**: Requires either a version argument (e.g., `bundle profile 9.2.0`) OR an `output_products` pattern in the profile configuration when using placeholders. If you invoke a profile with only a promotion report (e.g., `bundle profile ./report.html`), placeholders will fail unless `output_products` is configured. - -**Multiline descriptions in YAML:** - -For complex descriptions with multiple paragraphs, lists, and links, use YAML literal block scalars with the `|` (pipe) syntax: - -```yaml -bundle: - description: | - This release includes significant improvements: - - - Enhanced performance - - Bug fixes and stability improvements - - New features for better user experience - - For security updates, go to [security announcements](https://example.com/docs). - - Download the release binaries: https://github.com/{owner}/{repo}/releases/tag/v{version} -``` - -The `|` (pipe) preserves line breaks and is ideal for Markdown-formatted text. Avoid using `>` (greater than) for descriptions as it folds line breaks into spaces, making lists and paragraphs difficult to format correctly. - -**Command line usage:** - -For simple descriptions, use the `--description` option with regular quotes: - -```sh -docs-builder changelog bundle --all --description "This release includes new features." -``` - -For multiline descriptions on the command line, use ANSI-C quoting (`$'...'`) with `\n` for line breaks: - -```sh -docs-builder changelog bundle --all --description $'Enhanced release:\n\n- Performance improvements\n- Bug fixes' -``` - -`output_products` is optional. When omitted, the bundle products array is derived from the matched changelog files' own `products` fields — the same fallback used by all other profile types. Set `output_products` when you want a single clean product entry that reflects the release identity rather than the diverse metadata across individual changelog files, or to hardcode a lifecycle that cannot be inferred from the tag format: - -```yaml -# Produce one authoritative product entry instead of inheriting from changelog files -agent-gh-release: - source: github_release - repo: apm-agent-dotnet - output: "apm-agent-dotnet-{version}.yaml" - output_products: "apm-agent-dotnet {version} {lifecycle}" - -# Or hardcode the lifecycle when the tag format doesn't encode it -agent-gh-release-preview: - source: github_release - repo: apm-agent-dotnet - output: "apm-agent-dotnet-{version}-preview.yaml" - output_products: "apm-agent-dotnet {version} preview" -``` - -`source: github_release` is mutually exclusive with `products`, and a third positional argument (promotion report or URL list) is not accepted by this profile type. - -### Filter by product [changelog-bundle-product] - -You can use the `--input-products` option to create a bundle of changelogs that match the product details. -When using `--input-products`, you must provide all three parts: product, target, and lifecycle. -Each part can be a wildcard (`*`) to match any value. - -:::{tip} -If you use profile-based bundling, provide this information in the `bundle.profiles..products` field. -::: - -```sh -docs-builder changelog bundle \ - --input-products "cloud-serverless 2025-12-02 ga, cloud-serverless 2025-12-06 beta" <1> -``` - -1. Include all changelogs that have the `cloud-serverless` product identifier with target dates of either December 2 2025 (lifecycle `ga`) or December 6 2025 (lifecycle `beta`). For more information about product values, refer to [](#product-format). - -You can use wildcards in any of the three parts: - -```sh -# Bundle any changelogs that have exact matches for either of these clauses -docs-builder changelog bundle --input-products "cloud-serverless 2025-12-02 ga, elasticsearch 9.3.0 beta" - -# Bundle all elasticsearch changelogs regardless of target or lifecycle -docs-builder changelog bundle --input-products "elasticsearch * *" - -# Bundle all cloud-serverless 2025-12-02 changelogs with any lifecycle -docs-builder changelog bundle --input-products "cloud-serverless 2025-12-02 *" - -# Bundle any cloud-serverless changelogs with target starting with "2025-11-" and "ga" lifecycle -docs-builder changelog bundle --input-products "cloud-serverless 2025-11-* ga" - -# Bundle all changelogs (equivalent to --all) -docs-builder changelog bundle --input-products "* * *" -``` - -If you have changelog files that reference those product details, the command creates a file like this: - -```yaml -products: <1> -- product: cloud-serverless - target: 2025-12-02 -- product: cloud-serverless - target: 2025-12-06 -entries: -- file: - name: 1765495972-fixes-enrich-and-lookup-join-resolution-based-on-m.yaml - checksum: 6c3243f56279b1797b5dfff6c02ebf90b9658464 -- file: - name: 1765507778-break-on-fielddata-when-building-global-ordinals.yaml - checksum: 70d197d96752c05b6595edffe6fe3ba3d055c845 -``` - -1. By default these values match your `--input-products` (even if the changelogs have more products). -To specify different product metadata, use the `--output-products` option. - -### Filter by pull requests [changelog-bundle-pr] - -You can use the `--prs` option to create a bundle of the changelogs that relate to those pull requests. -You can provide either a comma-separated list of PRs (`--prs "https://github.com/owner/repo/pull/123,12345"`) or a path to a newline-delimited file (`--prs /path/to/file.txt`). -In the latter case, the file should contain one PR URL or number per line. - -Pull requests can be identified by a full URL (such as `https://github.com/owner/repo/pull/123`), a short format (such as `owner/repo#123`), or just a number (in which case you must also provide `--owner` and `--repo` options). - -```sh -docs-builder changelog bundle --prs "108875,135873,136886" \ <1> - --repo elasticsearch \ <2> - --owner elastic \ <3> - --output-products "elasticsearch 9.2.2 ga" <4> -``` - -1. The comma-separated list of pull request numbers to seek. -2. The repository in the pull request URLs. Not required when using full PR URLs, or when `bundle.repo` is set in the changelog configuration. -3. The owner in the pull request URLs. Not required when using full PR URLs, or when `bundle.owner` is set in the changelog configuration. -4. The product metadata for the bundle. If it is not provided, it will be derived from all the changelog product values. - -In Mode 3, the **rule context product** is the first alphabetically from `--output-products` (or from aggregated changelog products if omitted). To apply a different product's per-product rules, use a bundle whose `output_products` contains only that product (separate command or profile). - -If you have changelog files that reference those pull requests, the command creates a file like this: - -```yaml -products: -- product: elasticsearch - target: 9.2.2 - lifecycle: ga -entries: -- file: - name: 1765507819-fix-ml-calendar-event-update-scalability-issues.yaml - checksum: 069b59edb14594e0bc3b70365e81626bde730ab7 -- file: - name: 1765507798-convert-bytestransportresponse-when-proxying-respo.yaml - checksum: c6dbd4730bf34dbbc877c16c042e6578dd108b62 -- file: - name: 1765507839-use-ivf_pq-for-gpu-index-build-for-large-datasets.yaml - checksum: 451d60283fe5df426f023e824339f82c2900311e -``` - -### Filter by issues [changelog-bundle-issues] - -You can use the `--issues` option to create a bundle of changelogs that relate to those GitHub issues. -Provide either a comma-separated list of issues (`--issues "https://github.com/owner/repo/issues/123,456"`) or a path to a newline-delimited file (`--issues /path/to/file.txt`). -Issues can be identified by a full URL (such as `https://github.com/owner/repo/issues/123`), a short format (such as `owner/repo#123`), or just a number (in which case `--owner` and `--repo` are required — or set via `bundle.owner` and `bundle.repo` in the configuration). - -```sh -docs-builder changelog bundle --issues "12345,12346" \ - --repo elasticsearch \ - --owner elastic \ - --output-products "elasticsearch 9.2.2 ga" -``` - -### Filter by pull request or issue file [changelog-bundle-file] - -If you have a file that lists pull requests (such as PRs associated with a GitHub release), you can pass it to `--prs`. -For example, if you have a file that contains full pull request URLs like this: - -```txt -https://github.com/elastic/elasticsearch/pull/108875 -https://github.com/elastic/elasticsearch/pull/135873 -https://github.com/elastic/elasticsearch/pull/136886 -https://github.com/elastic/elasticsearch/pull/137126 -``` - -You can use the `--prs` option with the file path to create a bundle of the changelogs that relate to those pull requests. -You can also combine multiple `--prs` options: - -```sh -./docs-builder changelog bundle \ - --prs "https://github.com/elastic/elasticsearch/pull/108875,135873" \ <1> - --prs test/9.2.2.txt \ <2> - --output-products "elasticsearch 9.2.2 ga" <3> - --resolve <4> -``` - -1. Comma-separated list of pull request URLs or numbers. -2. The path for the file that lists the pull requests. If the file contains only PR numbers, you must add `--repo` and `--owner` command options. -3. The product metadata for the bundle. If it is not provided, it will be derived from all the changelog product values. -4. Optionally include the contents of each changelog in the output file. - -:::{tip} -You can use these files with profile-based bundling too. Refer to [](/cli/changelog/bundle.md). -::: - -If you have changelog files that reference those pull requests, the command creates a file like this: - -```yaml -products: -- product: elasticsearch - target: 9.2.2 - lifecycle: ga -entries: -- file: - name: 1765507778-break-on-fielddata-when-building-global-ordinals.yaml - checksum: 70d197d96752c05b6595edffe6fe3ba3d055c845 - type: bug-fix - title: Break on FieldData when building global ordinals - products: - - product: elasticsearch - areas: - - Aggregations - prs: - - https://github.com/elastic/elasticsearch/pull/108875 -... -``` - -:::{note} -When a changelog matches multiple `--input-products` filters, it appears only once in the bundle. This deduplication applies even when using `--all` or `--prs`. -::: - -### Filter by GitHub release notes [changelog-bundle-release-version] - -If you have GitHub releases with automated release notes (the default format or [Release Drafter](https://github.com/release-drafter/release-drafter) format), you can use the `--release-version` option to derive the PR list from those release notes. -For example: - -```sh -docs-builder changelog bundle \ - --release-version v1.34.0 \ - --repo apm-agent-dotnet --owner elastic <1> -``` - -1. The repo and repo owner are used to fetch the release and follow these rules of precedence: - -- Repo: `--repo` flag > `bundle.repo` in `changelog.yml` (one source is required) -- Owner: `--owner` flag > `bundle.owner` in `changelog.yml` > `elastic` - -This command creates a bundle of changelogs that match the list of PRs found in the `v1.34.0` GitHub release notes. - -The bundle's product metadata is inferred automatically from the release tag and repository name; you can override that behavior with the `--output-products` option. - -:::{tip} -If you are not creating changelogs when you create your pull requests, consider the `docs-builder changelog gh-release` command as a one-shot alternative to the `changelog add` and `changelog bundle` commands. -It parses the release notes, creates one changelog file per pull request found, and creates a `changelog-bundle.yaml` file — all in a single step. Refer to [](/cli/changelog/gh-release.md) -::: - -### Hide features [changelog-bundle-hide-features] - -You can use the `--hide-features` option to embed feature IDs that should be hidden when the bundle is rendered. This is useful for features that are not yet ready for public documentation. - -```sh -docs-builder changelog bundle \ - --input-products "elasticsearch 9.3.0 *" \ - --hide-features "feature:hidden-api,feature:experimental" \ <1> - --output /path/to/bundles/9.3.0.yaml -``` - -1. Feature IDs to hide. Changelogs with matching `feature-id` values will be commented out when rendered. - - - -The bundle output will include a `hide-features` field: - -```yaml -products: -- product: elasticsearch - target: 9.3.0 -hide-features: - - feature:hidden-api - - feature:experimental -entries: -- file: - name: 1765495972-new-feature.yaml - checksum: 6c3243f56279b1797b5dfff6c02ebf90b9658464 -``` - -When this bundle is rendered (either via the `changelog render` command or the `{changelog}` directive), changelogs with `feature-id` values matching any of the listed features will be commented out in the output. - -:::{note} -The `--hide-features` option on the `render` command and the `hide-features` field in bundles are **combined**. If you specify `--hide-features` on both the `bundle` and `render` commands, all specified features are hidden. The `{changelog}` directive automatically reads `hide-features` from all loaded bundles and applies them. -::: - -### Hide private links - -A changelog can reference multiple pull requests and issues in the `prs` and `issues` array fields. - -To comment out links that are not in your allowlist in all changelogs in your bundles, refer to [changelog bundle](/cli/changelog/bundle.md#link-allowlist). - -If you are working in a private repo and do not want any pull request or issue links to appear (even if they target a public repo), you also have the option to configure link visibiblity in the [changelog directive](/syntax/changelog.md) and [changelog render](/cli/changelog/render.md) command. - -:::{tip} -You must run the `docs-builder changelog bundle` command with the `--resolve` option or set `bundle.resolve` to `true` in the changelog configuration file (so that bundle files are self-contained) in order to hide the private links. -::: - -### Amend bundles [changelog-bundle-amend] - -When you need to add changelogs to an existing bundle without modifying the original file, you can use the `docs-builder changelog bundle-amend` command to create amend bundles. -Amend bundles follow a specific naming convention: `{parent-bundle-name}.amend-{N}.yaml` where `{N}` is a sequence number. - -When bundles are loaded (either via the `changelog render` command or the `{changelog}` directive), amend files are **automatically merged** with their parent bundles. -The changelogs from all matching amend files are combined with the parent bundle's changelogs and the result is rendered as a single release. - -:::{warning} -If you explicitly list the amend bundles in the `--input` option of the `docs-builder changelog render` command, you'll get duplicate entries in the output files. List only the original bundles. -::: - -For more details and examples, go to [](/cli/changelog/bundle-amend.md). - -## Create documentation - -### Control changelog publishing [example-rules-publishing] - -:::{warning} -This functionality is deprecated. Perform the filtering at bundle time instead. Using `rules.publish` emits a deprecation warning during configuration loading. -::: - -You can use rules in the changelog configuration file to refrain from publishing changelogs based on their areas and types. - -For example, your configuration file can contain a `rules` section like this: - -```yaml -rules: - # Global match default for multi-valued fields (labels, areas). - # any (default) = match if ANY item matches the list - # all = match only if ALL items match the list - # match: any - # Publish — controls which changelogs appear in rendered output. - publish: - exclude_types: - - docs - exclude_areas: - - "Internal" - products: - 'cloud-serverless': - exclude_areas: - - "Internal" - - "Autoscaling" - - "Watcher" - 'elasticsearch, kibana': - exclude_types: - - docs - - other -``` - -For example, if you run the `docs-builder changelog render` command for a Cloud Serverless bundle, any changelogs that have "Internal", "Autoscaling", or "Watcher" areas are commented out. - -You can also use **include** mode instead of **exclude** mode. -For example, to only publish changelogs with specific areas: - -```yaml -rules: - publish: - include_areas: - - "Search" - - "Monitoring" -``` - -When subsections are enabled (`:subsections:` in the `{changelog}` directive or `--subsections` in the `changelog render` command), these `include_areas` and `exclude_areas` rules also affect which area label is used for grouping. -Changelogs with multiple areas are grouped under the first area that aligns with the rules — the first included area for `include_areas`, or the first non-excluded area for `exclude_areas`. - -### Include changelogs inline [changelog-directive] - -You can use the [`{changelog}` directive](../syntax/changelog.md) to render all changelog bundles directly in your documentation pages. - -```markdown -:::{changelog} -::: -``` - -By default, the directive renders all bundles from `changelog/bundles/` (relative to the docset root), ordered by semantic version (newest first). -For full documentation and examples, refer to the [{changelog} directive syntax reference](../syntax/changelog.md). - -:::{note} -All product-specific filtering must be configured at bundle time via `rules.bundle`. Unlike the `changelog render` command, the directive does not apply `rules.publish`. -::: - -### Generate markdown or asciidoc [render-changelogs] - -The `docs-builder changelog render` command creates markdown or asciidoc files from changelog bundles for documentation purposes. -For up-to-date details, use the `-h` command option or refer to [](/cli/changelog/render.md). - -Before you can use this command you must create changelog files and collect them into bundles. -For example, the `docs-builder changelog bundle` command creates a file like this: - -```yaml -products: -- product: elasticsearch - target: 9.2.2 -entries: -- file: - name: 1765581721-convert-bytestransportresponse-when-proxying-respo.yaml - checksum: d7e74edff1bdd3e23ba4f2f88b92cf61cc7d490a -- file: - name: 1765581721-fix-ml-calendar-event-update-scalability-issues.yaml - checksum: dfafce50c9fd61c3d8db286398f9553e67737f07 -- file: - name: 1765581651-break-on-fielddata-when-building-global-ordinals.yaml - checksum: 704b25348d6daff396259216201053334b5b3c1d -``` - -To create markdown files from this bundle, run the `docs-builder changelog render` command: - -```sh -docs-builder changelog render \ - --input "/path/to/changelog-bundle.yaml|/path/to/changelogs|elasticsearch|keep-links,/path/to/other-bundle.yaml|/path/to/other-changelogs|kibana|hide-links" \ <1> - --title 9.2.2 \ <2> - --output /path/to/release-notes \ <3> - --subsections <4> -``` - -1. Provide information about the changelog bundle(s). The format for each bundle is `"|||"` using pipe (`|`) as delimiter. To merge multiple bundles, separate them with commas (`,`). Only the `` is required for each bundle. The `` is useful if the changelogs are not in the default directory and are not resolved within the bundle. The `` is necessary if your changelogs do not contain full URLs for the pull requests or issues. The `` can be `hide-links` or `keep-links` (default) to control whether PR/issue links are hidden for changelogs from private repositories. -2. The `--title` value is used for an output folder name and for section titles in the output files. If you omit `--title` and the first bundle contains a product `target` value, that value is used. Otherwise, if none of the bundles have product `target` fields, the title defaults to "unknown". -3. By default the command creates the output files in the current directory. -4. By default the changelog areas are not displayed in the output. Add `--subsections` to group changelog details by their `areas`. For breaking changes that have a `subtype` value, the subsections will be grouped by subtype instead of area. - -:::{important} -Paths in the `--input` option must be absolute paths or use environment variables. Tilde (`~`) expansion is not supported. -::: - -For example, the `index.md` output file contains information derived from the changelogs: - -```md -## 9.2.2 [elastic-release-notes-9.2.2] - -### Fixes [elastic-9.2.2-fixes] - -**Network** -* Convert BytesTransportResponse when proxying response from/to local node. [#135873](https://github.com/elastic/elastic/pull/135873) - -**Machine Learning** -* Fix ML calendar event update scalability issues. [#136886](https://github.com/elastic/elastic/pull/136886) [#136900](https://github.com/elastic/elastic/pull/136900) - -**Aggregations** -* Break on FieldData when building global ordinals. [#108875](https://github.com/elastic/elastic/pull/108875) -``` - -When a changelog includes multiple values in its `prs` or `issues` arrays, all its links are rendered inline, as shown in the Machine Learning example above. - -To comment out the pull request and issue links, for example if they relate to a private repository, add `hide-links` to the `--input` option for that bundle. -This allows you to selectively hide links per bundle when merging changelogs from multiple repositories. -When `hide-links` is set, all PR and issue links for affected changelogs are hidden together. - -If you have changelogs with `feature-id` values and you want them to be omitted from the output, use the `--hide-features` option. Feature IDs specified via `--hide-features` are **merged** with any `hide-features` already present in the bundle files. This means both CLI-specified and bundle-embedded features are hidden in the output. - -To create an asciidoc file instead of markdown files, add the `--file-type asciidoc` option: - -```sh -docs-builder changelog render \ - --input "./changelog-bundle.yaml,./changelogs,elasticsearch" \ - --title 9.2.2 \ - --output ./release-notes \ - --file-type asciidoc \ <1> - --subsections -``` - -1. Generate a single asciidoc file instead of multiple markdown files. - -#### Release highlights - -The `highlight` field allows you to mark changelogs that should appear in a dedicated highlights page. -Highlights are most commonly used for major or minor version releases to draw attention to the most important changes. - -When you set `highlight: true` in a changelog: - -- It appears in both the highlights page (`highlights.md`) and its normal type section (for example "Features and enhancements") -- The highlights page is only created when at least one changelog has `highlight: true` (unlike other special pages like `known-issues.md` which are always created) -- Highlights can be any type of changelog (features, enhancements, bug fixes, etc.) - -Example changelog with highlight: - -```yaml -type: feature -products: -- product: elasticsearch - target: 9.3.0 - lifecycle: ga -title: New Cloud Connect UI for self-managed installations -description: Adds Cloud Connect functionality to Kibana, which allows you to use cloud solutions like AutoOps and Elastic Inference Service in your self-managed Elasticsearch clusters. -highlight: true -``` - -When rendering, changelogs with `highlight: true` are collected from all types and rendered in a dedicated highlights section. -In markdown output, this creates a separate `highlights.md` file. -In asciidoc output, highlights appear as a dedicated section in the single asciidoc file. - -## Remove changelog files [changelog-remove] - -A single changelog file might be applicable to multiple releases (for example, it might be delivered in both Stack and {{serverless-short}} releases or {{ech}} and Enterprise releases on different timelines). -After it has been included in all of the relevant bundles, it is reasonable to delete the changelog to keep your repository clean. - -:::{important} -If you create docs with changelog directives, run the `docs-builder changelog bundle` command with the `--resolve` option or set `bundle.resolve` to `true` in the changelog configuration file (so that bundle files are self-contained). -Otherwise, the build will fail if you remove changelogs that the directive requires. - -Likewise, the `docs-builder changelog render` command fails for "unresolved" bundles after you delete the changelogs. -::: - -You can use the `docs-builder changelog remove` command to remove changelogs. -It supports the same two modes as `changelog bundle`: you can specify all the command options or you can define "profiles" in the changelog configuration file. -In the command option mode, exactly one filter option must be specified: `--all`, `--products`, `--prs`, `--issues`, `--release-version`, or `--report`. - -Before deleting, the command automatically scans for bundles that still hold unresolved (`file:`) references to the matching changelog files. -If any are found, the command reports an error for each dependency. -This check prevents the `{changelog}` directive from failing at build time with missing file errors. -To proceed with removal even when unresolved bundle dependencies exist, use `--force`. - -To preview what would be removed without deleting anything, use `--dry-run`. -Bundle dependency conflicts are also reported in dry-run mode. - -### Removal with profiles [changelog-remove-profile] - -If your `changelog.yml` configuration file defines `bundle.profiles`, you can use those profiles with `changelog remove`. -This is the easiest way to remove exactly the changelogs that were included in a profile-based bundle. -The command syntax is: - -```sh -docs-builder changelog remove -``` - -For example, if you bundled with: - -```sh -docs-builder changelog bundle elasticsearch-release 9.2.0 -``` - -You can remove the same changelogs with: - -```sh -docs-builder changelog remove elasticsearch-release 9.2.0 --dry-run -``` - -The command automatically discovers `changelog.yml` by checking `./changelog.yml` then `./docs/changelog.yml` relative to your current directory. -If no configuration file is found, the command returns an error with advice to create one or to run from the directory where the file exists. - -The `output`, `output_products`, `hide_features`, `link_allow_repos`, and `resolve` fields are bundle-specific and are always ignored for removal (along with other bundle-only settings that do not affect which changelog files match the filter). -Which other fields are used depends on the profile type: - -- Standard profiles: only the `products` field is used. The `repo` and `owner` fields are ignored (they only affect bundle output metadata). -- GitHub release profiles (`source: github_release`): `source`, `repo`, and `owner` are all used. The command fetches the PR list from the GitHub release identified by the version argument and removes changelogs whose `prs` field matches. - -For example, given a GitHub release profile: - -```sh -docs-builder changelog remove agent-gh-release v1.34.0 --dry-run -``` - -This fetches the PR list from the `v1.34.0` release (using the profile's `repo`/`owner` settings) and removes matching changelogs. - -:::{note} -`source: github_release` profiles require a `GITHUB_TOKEN` or `GH_TOKEN` environment variable (or an active `gh` login) to fetch release details from the GitHub API. -::: - -Profile-based removal is mutually exclusive with command options. -The only options allowed alongside a profile name are `--dry-run` and `--force`. - -You can also pass a promotion report URL, file path, or URL list file as the second argument, and the command removes changelogs whose pull request or issue URLs appear in the report: - -```sh -docs-builder changelog remove elasticsearch-release https://buildkite.../promotion-report.html -docs-builder changelog remove serverless-release 2026-02 ./promotion-report.html -docs-builder changelog remove serverless-release 2026-02 ./prs.txt -``` - -### Removal with command options [changelog-remove-raw] - -You can alternatively remove changelogs based on their issues, pull requests, product metadata, or remove all changelogs from a folder. -Exactly one filter option must be specified: `--all`, `--products`, `--prs`, `--issues`, `--release-version` or `--report`. -When using a file for `--prs` or `--issues`, every line must be a fully-qualified GitHub URL. - -```sh -docs-builder changelog remove --products "elasticsearch 9.3.0 *" --dry-run -``` +1. [Bundle changelogs](/contribute/bundle-changelogs.md) with the `docs-builder changelog bundle` command. For example, create a bundle for the pull requests that are included in a product release. When changelogs are no longer needed in the repo, [remove changelog files](/contribute/bundle-changelogs.md#changelog-remove) with `docs-builder changelog remove`. +1. [Publish release notes](/contribute/publish-changelogs.md): Use the `{changelog}` directive in docs or `docs-builder changelog render` to produce release documentation. -For full option details, go to [](/cli/changelog/remove.md). +For more information about running `docs-builder`, go to [Contribute locally](https://www.elastic.co/docs/contribute-docs/locally). \ No newline at end of file diff --git a/docs/contribute/configure-changelogs.md b/docs/contribute/configure-changelogs.md new file mode 100644 index 000000000..3c38a5083 --- /dev/null +++ b/docs/contribute/configure-changelogs.md @@ -0,0 +1,308 @@ +# Configure changelogs + +Before you can use the `docs-builder changelog` commands in your development workflow, you must make some decisions and do some setup steps: + +1. Ensure that your products exist in [products.yml](https://github.com/elastic/docs-builder/blob/main/config/products.yml). +1. Add labels to your GitHub pull requests that map to [changelog types](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/ChangelogEntryType.cs). At a minimum, create labels for the `feature`, `bug-fix`, and `breaking-change` types. +1. Optional: Choose areas or components that your changes affect and add labels to your GitHub pull requests (such as `:Analytics/Aggregations`). +1. Optional: Add labels to your GitHub pull requests to indicate that they are not notable and should not generate changelogs. For example, `non-issue` or `release_notes:skip`. Alternatively, you can assume that all PRs are *not* notable unless a specific label is present (for example, `@Public`). + +After you collect all this information, you can use it to make the changelog process more automated and repeatable by setting up a changelog configuration file. + +## Create a changelog configuration file [changelog-settings] + +The changelog configuration file: + +- Defines acceptable product, type, subtype, and lifecycle values. +- Sets default options, such as whether to extract issues and release note text from pull requests. +- Defines profiles for simplified bundle creation. +- Prevents the creation of changelogs when certain labels are present. +- Excludes changelogs from bundles based on their areas, types, or products. + +:::{tip} +Only one configuration file is required for each repository. +You must maintain the file if your repo labels change over time. +::: + +You can use the [docs-builder changelog init](/cli/changelog/init.md) command to create the changelog configuration file and folder structure automatically. +The command uses an existing docs folder or creates `{path}/docs` when it does not exist. +It creates a `changelog.yml` file in the `docs` folder and creates sub-folders for the changelog and bundle files. +Alternatively, you can create the file and folders manually. + +For the most up-to-date changelog configuration options, refer to [changelog.example.yml](https://github.com/elastic/docs-builder/blob/main/config/changelog.example.yml). + +## Rules for creation and bundling [rules] + +If you have pull request labels that indicate a changelog is not required (such as `>non-issue` or `release_note:skip`), you can declare these in the `rules.create` section of the changelog configuration. + +When you run the `docs-builder changelog add` command with the `--prs` or `--issues` options and the pull request or issue has one of the identified labels, the command does not create a changelog. + +Likewise, if you want to exclude changelogs with certain products, areas, or types from the release bundles, you can declare these in the `rules.bundle` section of the changelog configuration. +For example, you might choose to omit `other` or `docs` changelogs. +Or you might want to omit all autoscaling-related changelogs from the Cloud Serverless release bundles. + +:::{warning} +`rules.publish` is deprecated and no longer used by the `changelog render` command. Move your type/area filtering to `rules.bundle` so it applies at bundle time. Using `rules.publish` emits a deprecation warning during configuration loading. +::: + +You can define rules at the global level (applies to all products) or for specific products. +Product-specific rules **override** the global rules entirely—they do not merge. +For more information about the global versus per-product behavior of `rules.bundle`, refer to [bundle rule modes](#bundle-rule-modes). + +### `rules.match` [rules-match] + +Global match default for multi-valued fields (labels, areas). + +| Value | Description | +|-------|-------------| +| `any` (default) | Match if ANY item in the relevant changelog field matches an item in the configured list | +| `all` | Match only if ALL items in the relevant changelog field match items in the configured list (subset semantics; see product/area tables) | +| `conjunction` | Match only if EVERY item in the configured list appears in the relevant changelog field (logical AND over the list) | + +The `match` setting cascades from global to section to product: + +``` +rules.match (global default, "any" if omitted) + ├─ rules.create.match → rules.create.products.{id}.match + ├─ rules.bundle.match_products + ├─ rules.bundle.match_areas → rules.bundle.products.{id}.match_areas + └─ rules.publish.match_areas → rules.publish.products.{id}.match_areas (deprecated) +``` + +If a lower-level `match` or `match_areas` is specified, it overrides the inherited value. + +### `rules.create` [rules-create] + +Filters the pull requests or issues that can generate changelogs. +Evaluated when running `docs-builder changelog add` with `--prs` or `--issues`. + +| Option | Type | Description | +|--------|------|-------------| +| `exclude` | string | Comma-separated labels that prevent changelog creation. A PR with any matching label is skipped. | +| `include` | string | Comma-separated labels required for changelog creation. A PR without any matching label is skipped. | +| `match` | string | Override `rules.match` for create rules. Values: `any`, `all`, `conjunction`. | +| `products` | map | Product-specific create rules (per following section). | + +You cannot specify both `exclude` and `include`. + +#### Product-specific create rules (`rules.create.products`) [rules-create-products] + +Product keys can be a single product ID or a comma-separated list of product IDs (for example, `'elasticsearch, kibana'`). +Each product override supports the same `exclude`, `include`, and `match` options. +Product-specific rules **override** the global create rules entirely. + +```yaml +rules: + create: + exclude: ">non-issue" + products: + 'elasticsearch, kibana': + exclude: ">test" + cloud-serverless: + exclude: ">non-issue, ILM" +``` + +### `rules.bundle` [rules-bundle] + +Filters the changelogs that are included in a bundle file. +Applied during `docs-builder changelog bundle` and `docs-builder changelog gh-release` after the primary filter (`--prs`, `--issues`, `--all`) has matched entries. + +Input stage (gathering entries) and bundle filtering stage (filtering for output) are conceptually separate. +Which global fields take effect depends on the [bundle rule mode](#bundle-rule-modes). + +#### Bundle rule modes [bundle-rule-modes] + +The bundler chooses one of three modes from your parsed `rules.bundle` configuration: + +| Mode | When it applies | Filtering behavior | +|------|-----------------|-------------------| +| **1 — No filtering** | There is no effective bundle rule: no `exclude_products` / `include_products`, no type/area blocker, and no non-empty `products` map. | No product, type, or area filtering from `rules.bundle`. | +| **2 — Global content** | At least one global filter or blocker is set, and `products` section is absent or empty (including `products: {}`). | Global lists are evaluated against each changelog’s own `products`, `type`, and `areas`. There is no single rule-context product and no disjoint exclusion. Changelogs with missing or empty `products` are included with a warning; global product include or exclude lists are skipped for those entries, global type and area rules still apply. | +| **3 — Per-product context** | `products` section has at least one key with a rule block. | Global `exclude_products`, `include_products`, `match_products`, and global type and area fields under `rules.bundle` are not used for filtering. configure what you need under each product key (or use Mode 2 by removing product keys). The bundle uses a single rule-context product, disjoint changelogs are excluded, and changelogs with missing or empty `products` are excluded with a warning. If the rule-context product has no per-product block, the entry passes through without global fallback. | + +Configuration loading emits a hint when both global bundle fields and a non-empty `products` map are present because global keys are ignored in Mode 3. + +#### Product filtering + +| Option | Type | Description | +|--------|------|-------------| +| `exclude_products` | string or list | Product IDs to exclude from the bundle. Cannot be combined with `include_products`. | +| `include_products` | string or list | Only these product IDs are included; all others are excluded. Cannot be combined with `exclude_products`. | +| `match_products` | string | Override `rules.match` for product matching. Values: `any`, `all`, `conjunction`. | + +#### Type and area filtering + +| Option | Type | Description | +|--------|------|-------------| +| `exclude_types` | string or list | Changelog types to exclude from the bundle. | +| `include_types` | string or list | Only changelogs with these types are kept; all others are excluded. | +| `exclude_areas` | string or list | Changelog areas to exclude from the bundle. | +| `include_areas` | string or list | Only changelogs with these areas are kept; all others are excluded. | +| `match_areas` | string | Override `rules.match` for area matching. Values: `any`, `all`, `conjunction`. | +| `products` | map | Per-product type/area filter overrides (per following section). | + +You cannot specify both `exclude_products` and `include_products`, both `exclude_types` and `include_types`, or both `exclude_areas` and `include_areas`. You can mix exclude and include across different fields (for example, `exclude_types` with `include_areas`). + +When a changelog is excluded by `rules.bundle`, the bundling service emits a warning with a `[-bundle-exclude]`, `[-bundle-include]`, `[-bundle-type-area]`, or mode-specific prefix such as `[-bundle-global]`. + +:::{important} +In **Mode 3** (non-empty `rules.bundle.products`), per-product `include_products` can **only** affect changelogs that already contain the rule context product. +It cannot pull in changelogs that are disjoint from that context. +Under **Mode 2** (global-only `rules.bundle`), `match_products: any` with `include_products` is meaningful: each changelog is evaluated on its own, so OR-style inclusion (for example, elasticsearch **or** kibana) works without per-product blocks. +::: + +#### Product-specific bundle rules (`rules.bundle.products`) [rules-bundle-products] + +This section applies to **Mode 3 — Per-product context** (at least one key under `rules.bundle.products` with rules). + +Product keys can be a single product ID or a comma-separated list. +Each product override supports: + +- **Product filtering**: `include_products`, `exclude_products`, `match_products` — controls which changelog entries are included based on their product IDs +- **Type/area filtering**: `exclude_types`, `include_types`, `exclude_areas`, `include_areas`, `match_areas` — controls which entries are included based on their type and area fields + +When a per-product rule applies to an entry, it is used **instead of** any global `rules.bundle` filters (global bundle keys are not applied in Mode 3). If a filter type is omitted in that per-product block, it is not inherited from global `rules.bundle` — repeat the constraint under the product key if you still need it. + +If the changelog contains the rule context product but **no** block exists for that product ID, the entry is **included** without applying global bundle filters (**pass-through**). + +**Example (Mode 3)** + +Per-product rule replaces global keys for matching entries: + +```yaml +rules: + bundle: + exclude_types: [docs] + exclude_areas: [Internal] + products: + kibana: + include_areas: [UI] +``` + +The result when the rule context product is `kibana` is as follows: + +- Elasticsearch-only entries: **excluded** as disjoint (they never use the `kibana` block). +- Kibana entries: only the `kibana` block applies — global `exclude_types` / `exclude_areas` do not apply. Add `exclude_types` under `kibana` if you still need to drop `docs` entries. + +**Mode 3** uses a **single rule-context product** for each bundle: + +1. **Rule context product**: + - **With `--output-products`** (CLI) or profile **`output_products`**: First product alphabetically from that list + - **Without** those: First product alphabetically from all products aggregated from matched changelog entries (regardless of input method: `--all`, `--prs`, `--issues`, etc.) + +2. **For each changelog**: + - **Contains rule context product** and a per-product block exists for that product: apply that block (product rules, then type/area for that block). + - **Contains rule context product** and **no** per-product block for that product: **include** without applying global `rules.bundle` filters (pass-through). + - **Disjoint** from rule context: **exclude** the changelog. + - **No products** in the changelog: emit a warning and **exclude** the changelog. + +**Input method independence**: Bundle filtering still applies regardless of how entries were gathered (`--input-products`, `--prs`, `--all`, etc.). + +For example, with `--output-products "kibana 9.3.0, security 9.3.0"` (rule context: `kibana`): + +| Changelog `products` | Contains `kibana`? | Result (Mode 3) | +|--------------------|-------------------|---------| +| `[kibana]` | Yes | Use `kibana` per-product rules if defined; otherwise pass-through | +| `[security]` | No | **Excluded** (disjoint) | +| `[kibana, security]` | Yes | Use `kibana` per-product rules if defined; otherwise pass-through | +| `[elasticsearch]` | No | **Excluded** (disjoint) | +| `[]` (empty/missing) | No | **Excluded** with warning | + +**Multi-product bundles**: For release notes that need different rule behavior per product, run **separate** `changelog bundle` invocations with a **single** product in `--output-products` (or a profile whose `output_products` resolves to one product), or use **Mode 2** (global-only `rules.bundle`) when you need OR-style product inclusion without disjoint exclusion. + +### `rules.publish` + +:::{warning} +`rules.publish` is deprecated and **no longer used by the `changelog render` command**. The command now only supports `rules.bundle` for type/area filtering at bundle time. Using `rules.publish` emits a deprecation warning during configuration loading. +::: + +`rules.publish` is ignored by the `changelog render` command and will be removed in a future release. If you have `rules.publish` configured, move your type/area filtering to `rules.bundle` so it applies at bundle time. + +**Deprecated (no longer used):** + +```yaml +rules: + publish: + exclude_types: docs + exclude_areas: + - Internal +``` + +**Use instead:** + +```yaml +rules: + bundle: + exclude_types: docs + exclude_areas: + - Internal +``` + +### Product matching behavior + +The following applies to **global** `rules.bundle` product lists (**Mode 2**). In **Mode 3**, product matching uses the per-product block for the rule context product instead. + +With `match_products`, the behavior differs depending on the mode. The keyword **`conjunction`** means *every product ID in the config list must appear on the changelog* (logical AND). It does not refer to the `include_products` / `exclude_products` field names — those choose **which** list and **include vs exclude**; `match_products` chooses **how** that list is interpreted. + +| Config | Changelog `products` | `match_products` | Result | +|--------|----------------|----------------|--------| +| `exclude_products: [cloud-enterprise]` | `[cloud-enterprise, kibana]` | `any` | **Excluded** ("cloud-enterprise" matches) | +| `exclude_products: [cloud-enterprise]` | `[cloud-enterprise, kibana]` | `all` | **Included** (not all products are in the exclude list) | +| `exclude_products: [kibana, observability]` | `[kibana]` | `conjunction` | **Included** (not every listed exclude ID is on the changelog) | +| `exclude_products: [kibana, observability]` | `[kibana, observability]` | `conjunction` | **Excluded** (every listed exclude ID is on the changelog) | +| `include_products: [elasticsearch]` | `[elasticsearch, kibana]` | `any` | **Included** ("elasticsearch" matches) | +| `include_products: [elasticsearch]` | `[elasticsearch, kibana]` | `all` | **Excluded** ("kibana" is not in the include list) | +| `include_products: [elasticsearch, security]` | `[elasticsearch, security, kibana]` | `conjunction` | **Included** (every listed include ID is on the changelog) | +| `include_products: [elasticsearch, security]` | `[elasticsearch]` | `conjunction` | **Excluded** ("security" is missing from the changelog) | + +In practice, most changelogs have a single product, so `any` (the default) and `all` behave identically for them. +The difference only matters for changelogs with multiple products. + +### Area matching behavior + +With `match_areas` (applies to both `rules.bundle` and `rules.publish`), the behavior differs depending on the mode. As with products, **`conjunction`** means every area in the config list must appear on the changelog. + +| Config | Changelog `areas` | `match_areas` | Result | +|--------|------------|-------------|--------| +| `exclude_areas: [Internal]` | `[Search, Internal]` | `any` | **Excluded** ("Internal" matches) | +| `exclude_areas: [Internal]` | `[Search, Internal]` | `all` | **Included** (not all areas are in the exclude list) | +| `exclude_areas: [Search, Internal]` | `[Search]` | `conjunction` | **Included** ("Internal" is not on the changelog) | +| `exclude_areas: [Search, Internal]` | `[Search, Internal, Monitoring]` | `conjunction` | **Excluded** (every listed exclude area is on the changelog) | +| `include_areas: [Search]` | `[Search, Internal]` | `any` | **Included** ("Search" matches) | +| `include_areas: [Search]` | `[Search, Internal]` | `all` | **Excluded** ("Internal" is not in the include list) | +| `include_areas: [Search, Internal]` | `[Search, Internal]` | `conjunction` | **Included** (every listed include area is on the changelog) | +| `include_areas: [Search, Internal]` | `[Search]` | `conjunction` | **Excluded** ("Internal" is missing from the changelog) | + +### Validation + +The following configurations cause validation errors: + +| Condition | Error | +|-----------|-------| +| Old `block:` key found | `'block' is no longer supported. Rename to 'rules'. See changelog.example.yml.` | +| Both `exclude` and `include` in create | `rules.create: cannot have both 'exclude' and 'include'. Use one or the other.` | +| Both `exclude_types` and `include_types` in bundle | `rules.bundle: cannot have both 'exclude_types' and 'include_types'. Use one or the other.` | +| Both `exclude_areas` and `include_areas` in bundle | `rules.bundle: cannot have both 'exclude_areas' and 'include_areas'. Use one or the other.` | +| Both `exclude_products` and `include_products` in bundle | `rules.bundle: cannot have both 'exclude_products' and 'include_products'. Use one or the other.` | +| Both `exclude_types` and `include_types` in publish | `rules.publish: cannot have both 'exclude_types' and 'include_types'. Use one or the other.` | +| Both `exclude_areas` and `include_areas` in publish | `rules.publish: cannot have both 'exclude_areas' and 'include_areas'. Use one or the other.` | +| `rules.publish` present | Deprecation warning: `rules.publish is deprecated. Move type/area filtering to rules.bundle.` | +| Invalid match value | `rules.match: '{value}' is not valid. Use 'any', 'all', or 'conjunction'.` | +| Unknown product ID in bundle | `rules.bundle.exclude_products: '{id}' is not in the list of available products.` | +| Unknown product ID | `rules.create.products: '{id}' not in available products.` | + +### Ineffective configuration patterns [ineffective-configuration-patterns] + +Some `rules.bundle` combinations are valid YAML but do not filter the way you might expect: + +- **`match_products: any` with `include_products` in a per-product rule** provides no selective filtering in the common case. Consider `match_products: all` for strict filtering or `exclude_products` for exclusion-based filtering. +- **Disjoint products in `include_products`** in a per-product rule: If you list more than one product ID and some are disjoint from the rule context product, those changelogs cannot be included. Use separate bundles (each with a single product in `--output-products` or profile `output_products`), or multi-product changelogs instead. + +For how global `rules.bundle` fields interact with `products` keys, see [Bundle rule modes](#bundle-rule-modes). + +## Use a changelog configuration file + +By default, changelog commands check the following path: `docs/changelog.yml`. +You can specify a different path with the `--config` command option. + +For specific details about the usage and impact of the configuration file, refer to the [changelog commands](/cli/changelog/index.md). \ No newline at end of file diff --git a/docs/contribute/create-changelogs.md b/docs/contribute/create-changelogs.md new file mode 100644 index 000000000..587976822 --- /dev/null +++ b/docs/contribute/create-changelogs.md @@ -0,0 +1,312 @@ +# Create changelogs + +The changelogs associated with the `docs-builder changelog` commands use the following schema: + +:::{dropdown} Changelog schema +::::{include} /contribute/_snippets/changelog-fields.md +:::: +::: + +:::{important} +Some of the fields in the schema accept only a specific set of values: + +- Product values must exist in [products.yml](https://github.com/elastic/docs-builder/blob/main/config/products.yml). Invalid products will cause the `docs-builder changelog add` command to fail. +- Type, subtype, and lifecycle values must match the available values defined in [ChangelogEntryType.cs](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/ChangelogEntryType.cs), [ChangelogEntrySubtype.cs](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/ChangelogEntrySubtype.cs), and [Lifecycle.cs](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/Lifecycle.cs) respectively. Invalid values will cause the `docs-builder changelog add` command to fail. +::: + +## Create changelog files [changelog-add] + +You can use the `docs-builder changelog add` command to create a changelog file. + +If you specify `--prs` or `--issues`, the command tries to fetch information from GitHub. It derives the changelog `title` from the pull request or issue title, maps labels to areas, products, and type (if configured), and extracts linked references. +With `--issues`, it extracts linked PRs from the issue body (for example, "Fixed by #123"). +With `--prs`, it extracts linked issues from the PR body (for example, "Fixes #123"). + +When `--repo`, `--owner`, or `--output` are not specified, the command reads them from the `bundle` section of `changelog.yml` (`bundle.repo`, `bundle.owner`, `bundle.directory`). This applies to all modes — `--prs`, `--issues`, and `--release-version` alike. If no config value is available, `--owner` defaults to `elastic` and `--output` defaults to the current directory. + +:::{tip} +Ideally this task will be automated such that it's performed by a bot or GitHub action when you create a pull request. +If you run it from the command line, you must precede any special characters (such as backquotes) with a backslash escape character (`\`). +::: + +### CI two-step flow + +When automated via the [changelog GitHub Actions](https://github.com/elastic/docs-actions/tree/main/changelog), changelog creation is a two-step process: + +1. **`changelog evaluate-pr`** inspects the PR (title, labels, body) and produces outputs such as `title`, `type`, `description`, and `products`. +2. **`changelog add`** reads those outputs from `CHANGELOG_*` environment variables and generates the changelog YAML file. + +The `description` output from step 1 contains the release note extracted from the PR body (when `extract.release_notes` is enabled). If extraction is disabled — either by setting `extract.release_notes: false` in `changelog.yml` or by passing `--no-extract-release-notes` to `changelog add` — the `CHANGELOG_DESCRIPTION` environment variable is ignored and the extracted description is not written to the changelog. + +Refer to [CI auto-detection](/cli/changelog/add.md#ci-auto-detection) for the full list of environment variables and precedence rules. + +For up-to-date command usage information, use the `-h` option or refer to [](/cli/changelog/add.md). + +### Authorization + +If you use the `--prs`, `--issues`, or `--release-version` options, the `docs-builder changelog add` command interacts with GitHub services. +The `--release-version` option on the `docs-builder changelog add`, `bundle`, and `remove` commands also interacts with GitHub services. +Log into GitHub or set the `GITHUB_TOKEN` (or `GH_TOKEN` ) environment variable with a sufficient personal access token (PAT). +Otherwise, there will be fetch failures when you access private repositories and you might also encounter GitHub rate limiting errors. + +For example, to create a new token with the minimum authority to read pull request details: + +1. Go to **GitHub Settings** > **Developer settings** > **Personal access tokens** > [Fine-grained tokens](https://github.com/settings/personal-access-tokens). +2. Click **Generate new token**. +3. Give your token a descriptive name (such as "docs-builder changelog"). +4. Under **Resource owner** if you're an Elastic employee, select **Elastic**. +5. Set an expiration date. +6. Under **Repository access**, select **Only select repositories** and choose the repositories you want to access. +7. Under **Permissions** > **Repository permissions**, set **Pull requests** to **Read-only**. If you want to be able to read issue details, do the same for **Issues**. +8. Click **Generate token**. +9. Copy the token to a safe location and use it in the `GITHUB_TOKEN` environment variable. + +### Product format + +The `docs-builder changelog add` has a `--products` option and the `docs-builder changelog bundle` has `--input-products` and `--output-products` options that all use the same format. + +They accept values with the format `"product target lifecycle, ..."` where: + +- `product` is the product ID from [products.yml](https://github.com/elastic/docs-builder/blob/main/config/products.yml) (required) +- `target` is the target version or date (optional) +- `lifecycle` is one of: `preview`, `beta`, or `ga` (optional) + +Examples: + +- `"kibana 9.2.0 ga"` +- `"cloud-serverless 2025-08-05"` +- `"cloud-enterprise 4.0.3, cloud-hosted 2025-10-31"` + +### Filenames + +The `docs-builder changelog add` command names generated files according to the `filename` strategy in `changelog.yml`: + +| Strategy | Example filename | Description | +|---|---|---| +| `timestamp` (default) | `1735689600-fixes-enrich-and-lookup-join-resolution.yaml` | Uses a Unix timestamp with a sanitized title slug. | +| `pr` | `137431.yaml` | Uses the PR number. | +| `issue` | `2571.yaml` | Uses the issue number. | + +Set the strategy in your changelog configuration file: + +```yaml +filename: timestamp +``` + +Refer to [changelog.example.yml](https://github.com/elastic/docs-builder/blob/main/config/changelog.example.yml) for full documentation. + +You can override the configured strategy per invocation with the `--use-pr-number` or `--use-issue-number` CLI flags: + +```sh +docs-builder changelog add \ + --prs https://github.com/elastic/elasticsearch/pull/137431 \ + --products "elasticsearch 9.2.3" \ + --use-pr-number + +docs-builder changelog add \ + --issues https://github.com/elastic/docs-builder/issues/2571 \ + --products "elasticsearch 9.3.0" \ + --config docs/changelog.yml \ + --use-issue-number +``` + +:::{important} +`--use-pr-number` and `--use-issue-number` are mutually exclusive; specify only one. Each requires `--prs` or `--issues`. The numbers are extracted from the URLs or identifiers you provide, or from linked references in the issue or PR body when extraction is enabled. + +**Precedence**: CLI flags (`--use-pr-number` / `--use-issue-number`) > `filename` in `changelog.yml` > default (`timestamp`). +::: + +### Examples + +#### Create a changelog for multiple products [example-multiple-products] + +```sh +docs-builder changelog add \ + --title "Fixes enrich and lookup join resolution based on minimum transport version" \ <1> + --type bug-fix \ <2> + --products "elasticsearch 9.2.3, cloud-serverless 2025-12-02" \ <3> + --areas "ES|QL" + --prs "https://github.com/elastic/elasticsearch/pull/137431" <4> +``` + +1. This option is required only if you want to override what's derived from the PR title. +2. The type values are defined in [ChangelogEntryType.cs](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/ChangelogEntryType.cs). +3. The product values are defined in [products.yml](https://github.com/elastic/docs-builder/blob/main/config/products.yml). +4. The `--prs` value can be a full URL (such as `https://github.com/owner/repo/pull/123`), a short format (such as `owner/repo#123`), just a number (in which case you must also provide `--owner` and `--repo` options), or a path to a file containing newline-delimited PR URLs or numbers. Multiple PRs can be provided comma-separated, or you can specify a file path. You can also mix both formats by specifying `--prs` multiple times. One changelog file will be created for each PR. + +#### Create a changelog with PR label mappings [example-map-label] + +You can configure label mappings in your changelog configuration file: + +```yaml +pivot: + # Keys are type names, values can be: + # - simple string: comma-separated label list (e.g., ">bug, >fix") + # - empty/null: no labels for this type + # - object: { labels: "...", subtypes: {...} } for breaking-change type only + types: + # Example mappings - customize based on your label naming conventions + breaking-change: + labels: ">breaking, >bc" + bug-fix: ">bug" + enhancement: ">enhancement" + + # Area definitions with labels + # Keys are area display names, values are label strings + # Multiple labels can be comma-separated + areas: + # Example mappings - customize based on your label naming conventions + Autoscaling: ":Distributed Coordination/Autoscaling" + "ES|QL": ":Search Relevance/ES|QL" + + # Product definitions with labels (optional) + # Keys are product spec strings; values are label strings or lists. + # A product spec string is: " [] []" + products: + 'elasticsearch': + - ":stack/elasticsearch" + 'kibana': + - ":stack/kibana" + # Include a target version if known: + # 'cloud-serverless 2025-06 ga': + # - ":cloud/serverless" +``` + +When you use the `--prs` option to derive information from a pull request, it can make use of those mappings. Similarly, when you use the `--issues` option (without `--prs`), the command derives title, type, areas, and products from the GitHub issue labels using the same mappings. + +The following example omits `--products`, so the command derives them from the PR labels: + +```sh +docs-builder changelog add \ + --prs https://github.com/elastic/elasticsearch/pull/139272 \ + --config test/changelog.yml \ + --strip-title-prefix +``` + +In this case, the changelog file derives the title, type, areas, and products from the pull request. If none of the PR's labels match `pivot.products`, the command falls back to `products.default` or repository name inference from `--repo` (refer to [Products resolution](/cli/changelog/add.md#products-resolution) for more details). +The command also looks for patterns like `Fixes #123`, `Closes owner/repo#456`, `Resolves https://github.com/.../issues/789` in the pull request to derive its issues. Similarly, when using `--issues`, the command extracts linked PRs from the issue body (for example, "Fixed by #123"). You can turn off this behavior in either case with the `--no-extract-issues` flag or by setting `extract.issues: false` in the changelog configuration file. The `extract.issues` setting applies to both directions: issues extracted from PR bodies (when using `--prs`) and PRs extracted from issue bodies (when using `--issues`). + +The `--strip-title-prefix` option in this example means that if the PR title has a prefix in square brackets (such as `[ES|QL]` or `[Security]`), it is automatically removed from the changelog title. Multiple square bracket prefixes are also supported (for example `[Discover][ESQL] Title` becomes `Title`). If a colon follows the closing bracket, it is also removed. + +By default, `--strip-title-prefix` is disabled. You can enable it globally by setting `extract.strip_title_prefix: true` in the changelog configuration file, which will apply the prefix stripping to all `changelog add` and `changelog gh-release` commands without requiring the CLI flag. The CLI flag `--strip-title-prefix` overrides the configuration setting. + +:::{note} +The `--strip-title-prefix` option only applies when the title is derived from the PR (when `--title` is not explicitly provided). If you specify `--title` explicitly, that title is used as-is without any prefix stripping. +::: + +#### Extract release notes from PR descriptions [example-extract-release-notes] + +When you use the `--prs` option, by default the `docs-builder changelog add` command automatically extracts text from the PR descriptions and use it in your changelog. + +In particular, it looks for content in these formats in the PR description: + +- `Release Notes: This is the extracted sentence.` +- `Release-Notes: This is the extracted sentence.` +- `release notes: This is the extracted sentence.` +- `Release Note: This is the extracted sentence.` +- `Release Notes - This is the extracted sentence.` +- `## Release Note` (as a markdown header) + +How the extracted text is used: + +- **Release note found**: The extracted text is used as the changelog description (only if `--description` is not explicitly provided). The changelog title comes from `--title` or the PR title, not from the release note section. +- **No release note found**: No description is filled from the PR body; the title still comes from `--title` or the PR title as usual. + +:::{note} +If you explicitly provide `--title` or `--description`, those values take precedence over extracted release notes. +You can turn off the release note extraction in the changelog configuration file or by using the `--no-extract-release-notes` option. +::: + +#### Control changelog creation [example-block-label] + +You can prevent changelog creation for certain PRs based on their labels. + +If you run the `docs-builder changelog add` command with the `--prs` option and a PR has a blocking label for any of the resolved products (from `--products`, `pivot.products` label mapping, or `products.default`), that PR will be skipped and no changelog file will be created for it. +A warning message will be emitted indicating which PR was skipped and why. + +For example, your configuration file can contain a `rules` section like this: + +```yaml +rules: + # Global match default for multi-valued fields (labels, areas). + # any (default) = match if ANY item matches the list + # all = match only if ALL items match the list + # match: any + + # Create — controls which PRs generate changelogs. + create: + # Labels that block changelog creation (comma-separated string) + exclude: ">non-issue" + # Product-specific overrides + products: + 'cloud-serverless': + exclude: ">non-issue, >test" +``` + +Those settings affect commands with the `--prs` or `--issues` options, for example: + +```sh +docs-builder changelog add --prs "1234, 5678" \ + --products "cloud-serverless" \ + --owner elastic --repo elasticsearch \ + --config test/changelog.yml +``` + +If PR 1234 has the `>non-issue` or `>test` labels, it will be skipped and no changelog will be created. +If PR 5678 does not have any blocking labels, a changelog is created. + +You can also use **include** mode instead of **exclude** mode. +For example, to only create changelogs for PRs with specific labels: + +```yaml +rules: + create: + include: "@Public, @Notable" +``` + +#### Create changelogs from a file [example-file-add] + +You can create multiple changelogs in a single command by providing a newline-delimited file that contains pull requests or issues. +For example: + +```sh +# Create a file with PRs (one per line) +cat > prs.txt << EOF +https://github.com/elastic/elasticsearch/pull/1234 +https://github.com/elastic/elasticsearch/pull/5678 +EOF + +# Use the file with --prs +docs-builder changelog add --prs prs.txt \ + --products "elasticsearch 9.2.0 ga" \ + --config test/changelog.yml +``` + +In this example, the command creates one changelog for each pull request in the list. + +#### Create changelogs from GitHub release notes [changelog-add-release-version] + +If you have GitHub releases with automated release notes (the default format or [Release Drafter](https://github.com/release-drafter/release-drafter) format), the changelog commands can derive the PR list from those release notes with the `--release-version` option. +For example: + +```sh +docs-builder changelog add \ + --release-version v1.34.0 \ + --repo apm-agent-dotnet --owner elastic +``` + +This command creates one changelog file per PR found in the `v1.34.0` GitHub release notes. +The product, target version, and lifecycle in each changelog are inferred automatically from the release tag and the repository name. +For example, a tag of `v1.34.0` in the `apm-agent-dotnet` repo creates changelogs with `product: apm-agent-dotnet`, `target: 1.34.0`, and `lifecycle: ga`. + +:::{note} +`--release-version` requires `--repo` (or `bundle.repo` set in `changelog.yml`) and is mutually exclusive with `--prs` and `--issues`. +The option precedence is: CLI option > `changelog.yml` bundle section > built-in default. This applies to `--repo`, `--owner`, and `--output` for all `changelog add` modes. +::: + +You can use the `docs-builder changelog gh-release` command as a one-shot alternative to `changelog add` and `changelog bundle` commands. +The command parses the release notes, creates one changelog file per pull request found, and creates a `changelog-bundle.yaml` file — all in a single step. Refer to [](/cli/changelog/gh-release.md) + +:::{note} +This command requires a `GITHUB_TOKEN` or `GH_TOKEN` environment variable (or an active `gh` login) to fetch release details from the GitHub API. Refer to [Authorization](#authorization) for details. +::: diff --git a/docs/contribute/publish-changelogs.md b/docs/contribute/publish-changelogs.md new file mode 100644 index 000000000..6aa62ab0c --- /dev/null +++ b/docs/contribute/publish-changelogs.md @@ -0,0 +1,135 @@ +# Publish changelogs + +The structure of the changelogs and bundle files is designed to be as stable and consistent as possible so that all teams can incorporate it into their workflow. + +The process for deriving docs from the bundle files is designed to be a separate workflow, so that content contributors do not need to worry about layout changes over time. + +:::{note} +In the short term, the goal is to create docs that can be included in [existing release note pages](https://www.elastic.co/docs/release-notes). +In the longer term, the goal is to move to more filterable, dynamic pages. +::: + +## Include changelogs inline [changelog-directive] + +You can use the [`{changelog}` directive](/syntax/changelog.md) to render all changelog bundles directly in your documentation pages. + +```markdown +:::{changelog} +::: +``` + +By default, the directive renders all bundles from `changelog/bundles/` (relative to the docset root), ordered by semantic version (newest first). +For full documentation and examples, refer to the [{changelog} directive syntax reference](/syntax/changelog.md). + +:::{note} +All product-specific filtering must be configured at bundle time via `rules.bundle`. Unlike the `changelog render` command, the directive does not apply `rules.publish`. +::: + +## Generate markdown or asciidoc [render-changelogs] + +The `docs-builder changelog render` command creates markdown or asciidoc files from changelog bundles for documentation purposes. +For up-to-date details, use the `-h` command option or refer to [](/cli/changelog/render.md). + +Before you can use this command you must create changelog files and collect them into bundles. +For example, the `docs-builder changelog bundle` command creates a file like this: + +```yaml +products: +- product: elasticsearch + target: 9.2.2 +entries: +- file: + name: 1765581721-convert-bytestransportresponse-when-proxying-respo.yaml + checksum: d7e74edff1bdd3e23ba4f2f88b92cf61cc7d490a +- file: + name: 1765581721-fix-ml-calendar-event-update-scalability-issues.yaml + checksum: dfafce50c9fd61c3d8db286398f9553e67737f07 +- file: + name: 1765581651-break-on-fielddata-when-building-global-ordinals.yaml + checksum: 704b25348d6daff396259216201053334b5b3c1d +``` + +To create markdown files from this bundle, run the `docs-builder changelog render` command: + +```sh +docs-builder changelog render \ + --input "/path/to/changelog-bundle.yaml|/path/to/changelogs|elasticsearch|keep-links,/path/to/other-bundle.yaml|/path/to/other-changelogs|kibana|hide-links" \ <1> + --title 9.2.2 \ <2> + --output /path/to/release-notes \ <3> + --subsections <4> +``` + +1. Provide information about the changelog bundle(s). The format for each bundle is `"|||"` using pipe (`|`) as delimiter. To merge multiple bundles, separate them with commas (`,`). Only the `` is required for each bundle. The `` is useful if the changelogs are not in the default directory and are not resolved within the bundle. The `` is necessary if your changelogs do not contain full URLs for the pull requests or issues. The `` can be `hide-links` or `keep-links` (default) to control whether PR/issue links are hidden for changelogs from private repositories. +2. The `--title` value is used for an output folder name and for section titles in the output files. If you omit `--title` and the first bundle contains a product `target` value, that value is used. Otherwise, if none of the bundles have product `target` fields, the title defaults to "unknown". +3. By default the command creates the output files in the current directory. +4. By default the changelog areas are not displayed in the output. Add `--subsections` to group changelog details by their `areas`. For breaking changes that have a `subtype` value, the subsections will be grouped by subtype instead of area. + +:::{important} +Paths in the `--input` option must be absolute paths or use environment variables. Tilde (`~`) expansion is not supported. +::: + +For example, the `index.md` output file contains information derived from the changelogs: + +```md +## 9.2.2 [elastic-release-notes-9.2.2] + +### Fixes [elastic-9.2.2-fixes] + +**Network** +* Convert BytesTransportResponse when proxying response from/to local node. [#135873](https://github.com/elastic/elastic/pull/135873) + +**Machine Learning** +* Fix ML calendar event update scalability issues. [#136886](https://github.com/elastic/elastic/pull/136886) [#136900](https://github.com/elastic/elastic/pull/136900) + +**Aggregations** +* Break on FieldData when building global ordinals. [#108875](https://github.com/elastic/elastic/pull/108875) +``` + +When a changelog includes multiple values in its `prs` or `issues` arrays, all its links are rendered inline, as shown in the Machine Learning example above. + +To comment out the pull request and issue links, for example if they relate to a private repository, add `hide-links` to the `--input` option for that bundle. +This allows you to selectively hide links per bundle when merging changelogs from multiple repositories. +When `hide-links` is set, all PR and issue links for affected changelogs are hidden together. + +If you have changelogs with `feature-id` values and you want them to be omitted from the output, use the `--hide-features` option. Feature IDs specified via `--hide-features` are **merged** with any `hide-features` already present in the bundle files. This means both CLI-specified and bundle-embedded features are hidden in the output. + +To create an asciidoc file instead of markdown files, add the `--file-type asciidoc` option: + +```sh +docs-builder changelog render \ + --input "./changelog-bundle.yaml,./changelogs,elasticsearch" \ + --title 9.2.2 \ + --output ./release-notes \ + --file-type asciidoc \ <1> + --subsections +``` + +1. Generate a single asciidoc file instead of multiple markdown files. + +## Release highlights + +The `highlight` field allows you to mark changelogs that should appear in a dedicated highlights page. +Highlights are most commonly used for major or minor version releases to draw attention to the most important changes. + +When you set `highlight: true` in a changelog: + +- It appears in both the highlights page (`highlights.md`) and its normal type section (for example "Features and enhancements") +- The highlights page is only created when at least one changelog has `highlight: true` (unlike other special pages like `known-issues.md` which are always created) +- Highlights can be any type of changelog (features, enhancements, bug fixes, etc.) + +Example changelog with highlight: + +```yaml +type: feature +products: +- product: elasticsearch + target: 9.3.0 + lifecycle: ga +title: New Cloud Connect UI for self-managed installations +description: Adds Cloud Connect functionality to Kibana, which allows you to use cloud solutions like AutoOps and Elastic Inference Service in your self-managed Elasticsearch clusters. +highlight: true +``` + +When rendering, changelogs with `highlight: true` are collected from all types and rendered in a dedicated highlights section. +In markdown output, this creates a separate `highlights.md` file. +In asciidoc output, highlights appear as a dedicated section in the single asciidoc file. diff --git a/docs/syntax/changelog.md b/docs/syntax/changelog.md index dfada1db0..a5dcb7d9a 100644 --- a/docs/syntax/changelog.md +++ b/docs/syntax/changelog.md @@ -162,7 +162,7 @@ entries: When the directive loads multiple bundles, `hide-features` from **all bundles are aggregated** and applied to all entries. This means if bundle A hides `feature:x` and bundle B hides `feature:y`, both features are hidden in the combined output. To add `hide-features` to a bundle, use the `--hide-features` option when running `changelog bundle`. -For more details, go to [Hide features in bundles](../contribute/changelog.md#changelog-bundle-hide-features). +For more details, go to [Hide features in bundles](../contribute/bundle-changelogs.md#changelog-bundle-hide-features). ## Hiding private links [hide-links] @@ -285,7 +285,7 @@ To fix this, either: :::{tip} In general, if you want to be able to remove changelog files after your releases, create your bundles with the `--resolve` option or set `bundle.resolve` to `true` in the changelog configuration file. -For more command syntax details, go to [Remove changelog files](../contribute/changelog.md#changelog-remove). +For more command syntax details, go to [Remove changelog files](../contribute/bundle-changelogs.md#changelog-remove). ::: ## Example @@ -314,7 +314,7 @@ The `{changelog}` directive is ideal for release notes pages that should always ## Related -- [Create and bundle changelogs](/contribute/changelog.md) — Learn how to create changelog entries and bundles +- [Create and bundle changelogs](/contribute/changelog.md) — Overview, workflow, and links to detailed guides - [`changelog add`](/cli/changelog/add.md) — CLI command to create changelog entries - [`changelog bundle`](/cli/changelog/bundle.md) — CLI command to bundle changelog entries - [`changelog remove`](/cli/changelog/remove.md) — CLI command to remove changelog files diff --git a/src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs b/src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs index 2b4d130a3..3b0d5baf6 100644 --- a/src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs +++ b/src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs @@ -985,7 +985,7 @@ private static IReadOnlyList ApplyPerProductContextBundleF collector.EmitHint(string.Empty, $"Note: Per-product rule '{ruleContextProduct}' uses 'match_products: any' with 'include_products' which acts as " + $"{(wouldIncludeAll ? "include-all" : "exclude-all")} for this context. " + - $"See: https://elastic.github.io/docs-builder/contribute/changelog/#ineffective-configuration-patterns"); + $"Refer to https://github.com/elastic/docs-builder/blob/main/docs/contribute/configure-changelogs.md"); ruleStats["ineffective_pattern_warned"] = 1; } diff --git a/src/services/Elastic.Changelog/Configuration/ChangelogConfigurationLoader.cs b/src/services/Elastic.Changelog/Configuration/ChangelogConfigurationLoader.cs index f07b82a80..0f5b8a7ed 100644 --- a/src/services/Elastic.Changelog/Configuration/ChangelogConfigurationLoader.cs +++ b/src/services/Elastic.Changelog/Configuration/ChangelogConfigurationLoader.cs @@ -802,7 +802,7 @@ private static PivotConfiguration ConvertPivot(PivotConfigurationYaml yamlPivot) collector.EmitWarning(configPath, $"Configuration pattern 'match_products: any' with 'include_products' in per-product rule '{normalizedProductId}' provides no selective filtering. " + "Consider 'match_products: all' for strict filtering or 'exclude_products' for exclusion-based filtering. " + - "See: https://elastic.github.io/docs-builder/contribute/changelog/#ineffective-configuration-patterns"); + "Refer to https://github.com/elastic/docs-builder/blob/main/docs/contribute/configure-changelogs.md"); } // Detect disjoint products in per-product include_products @@ -817,7 +817,7 @@ private static PivotConfiguration ConvertPivot(PivotConfigurationYaml yamlPivot) $"Per-product rule '{normalizedProductId}' includes disjoint products [{string.Join(", ", disjointProducts)}] " + "which cannot be included due to single-product rule resolution. " + "Use separate bundles (each with a single product in output_products or profile output_products), or multi-product changelogs instead. " + - "See: https://elastic.github.io/docs-builder/contribute/changelog/#ineffective-configuration-patterns"); + "Refer to https://github.com/elastic/docs-builder/blob/main/docs/contribute/configure-changelogs.md"); } } @@ -868,7 +868,7 @@ private static PivotConfiguration ConvertPivot(PivotConfigurationYaml yamlPivot) { collector.EmitHint(configPath, "rules.bundle: When 'products' is present, global include_products, exclude_products, and type/area rules are not applied for filtering; configure filters under each product key or use global-only rules.bundle (no 'products' section). " + - "See: https://elastic.github.io/docs-builder/contribute/changelog/#bundle-rule-modes"); + "See: https://github.com/elastic/docs-builder/blob/main/docs/contribute/configure-changelogs.md#bundle-rule-modes"); } }