﻿---
title: changelog bundle cli command
description: 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...
url: https://docs-v3-preview.elastic.dev/elastic/docs-builder/pull/2927/cli/changelog/bundle
products:
  - Elastic Docs Builder
---

# changelog bundle cli command
```bash
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.

## Profile-based mode

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.
```sh
# 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 URL per line)

When your profile uses `{version}` in its output pattern and you also want to filter by a report, pass both arguments.
Example profile in `changelog.yml`:
```yaml
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}"
```


## Option-based mode

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.0` or `latest`)
- `--report` — filter by PRs referenced in a promotion report (URL or local file)

```sh
# 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
```


## Resolved vs. reference bundles

By default the bundle contains only file names and checksums — the original changelog files must remain on disk for rendering. Add `--resolve` (or set `bundle.resolve: true` in `changelog.yml`) to embed the full entry content inside the bundle. A resolved bundle is:
- Required when using the `{changelog}` directive after deleting the source changelog files
- Required when `link_allow_repos` is configured (private-link scrubbing only runs during resolve)
- Necessary to regenerate rendered Markdown or AsciiDoc after the source files are removed

<tip>
  For most release workflows, use `--resolve`. It makes the bundle self-contained and allows you to clean up the changelog files with `docs-builder changelog remove` immediately after bundling.
</tip>


## CI usage

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](https://docs-v3-preview.elastic.dev/elastic/docs-builder/pull/2927/contribute/bundle-changelogs).

## Product format

The `changelog bundle` command has `--input-products` and `--output-products` options that 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` exists in [Lifecycle.cs](https://github.com/elastic/docs-builder/blob/main/src/Elastic.Documentation/Lifecycle.cs) (optional)

You can further limit the possible values with the [products](/elastic/docs-builder/pull/2927/contribute/configure-changelogs-ref#products) and [lifecycles](/elastic/docs-builder/pull/2927/contribute/configure-changelogs-ref#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.

## Lifecycle inference

The way that lifecycle values are inferred varies between GitHub release profiles and standard profiles.

### GitHub release 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`     |


### Standard profiles

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`     |

For more information about acceptable product and lifecycle values, go to [Product format](#product-format).

## PR and issue link allowlist

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.
<important>
  `bundle.link_allow_repos` requires a **resolved** bundle. Set `bundle.resolve: true` or pass `--resolve`.
</important>


## Arguments

<definitions>
  <definition term="<profile> string">
    Optional: Profile name from bundle.profiles in config (for example, "elasticsearch-release"). When specified, the second argument is the version or promotion report URL.
  </definition>
  <definition term="<profile-arg> string">
    Optional: Version number or promotion report URL/path when using a profile (for example, "9.2.0" or "[https://buildkite.../promotion-report.html](https://buildkite.../promotion-report.html)")
  </definition>
  <definition term="<profile-report> string">
    Optional: Promotion report or URL list file when also providing a version. When provided, the second argument must be a version string and this is the PR/issue filter source (for example, "bundle serverless-release 2026-02 ./report.html").
  </definition>
</definitions>


## Options

<definitions>
  <definition term="--[no-]all">
    Include all changelogs in the directory.
    **Default:** `false`
  </definition>
  <definition term="--config string">
    Optional: Path to the changelog.yml configuration file. Defaults to 'docs/changelog.yml'
    **Constraints:** symbolic links not allowed, must exist, extensions: yml, yaml, supports `~` home expansion
  </definition>
  <definition term="--directory string">
    Optional: Directory containing changelog YAML files. Uses config bundle.directory or defaults to current directory
    **Constraints:** symbolic links not allowed, supports `~` home expansion
  </definition>
  <definition term="--description string">
    Optional: Bundle description text with placeholder support. Supports VERSION, LIFECYCLE, OWNER, and REPO placeholders. Overrides bundle.description from config. In option-based mode, placeholders require --output-products to be explicitly specified.
  </definition>
  <definition term="--hide-features string[]">
    Optional: Filter by feature IDs (comma-separated) or a path to a newline-delimited file containing feature IDs. Can be specified multiple times. Entries with matching feature-id values will be commented out when the bundle is rendered (by CLI render or changelog directive).
    **Repeatable:** pass `--hide-features` multiple times to supply more than one value
  </definition>
  <definition term="--[no-]no-release-date">
    Optional: Skip auto-population of release date in the bundle. Mutually exclusive with --release-date. Not available in profile mode.
    **Default:** `false`
  </definition>
  <definition term="--release-date string">
    Optional: Explicit release date for the bundle in YYYY-MM-DD format. Overrides auto-population behavior. Mutually exclusive with --no-release-date. Not available in profile mode.
  </definition>
  <definition term="--input-products string">
    Filter by products in format "product target lifecycle, ..." (for example, "cloud-serverless 2025-12-02 ga, cloud-serverless 2025-12-06 beta"). When specified, all three parts (product, target, lifecycle) are required but can be wildcards (*). Examples: "elasticsearch * *" matches all elasticsearch changelogs, "cloud-serverless 2025-12-02 *" matches cloud-serverless 2025-12-02 with any lifecycle, "* 9.3.* *" matches any product with target starting with "9.3.", "* * *" matches all changelogs (equivalent to --all).
  </definition>
  <definition term="--output string">
    Optional: Output path for the bundled changelog. Can be either (1) a directory path, in which case 'changelog-bundle.yaml' is created in that directory, or (2) a file path ending in .yml or .yaml. Uses config bundle.output_directory or defaults to 'changelog-bundle.yaml' in the input directory
  </definition>
  <definition term="--output-products string">
    Optional: Explicitly set the products array in the output file in format "product target lifecycle, ...". Overrides any values from changelogs.
  </definition>
  <definition term="--issues string[]">
    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.
    **Repeatable:** pass `--issues` multiple times to supply more than one value
  </definition>
  <definition term="--owner string">
    GitHub repository owner, which is used when PRs or issues are specified as numbers or when using --release-version. Falls back to bundle.owner in changelog.yml when not specified. If that value is also absent, "elastic" is used.
  </definition>
  <definition term="--[no-]plan">
    Emit GitHub Actions step outputs (needs_network, needs_github_token, output_path) describing network requirements and the resolved output path, then exit without generating the bundle. Intended for CI actions.
    **Default:** `false`
  </definition>
  <definition term="--prs string[]">
    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.
    **Repeatable:** pass `--prs` multiple times to supply more than one value
  </definition>
  <definition term="--release-version string">
    GitHub release tag to use as a filter source (for example, "v9.2.0" or "latest"). When specified, fetches the release, parses PR references from the release notes, and uses those PRs as the filter — equivalent to passing the PR list via --prs. When --output-products is not specified, it is inferred from the release tag and repository name.
  </definition>
  <definition term="--repo string">
    GitHub repository name, which is used when PRs or issues are specified as numbers or when using --release-version. Falls back to bundle.repo in changelog.yml when not specified. If that value is also absent, the product ID is used.
  </definition>
  <definition term="--report string">
    A URL or file path to a promotion report. Extracts PR URLs and uses them as the filter.
  </definition>
  <definition term="--[no-]resolve">
    Optional: Copy the contents of each changelog file into the entries array. Uses config bundle.resolve or defaults to false.
  </definition>
  <definition term="-l --log-level enum">
    Minimum log level.
    **Values:** trace, debug, information, warning, error, critical, none
    **Default:** `information`
  </definition>
  <definition term="-c --config-source enum">
    Override the configuration source: local, remote
    **Values:** local, remote, embedded
  </definition>
  <definition term="--[no-]skip-private-repositories">
    Skip cloning private repositories
  </definition>
</definitions>


## Notes

Accepts either a named profile from changelog.yml (e.g. bundle my-release 9.2.0) or
an explicit filter flag. Exactly one filter must be specified: --all, --input-products,
--prs, --issues, --release-version, or --report.