Skip to content

Fix parent profile cache matching across activation contexts - #12762

Open
ulofiai wants to merge 1 commit into
apache:masterfrom
ulofiai:fix/issue-12724
Open

Fix parent profile cache matching across activation contexts#12762
ulofiai wants to merge 1 commit into
apache:masterfrom
ulofiai:fix/issue-12724

Conversation

@ulofiai

@ulofiai ulofiai commented Aug 18, 2026

Copy link
Copy Markdown

Fixes #12724.

Keep every explicitly consulted profile state in DefaultProfileActivationContext.Record, including values that evaluate to false. This prevents an assembled parent model from being reused when a later module has a different -Pprofile or -!profile context.

Add focused regression tests for both active-profile and inactive-profile cache matching.

Signed-off-by: ulofiai <monsterking@tutamail.com>

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent fix, @ulofiai — this is a textbook example of a minimal, well-targeted bug fix with thorough tests.

Why the fix is correct:

The matchesProfiles() method (line 132-135) uses stream().allMatch(), which returns true vacuously on an empty map. The old removeIf(!value) in stop() stripped all false-valued entries, producing an empty map for parents built without any matching active profiles. That empty map then matched every activation context, causing the cache poisoning described in #12724.

By keeping the false entries, allMatch now correctly verifies that profiles which were inactive during caching are also inactive in the current context. The four key combinations all work correctly after this fix:

  • {release=true} vs [release]true==true → match ✅
  • {release=true} vs []true==false → no match ✅
  • {release=false} vs []false==false → match ✅
  • {release=false} vs [release]false==true → no match ✅

No side effects: replayRecordIntoContext() uses putIfAbsent, which correctly handles false entries. No other code depends on Records only containing true entries. The Map.copyOf() immutable copy in the constructor remains intact.

No memory concern: Profile IDs per parent are typically single digits, and the cache stores at most one Record per distinct activation context per parent Source.

Tests are solid — they directly verify the regression with clear assertion messages. One optional future hardening: a multi-profile test (e.g., {release=true, debug=false} not matching {release=true, debug=true}) would cover interactions between entries, but the existing tests nail the core regression.


This review was generated by an AI agent (Claude Code) and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of Guillaume Nodet

gnodet added a commit to gnodet/maven that referenced this pull request Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Profile-injected content from a parent POM is silently dropped in some reactor modules

2 participants