changelog bundle
Bundle changelog files.
To create the changelogs, use changelog add. For details and examples, go to Create and bundle changelogs.
docs-builder changelog bundle [arguments...] [options...] [-h|--help]
changelog bundle supports two mutually exclusive invocation modes:
- Profile-based: All paths and filters come from the changelog configuration file. No other options are allowed. For example,
bundle <profile> <version> <report>. - Option-based: You supply all filter and output options directly. For example,
bundle --all(or--input-products,--prs,--issues).
You cannot mix the two modes. Passing any option-based flag together with a profile returns an error.
Profile-based commands discover the changelog configuration automatically (no --config flag): they look for changelog.yml in the current directory, then docs/changelog.yml.
If neither file is found, the command returns an error with instructions to run docs-builder changelog init or to re-run from the folder where the file exists.
Option-based commands ignore the bundle.profiles section of the changelog configuration file.
These arguments apply to profile-based bundling:
[0] <string?>- Profile name from
bundle.profilesin the changelog configuration file. - For example, "elasticsearch-release".
- When specified, the second argument is the version, promotion report URL, or URL list file.
[1] <string?>- Version number, promotion report URL/path, or URL list file.
- For example,
9.2.0,https://buildkite.../promotion-report.html, or/path/to/prs.txt. [2] <string?>- Optional: Promotion report URL/path or URL list file when the second argument is a version string.
- When provided,
[1]must be a version string and[2]is the PR/issue filter source. - For example,
docs-builder changelog bundle serverless-release 2026-02 ./promotion-report.html.
The third argument ([2]) is required when your profile uses {version} placeholders in output or output_products patterns and you also want to filter by a promotion report or URL list. Without it, the version defaults to "unknown".
The second argument ([1]) and optional third argument ([2]) accept the following:
- Version string — Used for
{version}substitution in profile patterns. For example,9.2.0or2026-02. - Promotion report URL — A URL to an HTML promotion report. PR URLs are extracted from it.
- Promotion report file — A path to a downloaded
.htmlfile containing a promotion report. - URL list file — A path to a plain-text file containing one fully-qualified GitHub PR or issue URL per line. For example,
https://github.com/elastic/elasticsearch/pull/123. The file must contain only PR URLs or only issue URLs, not a mix. Bare numbers and short forms such asowner/repo#123are not allowed.
The following options are only valid in option-based mode (no profile argument).
Using any of them with a profile returns an error.
You must choose one method for determining what's in the bundle (--all, --input-products, --prs, --issues, --release-version, or --report).
--all- Include all changelogs from the directory.
--config <string?>- Optional: Path to the changelog.yml configuration file.
- Defaults to
docs/changelog.yml. --directory <string?>- Optional: The directory that contains the changelog YAML files.
- When not specified, falls back to
bundle.directoryfrom the changelog configuration, then the current working directory. See Output files for the full resolution order. --hide-features <string[]?>- Optional: A list of feature IDs (comma-separated), or a path to a newline-delimited file containing feature IDs.
- Can be specified multiple times.
- Adds a
hide-featureslist to the bundle. - When the bundle is rendered (by the
changelog rendercommand or{changelog}directive), changelogs with matchingfeature-idvalues will be commented out of the documentation. --input-products <List<ProductInfo>?>- Filter by products in the format "product target lifecycle, ...".
- For more information about the valid product and lifecycle values, go to 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"cloud-serverless 2025-12-02 *"- match cloud-serverless 2025-12-02 with any lifecycle"elasticsearch * *"- match all elasticsearch changelogs"* 9.3.* *"- match any product with target starting with "9.3.""* * *"- match all changelogs (equivalent to--all)
--issues <string[]?>- Filter by issue URLs (comma-separated), or a path to a newline-delimited file. Can be specified multiple times.
- Each occurrence can be either comma-separated issues (
--issues "https://github.com/owner/repo/issues/123,456") or a file path (for example--issues /path/to/file.txt). - When using a file, every line must be a fully-qualified GitHub issue URL such as
https://github.com/owner/repo/issues/123. Bare numbers and short forms are not allowed in files. --no-resolve- Optional: Explicitly turn off the
resolveoption if it's specified in the changelog configuration file. --output <string?>- Optional: The output path for the bundle.
- Can be either (1) a directory path, in which case
changelog-bundle.yamlis created in that directory, or (2) a file path ending in.ymlor.yaml. - When not specified, falls back to
bundle.output_directoryfrom the changelog configuration, then the input directory (which is itself resolved from--directory,bundle.directory, or the current working directory). See Output files for the full resolution order. --output-products <List<ProductInfo>?>- Optional: Explicitly set the products array in the output file in format "product target lifecycle, ...".
- This value replaces information that would otherwise by derived from changelogs.
--owner <string?>- Optional: The GitHub repository owner, required when pull requests or issues are specified as numbers.
- Precedence:
--ownerflag >bundle.ownerinchangelog.yml>elastic. --prs <string[]?>- Filter by pull request URLs (comma-separated) or a path to a newline-delimited file. Can be specified multiple times.
- Each occurrence can be either comma-separated PRs (for example
--prs "https://github.com/owner/repo/pull/123,6789") or a file path (for example--prs /path/to/file.txt). - When using a file, every line must be a fully-qualified GitHub PR URL such as
https://github.com/owner/repo/pull/123. Bare numbers and short forms are not allowed in files. --release-version <string?>- GitHub release tag to use as a source of pull requests (for example,
"v9.2.0"or"latest"). - When specified, the command fetches the release from GitHub, parses PR references from the release notes, and uses them as the bundle filter. Only automated GitHub release notes (the default format or Release Drafter format) are supported at this time.
- Requires repo (
--repoorbundle.repoinchangelog.yml) and owner (--ownerflag >bundle.ownerinchangelog.yml>elastic) details. - When
--output-productsis not specified, the products array in the bundle is derived from the matched changelog files' ownproductsfields, consistent with all other filter options. --repo <string?>- Optional: The GitHub repository name.
- Falls back to
bundle.repoinchangelog.ymlwhen not specified; if that is also absent, the product ID is used. --report <string?>- Filter by pull requests extracted from a promotion report. Accepts a URL or a local file path.
- The report can be an HTML page from Buildkite or any file containing GitHub PR URLs.
--resolve- Optional: Copy the contents of each changelog file into the entries array.
- By default, the bundle contains only the file names and checksums.
Both modes use the same ordered fallback to determine where to write the bundle. The first value that is set wins:
Output directory (where the bundle file is placed):
| Priority | Profile-based | Option-based |
|---|---|---|
| 1 | — | --output (explicit file or directory path) |
| 2 | bundle.output_directory in changelog.yml |
bundle.output_directory in changelog.yml |
| 3 | bundle.directory in changelog.yml |
--directory CLI option |
| 4 | Current working directory | bundle.directory in changelog.yml |
| 5 | — | Current working directory |
Input directory (where changelog YAML files are read from) follows the same fallback for both modes, minus the explicit CLI override that is forbidden in profile mode:
| Priority | Profile-based | Option-based |
|---|---|---|
| 1 | bundle.directory in changelog.yml |
--directory CLI option |
| 2 | Current working directory | bundle.directory in changelog.yml |
| 3 | — | Current working directory |
Bundle filename is determined by the bundle.profiles.<name>.output setting (profile-based) or defaults to changelog-bundle.yaml (both modes).
The profile output setting can include additional path segments. For example: "stack/kibana-{version}.yaml".
In option-based mode, when you specify --output, it supports two formats:
Directory path: If you specify a directory path (without a filename), the command creates
changelog-bundle.yamlin that directory:docs-builder changelog bundle --all --output /path/to/output/dir # Creates /path/to/output/dir/changelog-bundle.yamlFile path: If you specify a file path ending in
.ymlor.yaml, the command uses that exact path:docs-builder changelog bundle --all --output /path/to/custom-bundle.yaml # Creates /path/to/custom-bundle.yaml
If you specify a file path with a different extension (not .yml or .yaml), the command returns an error.
"Current working directory" means the directory you are in when you run the command (pwd).
Setting bundle.directory and bundle.output_directory in changelog.yml is recommended so you don't need to rely on running the command from a specific directory.
The repository name is stored in each bundle product entry to ensure that PR and issue links are generated correctly when the bundle is rendered. It can be set in three ways, in order of precedence:
--repooption (option-based mode only)repofield in the profile (profile-based mode only; overrides the bundle-level default)bundle.repoinchangelog.yml(applies to both modes as a default when neither of the above is set)
Setting bundle.repo and bundle.owner in your configuration means you rarely need to pass --repo and --owner on the command line:
bundle:
repo: elasticsearch
owner: elastic
You can still override them per profile if a project has multiple products with different repos.
The bundle output includes a repo field in each product:
products:
- product: cloud-serverless
target: 2025-12-02
repo: elasticsearch
owner: elastic
entries:
- file:
name: 1765495972-new-feature.yaml
checksum: 6c3243f56279b1797b5dfff6c02ebf90b9658464
When rendering, pull request and issue links use https://github.com/elastic/elasticsearch/... instead of the product ID.
If no repo is set at any level, the product ID is used as a fallback for link generation.
This may result in broken links if the product ID doesn't match the GitHub repository name (for example, cloud-serverless product ID in the elasticsearch repo).
You can use --report to filter by a promotion report:
# Extract PRs from a downloaded report and use them as the filter
docs-builder changelog bundle \
--report ./promotion-report.html \
--directory ./docs/changelog \
--output ./docs/releases/bundle.yaml
You can use --release-version to fetch pull request references directly from GitHub release notes and use them as the bundle filter.
This is equivalent to building a PR list file manually and passing it with --prs, but without any file management.
Only automated GitHub release notes (the default format or Release Drafter format) are supported at this time.
docs-builder changelog bundle \
--release-version v1.34.0 \
--repo apm-agent-dotnet \
--owner elastic
- You must specify
--repoor setbundle.repoin the changelog configuration file. - If you don't specify
--owner, it usesbundle.ownerin the changelog configuration or else defaults toelastic.
Without --output-products, the products array in the bundle is derived from the matched changelog files' own products fields — the same behavior as --prs, --issues, --report, and --all.
Use --output-products when you need a single, authoritative product entry that reflects the release identity rather than the diverse metadata across individual changelog files.
For example:
docs-builder changelog bundle \
--release-version v1.34.0 \
--output-products "apm-agent-dotnet 1.34.0 ga"
--release-version requires a GITHUB_TOKEN or GH_TOKEN environment variable (or an active gh login) to fetch release details from the GitHub API.
When the changelog configuration file defines bundle.profiles, you can use those profiles with the changelog bundle command.
If you're using profile-based commands, they're affected by the following fields in the bundle.profiles section of the changelog configuration file:
source- Optional. When set to
github_release, the PR list is fetched automatically from the GitHub release identified by the version argument. Requiresrepoto be set at the profile orbundlelevel. Mutually exclusive withproducts. - Example:
source: github_release products- Required when filtering by product metadata (equivalent to the
--input-productscommand option). - Not used when the filter comes from a promotion report, URL list file, or
source: github_release— in those cases the PR or issue list determines what's included andproductsis ignored. - Supports
{version}and{lifecycle}placeholders that are substituted at runtime. - Example:
"elasticsearch {version} {lifecycle}" output- Optional. The output filename pattern for the bundle file. Supports
{version}and{lifecycle}placeholders. - When not set, the output path falls back in order to:
bundle.output_directory/changelog-bundle.yaml(ifbundle.output_directoryis configured), thenchangelog-bundle.yamlin the input directory. - Setting this is recommended so each profile produces a distinctly named file rather than overwriting the default.
- Example:
"elasticsearch-{version}.yaml" output_products- Optional. Overrides the products array written to the bundle output. Supports
{version}and{lifecycle}placeholders. - When not set, the products array is derived from the individual changelog files matched by the filter. This often produces multiple product entries (one per unique product/target/lifecycle combination across all matched files), which may not reflect a single clean release identity.
- When set, the products array in the bundle is exactly the value you specify, replacing anything that would be derived from the matched changelogs. Use this to publish a single, authoritative product entry with a specific version and lifecycle.
- The
{lifecycle}placeholder is substituted at runtime with the inferred lifecycle. Forsource: github_releaseprofiles this comes from the release tag suffix. For standard profiles it comes from the version argument. Refer to changelog bundle > Lifecycle inference for standard profiles and changelog bundle > Bundle by GitHub release profiles for details. - If you omit lifecycle from the pattern (for example,
"elasticsearch {version}"), the lifecycle field is omitted from the products array entirely. - Example:
"elasticsearch {version} {lifecycle}"or"elasticsearch {version} ga"to hardcode GA regardless of tag. repo- Optional. The GitHub repository name written to each product entry in the bundle. Used by the
{changelog}directive to generate correct PR/issue links. Only needed when the product ID doesn't match the GitHub repository name. Overridesbundle.repowhen set. Required whensource: github_releaseis used and nobundle.repodefault is set. - Example:
repo: elasticsearch. owner- Optional. The GitHub owner written to each product entry in the bundle. Overrides
bundle.ownerwhen set. - Example:
owner: elastic hide_features- Optional. Feature IDs to mark as hidden in the bundle output (string or list). When the bundle is rendered, entries with matching
feature-idvalues are commented out.
If your configuration file defines a standard profile (that is to say, not a GitHub release profile), the lifecycle is inferred from the version string you pass as the second argument:
| Version argument | Inferred lifecycle |
|---|---|
9.2.0 |
ga |
9.2.0-rc.1 |
ga |
9.2.0-beta.1 |
beta |
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.
You can invoke those profiles with commands like this:
# Bundle changelogs for a GA release ({lifecycle} → "ga" inferred from "9.2.0")
docs-builder changelog bundle elasticsearch-release 9.2.0
# Bundle changelogs for a beta release ({lifecycle} → "beta" inferred from "9.2.0-beta.1")
docs-builder changelog bundle elasticsearch-release 9.2.0-beta.1
# Bundle changelogs with partial dates
docs-builder changelog bundle serverless-monthly 2026-02
# Bundle changelogs that match a list of PRs in a downloaded promotion report
# (version used for {version} substitution; report used as PR filter)
docs-builder changelog bundle serverless-report 2026-02-13 ./promotion-report.html
# Same using a URL list file instead of an HTML promotion report
docs-builder changelog bundle serverless-report 2026-02-13 ./prs.txt
# Bundle changelogs using the PR list from a GitHub release (source: github_release)
docs-builder changelog bundle elasticsearch-gh-release 9.2.0
# Use "latest" to fetch the most recent release
docs-builder changelog bundle elasticsearch-gh-release latest
You can create profiles that are equivalent to the --input-products filter option, that is to say the bundle will contain only changelogs with matching products.
For example:
bundle:
repo: elasticsearch
owner: elastic
profiles:
# Find changelogs with any lifecycle and a partial date
serverless-monthly:
products: "cloud-serverless {version}-* *"
output: "serverless-{version}.yaml"
output_products: "cloud-serverless {version}"
# Find changelogs with a specific lifecycle
elasticsearch-ga-only:
products: "elasticsearch {version} ga"
output: "elasticsearch-{version}.yaml"
# Infer the lifecycle from the version
elasticsearch-release:
hide_features:
- feature-flag-1
- feature-flag-2
products: "elasticsearch {version} {lifecycle}"
output: "elasticsearch-{version}.yaml"
output_products: "elasticsearch {version}"
- Bundle-level defaults that apply to all profiles. Individual profiles can override these.
- Bundles any changelogs that have
product: cloud-serverless, any lifecycle, and the date partially specified in the command. This is equivalent to the--input-productscommand option's support for wildcards. - Bundles any changelogs that have
product: elasticsearch,lifecycle: ga, and the version specified in the command. - Adds a
hide-featuresarray in the bundle. This is equivalent to the--hide-featurescommand option. - In this case, the lifecycle is inferred from the version string passed as the second command argument (for example,
9.2.0-beta.1→beta).
output_products: "elasticsearch {version} {lifecycle}" produces a single, authoritative product entry in the bundle derived from the release tag — for example, tag v9.2.0 gives elasticsearch 9.2.0 ga and tag v9.2.0-beta.1 gives elasticsearch 9.2.0 beta. Without output_products, the bundle products array is instead derived from the matched changelog files' own products fields, which is the consistent fallback for all profile types. Set output_products when you need a single clean product entry that reflects the release identity rather than the diverse metadata across individual changelog files.
You can also create profiles that are equivalent to the --prs, --issues, and --report filter options.
That is to say you can create bundles that contain only changelogs with matching prs or issues.
For example:
bundle:
repo: elasticsearch
owner: elastic
profiles:
# Find changelogs that match a list of PRs
serverless-report:
output: "serverless-{version}.yaml"
output_products: "cloud-serverless {version}"
- Bundle-level defaults that apply to all profiles. Individual profiles can override these.
- If a profile is intended for use with a promotion report or a newline delimited file that lists the issues or pull requests, it does not need a
productsfilter. If theoutputandoutput_productsare omitted, the default path and file names are used. This example shows how you can use a{version}variable to customize the bundle's filename and product metadata.
To make bundling by GitHub release more easily repeatable, create a profile with source: github_release in your changelog configuration file.
For example:
bundle:
profiles:
# Fetch the PR list directly from a GitHub release
agent-gh-release:
source: github_release
repo: apm-agent-dotnet
output: "agent-{version}.yaml"
output_products: "apm-agent-dotnet {version} {lifecycle}"
- Instead of filtering pre-existing changelog files by product, this profile fetches the PR list from the GitHub release notes for the given version. Mutually exclusive with
products. - The repository to fetch the release from. Overrides
bundle.repofor this profile.
For source: github_release profiles, the {lifecycle} placeholder in output and output_products is inferred from the release tag returned by GitHub (not the argument you pass to the command).
This means the pre-release suffix on the tag drives the lifecycle value:
| Release tag | {version} |
{lifecycle} |
|---|---|---|
v9.2.0 |
9.2.0 |
ga |
v9.2.0-beta.1 |
9.2.0 |
beta |
v9.2.0-preview.1 |
9.2.0 |
preview |
v1.34.1 |
1.34.1 |
ga |
v1.34.1-preview.1 |
1.34.1 |
preview |
This differs from standard profiles, where lifecycle is inferred from the version argument you type. For source: github_release, the {version} placeholder always uses the clean base version (stripped of any pre-release suffix), while {lifecycle} reflects the actual tag format.
If the lifecycle you want to advertise cannot be inferred from the tag format — for example, because your team uses clean tags like v1.34.1 even for pre-releases — hardcode the lifecycle directly in output_products instead of using the {lifecycle} placeholder:
# Instead of relying on {lifecycle} inference, hardcode the lifecycle
gh-release:
source: github_release
repo: apm-agent-dotnet
output: "apm-agent-dotnet-{version}.yaml"
output_products: "apm-agent-dotnet {version} preview"