Skip to content
Open
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
11 changes: 8 additions & 3 deletions config/changelog.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -246,20 +246,25 @@ bundle:
# repo: elasticsearch
# Optional: default GitHub owner applied to all profiles that do not specify their own.
# owner: elastic
# Optional: branch whose CDN changelog pool (changelog/{org}/{repo}/{branch}/...) is sourced from when
# Optional: branch whose CDN changelog entries (changelog/{org}/{repo}/{branch}/...) are sourced from when
# bundling entries from the CDN. Defaults to "main" when unset. Can be overridden per profile.
# branch: main
# Optional: control auto-population of release-date for all profiles by default.
# When true (default), auto-populate release dates. Profiles can override this setting.
# release_dates: true
# Optional: when true, git-ref bundling synthesizes changelog entries from GitHub PR metadata
# when no matching changelog YAML is found on the CDN (or in the local folder when local
# sourcing is forced). Default false: unmatched PRs are warned and omitted like --prs.
# Override per profile or with CLI --infer.
# infer_missing_changelogs: false

# Named bundle profiles for different release scenarios.
# Profiles can be used with both 'changelog bundle' and 'changelog remove':
# docs-builder changelog bundle elasticsearch-release 9.2.0
# docs-builder changelog remove elasticsearch-release 9.2.0
# When used with 'changelog remove', only the 'products' field is applied.
# The 'output', 'output_products', 'repo', 'owner', and 'hide_features' fields are
# bundle-specific and are ignored for removal.
# The 'output', 'output_products', 'repo', 'owner', 'hide_features', and
# 'infer_missing_changelogs' fields are bundle-specific and are ignored for removal.
profiles:
# Example: Elasticsearch release profile (filter by changelog fields)
# elasticsearch-release:
Expand Down
26 changes: 21 additions & 5 deletions docs/cli-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3240,7 +3240,7 @@
"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."
"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 changelog YAML is sourced from the CDN (or the local folder when local sourcing is forced); unmatched PRs are warned and omitted unless --infer or bundle.infer_missing_changelogs is set. 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",
Expand All @@ -3254,7 +3254,15 @@
"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.",
"summary": "Resolve the commit range and print the run report (resolved PR list with per-PR entry source: pool, no changelog, 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": "infer",
"type": "boolean",
"required": false,
"summary": "When bundling a git commit range, synthesize in-memory changelog entries from GitHub PR metadata for PRs with no matching changelog YAML on the CDN (or in the local folder when using --force-local). Default: unmatched PRs are warned and omitted like --prs. Equivalent to bundle.infer_missing_changelogs: true without editing config. Allowed in profile-based commands. Only valid together with --start-git-ref/--end-git-ref.",
"defaultValue": "false"
},
{
Expand Down Expand Up @@ -3333,7 +3341,7 @@
"name": "add",
"type": "array",
"required": false,
"summary": "Optional: Changelog YAML paths to add. Repeat --add or pass a comma-separated list in one value (for example, --add \u0022file1.yaml,file2.yaml\u0022). Supports tilde (~) expansion and relative paths.",
"summary": "Optional: Changelog YAML paths to add. Repeat --add or pass a comma-separated list in one value (for example, --add \u0022file1.yaml,file2.yaml\u0022). Supports tilde (~) expansion and relative paths. When entries are sourced from the CDN (the default when bundle.repo or the parent bundle\u0027s repo resolves), paths are matched by file name and do not need to exist locally; with local sourcing (--force-local or bundle.use_local_changelogs) the paths must exist on disk.",
"repeatable": true,
"elementType": "string"
},
Expand All @@ -3342,7 +3350,7 @@
"name": "remove",
"type": "array",
"required": false,
"summary": "Optional: Changelog YAML paths to exclude from the effective bundle. Repeat --remove or pass a comma-separated list in one value. Supports tilde (~) expansion and relative paths.",
"summary": "Optional: Changelog YAML paths to exclude from the effective bundle. Repeat --remove or pass a comma-separated list in one value. Supports tilde (~) expansion and relative paths. When entries are sourced from the CDN, paths are matched by file name and do not need to exist locally; with local sourcing the paths must exist on disk unless --force is used to exclude by file name.",
"repeatable": true,
"elementType": "string"
},
Expand All @@ -3351,7 +3359,15 @@
"name": "force",
"type": "boolean",
"required": false,
"summary": "Optional: When removing, match by file name even if the bundle checksum differs from the file on disk.",
"summary": "Optional: When removing, match by file name even if the bundle checksum differs from the sourced changelog, or when no YAML can be sourced (inferred git-ref entries).",
"defaultValue": "false"
},
{
"role": "flag",
"name": "force-local",
"type": "boolean",
"required": false,
"summary": "Optional: Force local entry sourcing for this run (equivalent to bundle.use_local_changelogs: true without editing config).",
"defaultValue": "false"
},
{
Expand Down
50 changes: 41 additions & 9 deletions docs/cli/changelog/cmd-bundle-amend.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,37 +60,66 @@ The result is rendered as a single release.
Amend bundles created by older docs-builder versions may omit `products`; they are still accepted when loading and merge into their parent as before. `hide-features` is always inherited from the parent bundle. If an amend bundle is found without a matching parent bundle, it remains standalone.

`rules.bundle` filtering does not apply to `changelog bundle-amend`. The command is a direct-injection escape hatch: the files you specify with `--add` are always included regardless of any product, type, or area filter configuration.

`--add` and `--remove` follow the same entry-sourcing gate as [](/cli/changelog/bundle.md): CDN by default when `bundle.repo` or the parent bundle's `repo` resolves; local disk when `--force-local` or `bundle.use_local_changelogs` is set, or when no authoring repo can be resolved. In CDN mode, paths are matched by file name (including CDN paths such as `/changelog/elastic/kibana/main/247279.yaml`) and do not need to exist locally. Use `--force-local` to read local changelogs from disk.

The parent bundle argument is always a local file. The command writes `{parent}.amend-N.yaml` next to it and does not fetch the parent from the CDN.
:::

## Examples

### Add a single changelog to a bundle
### Add a changelog from the CDN

The first argument is the local parent bundle. `--add` can be a CDN path (matched by file name) when entry sourcing uses the CDN:

```sh
docs-builder changelog bundle-amend \
./docs/changelog/bundles/9.3.0.yaml \
--add ./docs/changelog/138723.yaml
--add /changelog/elastic/kibana/main/138723.yaml
```

### Add a single local changelog to a bundle

```sh
docs-builder changelog bundle-amend \
./docs/changelog/bundles/9.3.0.yaml \
--add ./docs/changelog/138723.yaml \
--force-local
```

### Remove a changelog from a bundle

```sh
docs-builder changelog bundle-amend \
./docs/changelog/bundles/9.3.0.yaml \
--remove ./docs/changelog/138723.yaml
--remove /changelog/elastic/kibana/main/138723.yaml
```

The CLI computes the file checksum automatically and matches it against the effective bundle (parent plus any existing amend files).
The CLI computes the checksum of the sourced YAML and matches it against the effective bundle (parent plus any existing amend files).
If the bundle contains the file with a different checksum, the command fails unless you pass `--force` to remove by file name only.

### Remove an inferred git-ref entry [inferred-git-ref-entry]

Git-ref bundles created with `--infer` (or `infer_missing_changelogs: true`) can include entries that were synthesized from GitHub PR metadata. Those entries live only in the bundle. Their `file.name` is `{pull-request-number}.yaml`, and there is no changelog YAML on disk or on the CDN whose checksum you can match.

Pass `--force` so matching is by filename only. The path does not need to exist:

```sh
docs-builder changelog bundle-amend ./docs/releases/cloud-hosted-2026-08-13.yaml \
--remove 300.yaml --force
```

Refer to [](/cli/changelog/bundle.md#inferred-entries) for the full workflow, including how to replace inferred copy with a real changelog.

### Add multiple changelogs to a bundle

Comma-separated list:

```sh
docs-builder changelog bundle-amend \
./docs/changelog/bundles/9.3.0.yaml \
--add "./docs/changelog/138723.yaml,./docs/changelog/1770424335.yaml"
--add "./docs/changelog/138723.yaml,./docs/changelog/1770424335.yaml" \
--force-local
```

Or repeat `--add`:
Expand All @@ -99,15 +128,17 @@ Or repeat `--add`:
docs-builder changelog bundle-amend \
./docs/changelog/bundles/9.3.0.yaml \
--add ./docs/changelog/138723.yaml \
--add ./docs/changelog/1770424335.yaml
--add ./docs/changelog/1770424335.yaml \
--force-local
```

### Remove multiple changelogs from a bundle

```sh
docs-builder changelog bundle-amend \
./docs/changelog/bundles/9.3.0.yaml \
--remove "./docs/changelog/old-a.yaml,./docs/changelog/old-b.yaml"
--remove "./docs/changelog/old-a.yaml,./docs/changelog/old-b.yaml" \
--force-local
```

### Replace an entry in one amend file
Expand All @@ -116,14 +147,15 @@ docs-builder changelog bundle-amend \
docs-builder changelog bundle-amend \
./docs/changelog/bundles/9.3.0.yaml \
--remove ./docs/changelog/old-entry.yaml \
--add ./docs/changelog/new-entry.yaml
--add ./docs/changelog/new-entry.yaml \
--force-local
```

### Preview without writing an amend file

```sh
docs-builder changelog bundle-amend \
./docs/changelog/bundles/9.3.0.yaml \
--remove ./docs/changelog/138723.yaml \
--remove /changelog/elastic/kibana/main/138723.yaml \
--dry-run
```
Loading
Loading