Fix multi-product rule resolution for changelog render#2889
Draft
lcawl wants to merge 1 commit intochangelog-bundle-rulesfrom
Draft
Fix multi-product rule resolution for changelog render#2889lcawl wants to merge 1 commit intochangelog-bundle-rulesfrom
lcawl wants to merge 1 commit intochangelog-bundle-rulesfrom
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR relates to a bug found while testing #2874:
Make per-product type/area rules (in
rules.bundle.productsandrules.publish.products) resolve consistently using intersection + alphabetical first-match, withoutput_products/ bundleProductsas the authoritative product context.The core problem
The two existing behaviors are inconsistent and both wrong for multi-product entries:
**changelog bundle**(GetBlockerForEntry): "first-match from the entry's own product list in YAML order" — ignores which product(s) the bundle is being assembled for; YAML order is arbitrary**changelog render**(ShouldHideEntry): "any-blocks from the bundle'sProductsarray" — too aggressive; one product's exclusion rules block the entry from a different product's outputThis PR fixes the render-specific scenario.
Implementation details
src/services/Elastic.Changelog/Rendering/ChangelogRenderUtilities.cs:GetPublishBlockerForEntry: replaced the first-match-from-iteration-order loop over bundle products with a call to the sharedPublishBlockerExtensions.ResolveBlocker(bundleProducts, entryOwnIds, byProduct, globalBlocker). ThecontextIdsare the bundle's top-level product IDs (EntryToBundleProducts[entry]); theentryOwnIdscome fromentry.Products.Select(p => p.ProductId).ShouldHideEntry: replaced the "any-blocks" loop with a singleGetPublishBlockerForEntrycall, returningblocker?.ShouldBlock(entry) ?? false.GetPublishBlockerForProductmethod.src/services/Elastic.Changelog/Rendering/ChangelogRenderingService.cs:EmitBlockedEntryWarnings: replaced the "any-blocks" loop (which would emit a warning for every product whose rule blocked the entry) with a singlePublishBlockerExtensions.ResolveBlockercall per entry. The resolved blocker is checked once; if it blocks, one warning is emitted without the now-incorrect "for product X" annotation.GetPublishBlockerForProductmethod.tests/Elastic.Changelog.Tests/Changelogs/Render/BlockConfigurationTests.cs— three new tests:RenderChangelogs_WithMultipleProducts_SharedEntry_UsesAlphabeticalFirstMatch— bundle has[elasticsearch, kibana]; a shared entry uses the alphabetically-first (elasticsearch) rule, while a kibana-only entry has no matching rule and stays visible.RenderChangelogs_WithMultipleProducts_SingleProductEntries_UseTheirOwnRules— each single-product entry (elasticsearch, kibana) in a mixed bundle uses only its own per-product rule.RenderChangelogs_WithDisjointBundleAndEntryProducts_FallsBackToGlobalBlocker— when the bundle's products ([kibana]) and the entry's own products ([elasticsearch]) are disjoint, the algorithm falls back to the entry's own product list and then to the global blocker, ensuring that per-product rules for the bundle context don't bleed across to unrelated entries.Documentation:
docs/contribute/changelog.md— added a paragraph to therules.publishsection explaining that the same intersection + alphabetical first-match algorithm applies to per-productrules.publishoverrides, with one key difference: at render time the context comes from the bundle's top-levelproducts:array, not from a CLI flag like--output-products. Links to the existing#changelog-bundle-multi-product-rulesanchor where the algorithm is documented in full.docs/syntax/changelog.md— appended three lines to the "Filtering entries with publish rules" section noting that the directive picks one product's rule via:product:and applies it to everything, while thechangelog rendercommand is what uses the intersection + alphabetical first-match algorithm with the bundle'sproducts:array as context.docs/cli/release/changelog-render.md— extended the existing "block definitions" paragraph with a note coveringrules.publish.products, and linking to the algorithm reference. This is the command reference page users will land on directly, so having the pointer here means they don't have to go digging.Generative AI disclosure
Tool(s) and model(s) used: composer-1.5, claude-4.6-sonnet-medium