changelog bundle cli command
docs-builder changelog bundle \
[<profile>] \
[<profile-arg>] \
[<profile-report>] \
[options]
Aggregates changelog YAML files matching a filter into a single bundle file. The bundle is the artifact used by the {changelog} directive and docs-builder changelog render to produce release notes.
The command has two mutually exclusive modes. You cannot mix them: supplying a profile name on the command line disables all filter and output flags (refer to Options for equivalent changelog configuration settings).
<profile>string- Profile name from bundle.profiles in config (for example, "elasticsearch-release"). Used as the first positional argument in profile-based commands. The equivalent configuration entry is bundle.profiles.<name>.
<profile-arg>string- Version number or promotion report URL/path when using a profile (for example, "9.2.0" or "https://buildkite.../promotion-report.html"). Required second positional argument in profile-based commands.
<profile-report>string- Promotion report, URL list file, or changelog path list file when also providing a version. When provided, the second argument must be a version string and this is the filter source (for example, "bundle serverless-release 2026-02 ./report.html"). Optional third positional argument in profile-based commands.
--[no-]all-
Include all changelogs in the directory. This option is not supported in profile-based commands. The equivalent configuration option is bundle.profiles.<name>.products: "* * *".
Default:
false --configstring-
Path to the changelog.yml configuration file. Defaults to 'docs/changelog.yml' in option-based mode. This option is not supported in profile-based commands; configuration is auto-discovered.
Constraints: symbolic links not allowed, must exist, extensions: yml, yaml
--directorystring-
Directory containing changelog YAML files. Uses config bundle.directory or defaults to current directory. This option is not supported in profile-based commands. The equivalent configuration option is bundle.directory.
Constraints: symbolic links not allowed
--descriptionstring- Bundle description text with placeholder support ({version}, {lifecycle}, {owner}, {repo}). Overrides bundle.description from config. In option-based mode, placeholders require --output-products. This option is not supported in profile-based commands. The equivalent configuration options are bundle.description or bundle.profiles.<name>.description.
--hide-featuresstring[]-
Feature IDs (comma-separated) or a path to a newline-delimited file. Entries with matching feature-id values are hidden when the bundle is rendered. This option is not supported in profile-based commands. The equivalent configuration option is bundle.profiles.<name>.hide_features.
Repeatable: pass
--hide-featuresmultiple times to supply more than one value --[no-]no-release-date-
Skip auto-population of release date in the bundle. Mutually exclusive with --release-date. This option is not supported in profile-based commands. The equivalent configuration options are bundle.release_dates: false or bundle.profiles.<name>.release_dates: false.
Default:
false --release-datestring- Explicit release date for the bundle in YYYY-MM-DD format. Overrides auto-population behaviour. Mutually exclusive with --no-release-date. This option is not supported in profile-based commands; use option-based mode, or set bundle.release_dates in configuration to control auto-population.
--input-productsstring- Filter by products in format "product target lifecycle, ..." (for example, "cloud-serverless 2025-12-02 ga, cloud-serverless 2025-12-06 beta"). All three parts are required but can be wildcards (*). This option is not supported in profile-based commands. The equivalent configuration option is bundle.profiles.<name>.products.
--outputstring- Output path for the bundled changelog (directory or .yml/.yaml file). Uses config bundle.output_directory or defaults to 'changelog-bundle.yaml' in the input directory. This option is not supported in profile-based commands. The equivalent configuration option is bundle.profiles.<name>.output.
--output-productsstring- Explicitly set the products array in the output file in format "product target lifecycle, ...". This option is not supported in profile-based commands. The equivalent configuration option is bundle.profiles.<name>.output_products.
--issuesstring[]-
Filter by issue URLs (comma-separated), or a path to a newline-delimited file containing fully-qualified GitHub issue URLs. Can be specified multiple times. This option is not supported in profile-based commands. Pass a promotion report as the second or third positional argument instead, or set source: github_release on the profile.
Repeatable: pass
--issuesmultiple times to supply more than one value --filesstring[]-
Filter by changelog YAML paths (comma-separated), or a path to a newline-delimited file containing changelog paths. Can be specified multiple times. Forces local entry sourcing. This option is not supported in profile-based commands; pass a path list file as the second or third positional argument instead.
Repeatable: pass
--filesmultiple times to supply more than one value --[no-]force-local-
Force local entry sourcing for this run (equivalent to bundle.use_local_changelogs: true without editing config). Allowed in profile-based commands.
Default:
false --ownerstring- GitHub repository owner for PR/issue numbers or --release-version. Falls back to bundle.owner or "elastic". This option is not supported in profile-based commands. The equivalent configuration options are bundle.owner or bundle.profiles.<name>.owner.
--branchstring- Branch whose CDN changelog entry pool (changelog/{org}/{repo}/{branch}/...) is sourced from. Falls back to bundle.branch or "main". This option is not supported in profile-based commands. The equivalent configuration options are bundle.branch or bundle.profiles.<name>.branch.
--[no-]plan-
Emit GitHub Actions step outputs (needs_network, needs_github_token, output_path, and cdn_url when a product is resolvable) describing network requirements, the resolved output path, and the public CDN URL of the scrubbed bundle, then exit without generating the bundle. Intended for CI actions. Supported in profile-based commands.
Default:
false --prsstring[]-
Filter by pull request URLs (comma-separated), or a path to a newline-delimited file containing fully-qualified GitHub PR URLs. Can be specified multiple times. This option is not supported in profile-based commands. Pass a promotion report as the second or third positional argument instead, or set source: github_release on the profile.
Repeatable: pass
--prsmultiple times to supply more than one value --release-versionstring- GitHub release tag to use as a filter source (for example, "v9.2.0" or "latest"). Fetches PR references from release notes. This option is not supported in profile-based commands. The equivalent configuration option is bundle.profiles.<name>.source: github_release.
--repostring- GitHub repository name for PR/issue numbers or --release-version. Falls back to bundle.repo or the product ID. This option is not supported in profile-based commands. The equivalent configuration options are bundle.repo or bundle.profiles.<name>.repo.
--reportstring- URL or file path to a promotion report; extracts PR URLs as the filter. This option is not supported in profile-based commands. Pass the report as the second or third positional argument instead.
-l--log-levelenum-
Minimum log level.
Values: trace, debug, information, warning, error, critical, none
Default:
information -c--config-sourceenum-
Override the configuration source: local, remote
Values: local, remote, embedded
--[no-]skip-private-repositories- Skip cloning private repositories
-l--log-levelenum-
Minimum log level.
Values: trace, debug, information, warning, error, critical, none
Default:
information -c--config-sourceenum-
Override the configuration source: local, remote
Values: local, remote, embedded
--[no-]skip-private-repositories- Skip cloning private repositories
Define reusable profiles in changelog.yml and invoke by name. This is the recommended approach for release workflows because the filter, output path, and product metadata are all captured in configuration and don't need to be specified on the command line.
# Bundle using a named profile (version inferred for {lifecycle} placeholder)
docs-builder changelog bundle elasticsearch-release 9.2.0
# Bundle using a profile with a promotion report as the filter source
docs-builder changelog bundle elasticsearch-release 9.2.0 ./promotion-report.html
The second positional argument accepts:
- A version string (e.g.
9.2.0,9.2.0-beta.1) — lifecycle is inferred automatically (ga,beta,rc) - A promotion report URL or file path
- A plain-text URL list file (one fully-qualified GitHub PR or issue URL per line)
- A plain-text path list file (one changelog YAML path per line, ending in
.yamlor.yml)
When your profile uses {version} in its output pattern and you also want to filter by a report or list file, pass both arguments (version first, then the filter file).
Example profile in changelog.yml:
bundle:
repo: elasticsearch
owner: elastic
directory: docs/changelog
output_directory: docs/releases
profiles:
elasticsearch-release:
products: "elasticsearch {version} {lifecycle}"
output: "elasticsearch/{version}.yaml"
output_products: "elasticsearch {version}"
Supply filter flags directly when you don't have a profile configured or need a one-off bundle.
Exactly one of the following filter flags is required:
--all— include every changelog in the directory--input-products— match by product, target date, and lifecycle (e.g."elasticsearch * *")--prs— filter by PR URLs or a newline-delimited file of PR URLs--issues— filter by issue URLs or a newline-delimited file of issue URLs--release-version— fetch PR references from a GitHub release tag (e.g.v9.2.0orlatest)--report— filter by PRs referenced in a promotion report (URL or local file)--files— include specific changelog YAML paths, or a newline-delimited path list file
--force-local is not a filter. It forces local entry sourcing for the run (equivalent to bundle.use_local_changelogs: true without editing config) and is allowed in both option-based and profile-based modes.
# Bundle all changelogs in docs/changelog/
docs-builder changelog bundle --all --directory docs/changelog
# Bundle changelogs for a specific product release
docs-builder changelog bundle \
--input-products "elasticsearch 9.2.0 ga" \
--output docs/releases/9.2.0.yaml
# Bundle from a GitHub release
docs-builder changelog bundle \
--release-version v9.2.0 \
--repo elasticsearch \
--owner elastic
# Bundle an explicit list of changelog files
docs-builder changelog bundle \
--files "./docs/changelog/a.yaml,./docs/changelog/b.yaml" \
--output docs/releases/serverless/2026-07-07.yaml \
--output-products "cloud-serverless 2026-07-07"
Every bundle embeds the full content of each changelog entry (title, type, products, and so on), plus a file block recording the source file name and checksum for provenance. Rendering — via the {changelog} directive, changelog render, or the CDN pipeline — never reads the original changelog files, so you can clean them up with docs-builder changelog remove immediately after bundling.
Pass --plan to emit GitHub Actions step outputs (needs_network, needs_github_token, output_path) without generating the bundle. Use this in a planning step to decide whether subsequent steps require a GitHub token or network access.
For full configuration reference, see Bundle changelogs.
The changelog bundle command has --input-products and --output-products options that accept values with the format "product target lifecycle, ..." where:
productis the product ID from products.yml (required)targetis the target version or date (optional)lifecycleexists in Lifecycle.cs (optional)
You can further limit the possible values with the products and lifecycles options in the changelog configuration file.
For example:
"kibana 9.2.0 ga""cloud-serverless 2025-08-05""cloud-enterprise 4.0.3, cloud-hosted 2025-10-31"
If you use "* * *" in the --input-products command option or bundle.profiles.<name>.products configuration setting, it's equivalent to the --all command option.
The way that lifecycle values are inferred varies between GitHub release profiles and standard profiles.
For source: github_release profiles, the {lifecycle} placeholder in output and output_products is derived from the full release tag name. For example:
| 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 |
For standard profiles, {version} is copied verbatim from your command argument and {lifecycle} is derived from that value. For example:
| Version argument | {version} |
{lifecycle} |
|---|---|---|
9.2.0 |
9.2.0 |
ga |
9.2.0-beta.1 |
9.2.0-beta.1 |
beta |
9.2.0-preview.1 |
9.2.0-preview.1 |
preview |
2026-07-21 |
2026-07-21 |
ga |
Profile mode does not accept lifecycle on the command line. For semver and date-based releases alike, set lifecycle in the profile YAML:
- Omit lifecycle from the pattern (for example,
"cloud-serverless {version}") to leave the field out of the bundle. - Use
{lifecycle}to derive it from the version or date argument (as in the table above). - Hardcode a lifecycle (for example,
"cloud-serverless {version} ga"or"cloud-serverless {version} preview") when you need an explicit value. Non-gadate-based releases are exceptional and should use a hardcoded lifecycle.
For more information about acceptable product and lifecycle values, go to Product format.
A changelog in a public repository might contain links to pull requests or issues in repositories that should not appear in published documentation.
Set bundle.link_allow_repos in changelog.yml to an explicit list of owner/repo strings. When this key is present (including as an empty list), PR and issue references are filtered at bundle time: only links whose resolved repository is in the list are kept; others are rewritten to # PRIVATE: sentinel strings in the 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
--output-products "apm-agent-dotnet 1.34.0 ga"
- The tag value that is used in the
GET /repos/{owner}/{repo}/releases/tags/{tag}releases API. - 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. - The bundle's product metadata is inferred automatically from the release tag and repository name; you can override that behavior with the
--output-productsoption.
--release-version requires a GITHUB_TOKEN or GH_TOKEN environment variable (or an active gh login) to fetch release details from the GitHub API.
By default all changelogs that match PRs in the GitHub release notes are included in the bundle. To apply additional filtering by the changelog type, areas, or products, add rules.bundle configuration settings.
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 changelog gh-release.
You can use the --issues option to create a bundle of changelogs that relate to those GitHub issues.
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).
docs-builder changelog bundle --issues "12345,12346" \
--repo elasticsearch \
--owner elastic \
--output-products "elasticsearch 9.2.2 ga"
Alternatively, you can specify a path to a newline-delimited file that contains the issue URLS (for example, --issues /path/to/file.txt).
In this case, you cannot use short URLs or numbers, each line must have a full URL.
By default all changelogs that match issues in the list are included in the bundle. To apply additional filtering by the changelog type, areas, or products, add rules.bundle configuration settings.
You can use the --prs option to create a bundle of the changelogs that relate to those pull requests.
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.
docs-builder changelog bundle --prs "108875,135873,136886" \
--repo elasticsearch \
--owner elastic \
--output-products "elasticsearch 9.2.2 ga"
- The comma-separated list of pull request numbers to seek.
- The repository in the pull request URLs. Not required when using full PR URLs, or when
bundle.repois set in the changelog configuration. - The owner in the pull request URLs. Not required when using full PR URLs, or when
bundle.owneris set in the changelog configuration. - The product metadata for the bundle. If it is not provided, it will be derived from all the changelog product values.
Alternatively, you can specify a path to a newline-delimited file that contains the PR URLS (for example, --prs /path/to/file.txt).
In this case, you cannot use short URLs or numbers, each line must have a full URL.
For example:
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
By default all changelogs that match PRs in the list are included in the bundle. To apply additional filtering by the changelog type, areas, or products, add rules.bundle configuration settings.
If you have changelog files that reference those pull requests, the command creates a file like this:
products:
- product: elasticsearch
target: 9.2.2
lifecycle: ga
entries:
- file:
name: 1765507819-fix-ml-calendar-event-update-scalability-issues.yaml
checksum: 069b59edb14594e0bc3b70365e81626bde730ab7
type: bug-fix
title: Fix ML calendar event update scalability issues
products:
- product: elasticsearch
target: 9.2.2
prs:
- https://github.com/elastic/elasticsearch/pull/108875
- file:
name: 1765507798-convert-bytestransportresponse-when-proxying-respo.yaml
checksum: c6dbd4730bf34dbbc877c16c042e6578dd108b62
type: bug-fix
title: Convert BytesTransportResponse when proxying responses
products:
- product: elasticsearch
target: 9.2.2
prs:
- https://github.com/elastic/elasticsearch/pull/135873
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.
If you use profile-based bundling, provide this information in the bundle.profiles.<name>.products field.
docs-builder changelog bundle \
--input-products "cloud-serverless 2025-12-02 ga, cloud-serverless 2025-12-06 beta"
- Include all changelogs that have the
cloud-serverlessproduct identifier with target dates of either December 2 2025 (lifecyclega) or December 6 2025 (lifecyclebeta). For more information about product values, refer to Product format.
You can use wildcards in any of the three parts:
# 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:
products:
- 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
type: bug-fix
title: Fixes enrich and lookup join resolution based on mappings
products:
- product: cloud-serverless
target: 2025-12-02
prs:
- https://github.com/elastic/elasticsearch/pull/136001
- 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: cloud-serverless
target: 2025-12-06
prs:
- https://github.com/elastic/elasticsearch/pull/136002
- By default these values match your
--input-products(even if the changelogs have more products). To specify different product metadata, use the--output-productsoption.
When a changelog matches multiple --input-products filters, it appears only once in the bundle. This deduplication applies even when using --all or --prs.
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
By default all changelogs that match PRs in the promotion report are included in the bundle. To apply additional filtering by the changelog type, areas, or products, add rules.bundle configuration settings.
Use --files when you know the exact changelog files to include and they may not have prs or issues metadata.
docs-builder changelog bundle \
--files "./docs/changelog/a.yaml,./docs/changelog/b.yaml" \
--output docs/releases/serverless/2026-07-07.yaml \
--output-products "cloud-serverless 2026-07-07"
You can also pass a newline-delimited path list file:
docs-builder changelog bundle --files ./docs/temp/changelog_files.txt --output ...
In profile mode, pass the same path list as a positional argument:
docs-builder changelog bundle serverless-release 2026-07-07 ./docs/temp/changelog_files.txt
--files / path-list selection always reads the named files from disk (local entry sourcing). It does not fetch entries from the CDN. rules.bundle still applies after selection.
When a repository defaults to CDN entry sourcing, you can use --force-local to read changelog YAML files from the local folder.
This option overrides the bundle.use_local_changelogs setting in your changelog.yml and is useful for ad hoc bundles that include freshly authored local files that are not on the CDN yet.
docs-builder changelog bundle serverless-release 2026-07-07 ./docs/temp/prs.txt --force-local
--force-local is allowed in both option-based and profile-based commands.
Path-list / --files filters already force local sourcing, so --force-local is optional in that case.
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.
docs-builder changelog bundle \
--input-products "elasticsearch 9.3.0 *" \
--hide-features "feature:hidden-api,feature:experimental" \
--output /path/to/bundles/9.3.0.yaml
- Feature IDs to hide. Changelogs with matching
feature-idvalues will be commented out when rendered.
The bundle output will include a hide-features field:
products:
- product: elasticsearch
target: 9.3.0
hide-features:
- feature:hidden-api
- feature:experimental
entries:
- file:
name: 1765495972-new-feature.yaml
checksum: 6c3243f56279b1797b5dfff6c02ebf90b9658464
type: feature
title: New feature behind a flag
feature-id: feature:hidden-api
products:
- product: elasticsearch
target: 9.3.0
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.
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.