Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/cli-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3227,6 +3227,28 @@
"required": false,
"summary": "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."
},
{
"role": "flag",
"name": "start-git-ref",
"type": "string",
"required": false,
"summary": "Start ref (exclusive) of a git commit range to bundle, for example the previously published endpoint ref. Must be provided together with --end-git-ref; the start ref is never inferred. The PR list is derived from the range itself (GitHub compare API \u002B GraphQL associatedPullRequests), each PR\u0027s entry is sourced pool-first with PR-metadata fallback, and requires GITHUB_TOKEN. Supported in profile-based commands (for example, \u0027bundle serverless-release 2026-08-13 --start-git-ref abc123 --end-git-ref def456\u0027); mutually exclusive with all other filter options."
},
{
"role": "flag",
"name": "end-git-ref",
"type": "string",
"required": false,
"summary": "End ref (inclusive) of the git commit range to bundle \u2014 the currently published endpoint ref. Must be provided together with --start-git-ref. Recorded in the bundle output as the git_ref metadata field."
},
{
"role": "flag",
"name": "dry-run",
"type": "boolean",
"required": false,
"summary": "Resolve the commit range and print the run report (resolved PR list with per-PR entry source: pool, inferred, or missing) as Markdown without writing a bundle. Only valid together with --start-git-ref/--end-git-ref. Supported in profile-based commands.",
"defaultValue": "false"
},
{
"role": "flag",
"name": "log-level",
Expand Down
38 changes: 38 additions & 0 deletions docs/cli/changelog/cmd-bundle.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Exactly one of the following filter flags is required:
- `--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)
- `--files` — include specific changelog YAML paths, or a newline-delimited path list file
- `--start-git-ref` + `--end-git-ref` — derive the PR list from a git commit range (see [Commit-range mode](#git-ref-mode))

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

Expand All @@ -75,6 +76,43 @@ docs-builder changelog bundle \
--output-products "cloud-serverless 2026-07-07"
```

## Commit-range mode [git-ref-mode]

`--start-git-ref` and `--end-git-ref` cut a bundle from a **git commit range** instead of an externally supplied PR list. This is the mode date-promotion automation (serverless, Cloud ECH/ECE) uses: the promotion system hands off two commit hashes from a protected branch, and the command derives everything else itself.

```sh
docs-builder changelog bundle serverless-release 2026-08-13 \
--start-git-ref <previous-published-ref> \
--end-git-ref <current-published-ref>
```

Both refs are always required together — the start ref is never inferred from previous bundles. The command:

1. Enumerates the commits in `start..end` via the GitHub compare API (paginated).
2. Resolves each commit to its merged pull request via GraphQL `associatedPullRequests`. Works for squash and merge commits on protected integration branches; commits with no associated PR are reported, never silently dropped. When a commit is associated with multiple merged PRs, the command warns and picks deterministically (merge-commit match first, then lowest PR number).
3. Sources each PR's changelog entry with a fixed precedence:
- **A checked-in entry from the entry pool wins.** Pool entries are matched by file-name-derived PR numbers (file names survive scrubbing, so this works for private repos whose `prs` references were removed from public copies) or by the entry's `prs` references.
- **Otherwise the entry is synthesized from PR metadata** — the same extraction path `changelog add` uses: release-note text from the PR body becomes the description, and labels map to type/areas/products/feature-id via the `pivot.*` configuration. `rules.create` label rules decide inclusion.
- **PRs whose metadata cannot be fetched are reported as missing** with a warning.
4. Records the end ref in the bundle output as the `git_ref` metadata field.

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

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

:::{note}
Commit-range mode requires a `GITHUB_TOKEN` environment variable: the GraphQL API used for commit→PR association does not accept anonymous requests.
:::

### Dry run

Pass `--dry-run` to resolve the range and print the run report — the resolved PR list with each PR's entry source (`pool`, `inferred (PR body)`, `inferred (title)`, `excluded (rules)`, or `missing`) plus any commits without an associated PR — as Markdown, without writing a bundle. The report is suitable for a release PR body or a CI job summary.

```sh
docs-builder changelog bundle serverless-release 2026-08-13 \
--start-git-ref abc123 --end-git-ref def456 --dry-run
```

## Bundles are self-contained

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.
Expand Down
27 changes: 27 additions & 0 deletions docs/data/release-notes/bundle.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,33 @@ bundle:
1. This profile fetches the PR list from the GitHub release notes for the version tag specified in the command.
2. For `source: github_release` profiles, the `{lifecycle}` placeholder in `output` and `output_products` is inferred from full release tag name. For example, if the release tag is `v1.34.1-preview.1` the lifecycle is `preview`. Refer to [](/cli/changelog/bundle.md#lifecycle-inference) for more details.

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

If the source of truth for what was shipped in each release is a **git commit range** — for example, a date-promotion deployment that hands off the previously and currently published commit hashes — pass `--start-git-ref` and `--end-git-ref` alongside the profile. The command derives the PR list from the range itself (GitHub compare API + GraphQL `associatedPullRequests`), so no PR list file or promotion report is needed.

Your profile must **not** contain a `products` pattern or `source: github_release`; it contributes output metadata only. For example:

```yaml
bundle:
repo: my-service <1>
owner: elastic
output_directory: docs/releases
profiles:
serverless-release:
output_products: "cloud-serverless {version}" <2>
```

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

```sh
docs-builder changelog bundle serverless-release 2026-08-13 \
--start-git-ref <previous-published-ref> \
--end-git-ref <current-published-ref>
```

For each PR in the range, a checked-in changelog entry (already uploaded to the entry pool) wins; otherwise an entry is synthesized from the PR's title, labels, and release-note text using the same extraction path as `changelog add`. The bundle records the end ref in a `git_ref` metadata field. Refer to [Commit-range mode](/cli/changelog/bundle.md#git-ref-mode) for the full behavior, including the `--dry-run` run report.

### Bundle by folder or changelog product

If the source of truth for what was shipped in each release is:
Expand Down
Loading
Loading