Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7614770
Fix changelog rule logic when a single config file must apply to mult…
lcawl Mar 24, 2026
804d0c0
Finalize tests
lcawl Mar 24, 2026
eebc92c
Merge branch 'main' into rules-bundle-products
lcawl Mar 24, 2026
7a310fe
Unify filtering precedence logic
lcawl Mar 24, 2026
894f730
Merge branch 'main' into rules-bundle-products
lcawl Mar 24, 2026
03370db
Fix test assumptions
lcawl Mar 24, 2026
99d6d08
Lint test spacing
lcawl Mar 24, 2026
27d1ba9
Refer to docs from config example
lcawl Mar 25, 2026
21fe13f
Add exclude_products to test
lcawl Mar 25, 2026
71800d7
Fix match_products resolution
lcawl Mar 25, 2026
9d438dc
Fix disjoint fallback logic
lcawl Mar 25, 2026
7a500a3
Unify filter fallback behaviour
lcawl Mar 25, 2026
92c15b5
Merge branch 'main' into rules-bundle-products
lcawl Mar 25, 2026
e207096
Switch to single product rule resolution
lcawl Mar 25, 2026
4f569fa
Fix broken link
lcawl Mar 25, 2026
60d573c
Merge branch 'main' into rules-bundle-products
lcawl Mar 25, 2026
c285148
Interim clarity
lcawl Mar 26, 2026
7b374dd
Implement three modes of rule resolution
lcawl Mar 26, 2026
d284984
Add conjunction matching
lcawl Mar 26, 2026
1ac952b
Merge branch 'main' into rules-bundle-products
lcawl Mar 26, 2026
9f2cf5f
Fix usage of AwesomeAssertions
lcawl Mar 26, 2026
34ed8e9
Remove rule_context_product and --rule-context-product
lcawl Mar 27, 2026
949ce53
Merge branch 'main' into rules-bundle-products
lcawl Mar 27, 2026
56cfe97
Reject malformed product entries
lcawl Mar 27, 2026
08a2521
Use the current product-filter diagnostic tag
lcawl Mar 27, 2026
fe85ff8
More test fixes
lcawl Mar 27, 2026
7519e46
Remove dead code
cotti Mar 27, 2026
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
99 changes: 35 additions & 64 deletions config/changelog.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,11 @@ pivot:
# - Comma-separated string: "value1, value2, value3"
# - YAML list: [value1, value2, value3]
#
# Global match default for multi-valued fields (labels, areas, products).
# any (default) = match if ANY item matches the list
# all = match only if ALL items match the list
# Inherited by create, bundle, publish, and all product overrides.
# For details and examples, refer to the [rules documentation](https://github.com/elastic/docs-builder/blob/main/docs/contribute/changelog.md#rules-for-creation-and-bundling).
rules:
# match: any

# Create — controls which PRs generate changelogs.
# exclude: block PRs with these labels (string or list)
# include: only create changelogs for PRs with these labels (string or list)
# Cannot specify both.
#
# create:
# exclude: ">non-issue, >test"
# # Or equivalently:
Expand All @@ -176,68 +169,40 @@ rules:
# exclude: "ILM"

# Bundle — filtering applied during 'changelog bundle' and 'changelog gh-release'.
# Applied after the primary filter (--prs, --issues, --all, ...) has collected changelogs.
#
# Product filtering:
# Skipped when the primary filter is already product-based
# (--input-products option or a profile with bundle.profiles.<name>.products configured).
# exclude_products / include_products (string or list) — cannot specify both.
# match_products inherits from rules.match if not specified.
# See docs/contribute/changelog.md → "Bundle rule modes" for Mode 1 / 2 / 3 behavior.
#
# Type and area filtering (replaces rules.publish):
# Always applied, regardless of the primary filter.
# exclude_types / include_types (string or list) — cannot specify both.
# exclude_areas / include_areas (string or list) — cannot specify both.
# match_areas inherits from rules.match if not specified.
#
# Per-product overrides:
# products:
# '<id>': override type/area filters for that product
#
# When an entry belongs to multiple products, the applicable rule is resolved using
# intersection + alphabetical first-match. See docs/contribute/changelog.md for details.
# Mode 2 (global content): use global lists only — no `products` key, or `products: {}`.
# Example — include changelogs that list elasticsearch OR kibana (evaluated per changelog):
# bundle:
# match_products: any
# include_products:
# - elasticsearch
# - kibana
# exclude_types: "deprecation, known-issue"
#
# Example — exclude only when the changelog lists BOTH products (conjunction); extras allowed:
# bundle:
# # match_products: any
# exclude_products: "cloud-enterprise"
# # Or include only certain products:
# # include_products:
# # - cloud-serverless
# # - cloud-hosted
# # Type/area filtering:
# # exclude_types: "deprecation, known-issue"
# # exclude_areas:
# # - "Internal"
# # Per-product overrides:
# # products:
# # 'elasticsearch, kibana':
# # exclude_types:
# # - docs
# # 'cloud-serverless':
# # # match_areas: any
# # include_areas:
# # - "Search"
# # - "Monitoring"

# Publish — DEPRECATED AND NO LONGER USED.
# The `changelog render` command does not use rules.publish. Move type/area filtering to rules.bundle above.
# The `{changelog}` directive also does not use rules.publish.
# This section is ignored by both commands, and will be removed in a future release.
# A deprecation warning is emitted if rules.publish is present in the configuration.
# match_products: conjunction
# exclude_products:
# - kibana
# - observability
#
# publish:
# # match_areas: any
# exclude_types: "deprecation, known-issue"
# exclude_areas:
# - "Internal"
# Mode 3 (per-product context): non-empty `rules.bundle.products` — global include/exclude/type/area
# under `bundle:` are NOT applied for filtering; configure filters under each product key.
# Example:
# bundle:
# exclude_types: [docs] # ignored for filtering in Mode 3 — duplicate under each product if needed
# products:
# 'elasticsearch, kibana':
# exclude_types:
# - docs
# 'cloud-serverless':
# observability:
# exclude_products: ["cloud-enterprise"]
# exclude_types: ["docs"]
# include_areas:
# - "Search"
# - "Monitoring"
# - "APM"
# - "Infrastructure monitoring"
# kibana:
# match_products: all
# include_products: ["kibana", "security"]
# exclude_types: ["docs"]

# Bundle configuration (profiles and defaults)
bundle:
Expand Down Expand Up @@ -292,3 +257,9 @@ bundle:
# hide_features:
# - feature-flag-1
# - feature-flag-2

# Example: Multi-product profile (Mode 3 rule context = first product alphabetically, e.g. kibana).
# For security-only rules, add a separate profile with output_products listing only security.
# kibana-security-release:
# output: "kibana-security-{version}.yaml"
# output_products: "kibana {version}, security {version}"
20 changes: 9 additions & 11 deletions docs/cli/release/changelog-bundle.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ You must choose one method for determining what's in the bundle (`--all`, `--inp
- `"* * *"` - match all changelogs (equivalent to `--all`)

:::{note}
When you use the `--input-products` filtering option, the bundle command ignores any `rules.bundle.include_products` or `exclude_products` [filters](#changelog-bundle-rules). They are mutually exclusive.
The `--input-products` option determines which changelog files are gathered for consideration. **`rules.bundle` is not disabled** when you use `--input-products` — global `include_products` / `exclude_products`, type/area rules, and (when configured) per-product rules still run **after** matching, unless your configuration is in [no-filtering mode](/contribute/changelog.md#bundle-rule-modes). The only “mutually exclusive” pairing on this command is **profile-based** bundling versus **option-based** flags (see [Usage](#usage)), not `--input-products` versus `rules.bundle`.
:::

`--issues <string[]?>`
Expand All @@ -108,7 +108,7 @@ When you use the `--input-products` filtering option, the bundle command ignores
`--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 be derived from changelogs.
: When `rules.bundle.products` per-product overrides are configured, `--output-products` also sets the product context used for rule resolution. For details, refer to [Per-product rule resolution for multi-product entries](/contribute/changelog.md#changelog-bundle-multi-product-rules).
: When `rules.bundle.products` per-product overrides are configured, `--output-products` also supplies the product IDs used to choose the **rule context product** (first alphabetically) for Mode 3. To use a different product's rules, run a separate bundle with only that product in `--output-products`. For details, refer to [Single-product rule resolution algorithm](/contribute/changelog.md#changelog-bundle-rule-resolution).

`--owner <string?>`
: Optional: The GitHub repository owner, required when pull requests or issues are specified as numbers.
Expand Down Expand Up @@ -187,10 +187,9 @@ Setting `bundle.directory` and `bundle.output_directory` in `changelog.yml` is r

## Rules for filtered bundles [changelog-bundle-rules]

The `rules.bundle` section in the changelog configuration file lets you filter entries during bundling. It applies to both `changelog bundle` and `changelog gh-release`, after entries are matched by the primary filter (`--prs`, `--issues`, `--all`) and before the bundle is written.
The `rules.bundle` section in the changelog configuration file lets you filter entries during bundling. It applies to both `changelog bundle` and `changelog gh-release`, after entries are matched by the primary filter (`--prs`, `--issues`, `--all`, **`--input-products`**, and so on) and before the bundle is written.

The **product filter** (`exclude_products`/`include_products`) is skipped when the primary filter is `--input-products` (or `bundle.profiles.<name>.products`), because the primary filter already constrains by product.
The **type and area filter** (`exclude_types`/`include_types`/`exclude_areas`/`include_areas`) always applies, regardless of the primary filter.
Which `rules.bundle` fields take effect depends on the [bundle rule modes](/contribute/changelog.md#bundle-rule-modes) (no filtering, global rules against each changelog’s content, or per-product rule context). Input stage (gathering entries) and bundle filtering stage (filtering for output) are conceptually separate.

The following fields are supported:

Expand All @@ -201,7 +200,7 @@ The following fields are supported:
: A product ID or list of product IDs to include in the bundle (all others are excluded). Cannot be combined with `exclude_products`.

`match_products`
: Match mode for the product filter (`any` or `all`). Inherits from `rules.match` when not specified.
: Match mode for the product filter (`any`, `all`, or `conjunction`). Inherits from `rules.match` when not specified.

`exclude_types`
: A changelog type or list of types to exclude from the bundle.
Expand All @@ -216,11 +215,10 @@ The following fields are supported:
: Only changelogs with these areas are kept; all others are excluded.

`match_areas`
: Match mode for the area filter (`any` or `all`). Inherits from `rules.match` when not specified.
: Match mode for the area filter (`any`, `all`, or `conjunction`). Inherits from `rules.match` when not specified.

`products`
: Per-product type/area filter overrides. Keys are product IDs (or comma-separated lists). Product-specific rules override the global `rules.bundle` type/area rules for entries matching that product.
: When an entry belongs to multiple products, the applicable rule is chosen by the intersection + alphabetical first-match algorithm. For details, refer to [Per-product rule resolution for multi-product entries](/contribute/changelog.md#changelog-bundle-multi-product-rules).
: Per-product filter overrides for **all filter types** (product, type, area). Keys are product IDs (or comma-separated lists). When this map is **non-empty**, the bundler uses **per-product rule context** mode: global `rules.bundle` product/type/area fields are **not** used for filtering (repeat constraints under each product key if you still need them). For details, refer to [Bundle rule modes](/contribute/changelog.md#bundle-rule-modes) and [Single-product rule resolution (Mode 3 only)](/contribute/changelog.md#changelog-bundle-rule-resolution).

```yaml
rules:
Expand Down Expand Up @@ -348,7 +346,7 @@ If you're using profile-based commands, they're affected by the following fields
: Example: `"elasticsearch {version} {lifecycle}"`

:::{note}
When you use the `products` filtering method, the bundle command ignores any `rules.bundle.include_products` or `exclude_products` [filters](#changelog-bundle-rules). They are mutually exclusive.
The `products` field determines which changelog files are gathered for consideration. **`rules.bundle` still applies** afterward (see the note under [`--input-products`](#options)). Input stage and bundle filtering stage are conceptually separate.
:::

`output`
Expand Down Expand Up @@ -456,7 +454,7 @@ bundle:
`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.

:::{note}
When you use the `products` filtering method, the bundle command ignores any `rules.bundle.include_products` or `exclude_products` [filters](#changelog-bundle-rules). They are mutually exclusive.
The `products` field determines which changelog files are gathered for consideration. **`rules.bundle` still applies** afterward (see the note under [`--input-products`](#options)). Input stage and bundle filtering stage are conceptually separate.
:::

### Bundle by report or URL list [profile-bundle-report-examples]
Expand Down
6 changes: 3 additions & 3 deletions docs/cli/release/changelog-gh-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ The product, target version, and lifecycle are inferred automatically from the r

## Configuration

The `rules.bundle` section of your `changelog.yml` applies to bundles created by this command.
Type, area, and product filtering all apply.
The `rules.bundle` section of your `changelog.yml` applies to bundles created by this command (after changelog files are gathered from the release).
Which fields take effect depends on [bundle rule modes](/contribute/changelog.md#bundle-rule-modes).
For details, refer to [Rules for filtered bundles](/cli/release/changelog-bundle.md#changelog-bundle-rules).
If you use per-product rule overrides and changelogs can belong to multiple products, refer to [Per-product rule resolution for multi-product entries](/contribute/changelog.md#changelog-bundle-multi-product-rules).
If you use per-product rule overrides, refer to [Single-product rule resolution (Mode 3 only)](/contribute/changelog.md#changelog-bundle-rule-resolution).

## Examples

Expand Down
Loading
Loading