Skip to content

Strip executable() conditions from consumer POMs - #12874

Open
gnodet wants to merge 1 commit into
masterfrom
implement-12570
Open

Strip executable() conditions from consumer POMs#12874
gnodet wants to merge 1 commit into
masterfrom
implement-12570

Conversation

@gnodet

@gnodet gnodet commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Strips executable() conditions from profile activations during consumer POM building, preventing environment-dependent PATH checks from polluting published artifacts
  • Applies to all three transform paths: transformNonPom, transformBom (via prune()), and transformPom (directly)
  • When no other activation triggers remain after stripping the condition, the activation is removed entirely

Details

The executable() function (added in #12332 / MNG-8768) evaluates against the local system PATH. When such conditions survive into published consumer POMs, downstream consumers silently evaluate them against their own PATH, producing non-reproducible builds.

This PR removes the entire condition string when it contains an executable( call during DefaultConsumerPomBuilder processing, rather than attempting partial expression surgery which could change boolean semantics in unexpected ways.

Test plan

  • 8 new unit tests in ConsumerPomBuilderTest covering:
    • Profile with only executable() activation → activation removed
    • Profile with executable() + other triggers (OS, property) → condition stripped, other triggers preserved
    • Profile without executable() → unchanged
    • Profile with null activation → unchanged
    • Negated executable() (not(executable(...))) → stripped
    • transformNonPom path strips executable conditions
    • transformPom path strips executable conditions
  • All 17 ConsumerPomBuilderTest tests pass (9 existing + 8 new)

Closes #12570

🤖 Generated with Claude Code

The executable() function evaluates against the local system PATH,
making profile activation environment-dependent. When such conditions
survive into published consumer POMs, downstream consumers silently
evaluate them against their own PATH, producing non-reproducible builds.

Strip the entire condition string when it contains an executable() call
during DefaultConsumerPomBuilder processing. This applies to all three
transform paths: transformNonPom and transformBom (via prune()), and
transformPom (directly). When no other activation triggers remain after
stripping, the activation is removed entirely.

Closes #12570

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet gnodet added this to the 4.1.0 milestone Aug 27, 2026
@gnodet
gnodet marked this pull request as ready for review August 28, 2026 08:17

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Correct and well-motivated change that prevents environment-dependent executable() conditions from leaking into published consumer POMs. The implementation covers all three transform paths and the design decision to remove the entire condition string (rather than surgically extracting executable() from compound expressions) is sound.

The condition.contains("executable(") heuristic correctly catches negated forms like not(executable(...)) and compound expressions. All activation fields are covered by isActivationEmpty.

Findings:

  1. Test assertion patterntestTransformNonPomStripsExecutableCondition guards the assertNull check with if (!result.getProfiles().isEmpty()), which silently passes if the profile is unexpectedly removed during pruning. The testTransformPomStripsExecutableCondition test correctly uses assertFalse(result.getProfiles().isEmpty(), ...) before checking the activation — the same pattern should be used here:

    assertFalse(result.getProfiles().isEmpty(),
            "Profile with dependencies should survive pruning");
    assertNull(result.getProfiles().get(0).getActivation(),
            "executable() condition should be stripped");
  2. Missing BOM test (minor) — No test covers the transformBom path with executable() conditions. It shares the same prune() code path, but a dedicated test would confirm end-to-end.

  3. Empty profile survival (minor) — In transformPom, stripExecutableConditions is applied but there's no isEmpty filter afterwards (unlike prune() which does filter). A profile whose sole content was an executable() activation would become id-only after stripping. This is consistent with existing transformPom behavior and the practical impact is negligible.

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

Claude Code on behalf of Guillaume Nodet

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.

Strip executable() conditions from consumer POMs

2 participants