Skip to content

fix: correct enforceBytecodeVersion excludes filtering - #990

Merged
slawekjaranowski merged 5 commits into
apache:masterfrom
w3lld1:fix/enforce-bytecode-excludes
Sep 14, 2026
Merged

slawekjaranowski merged 5 commits into
apache:masterfrom
w3lld1:fix/enforce-bytecode-excludes

Conversation

@w3lld1

@w3lld1 w3lld1 commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Following this checklist to help us incorporate your contribution quickly and easily:

  • This pull request addresses one issue without unrelated changes.
  • The description explains what the pull request does, how, and why.
  • The commit has a meaningful subject line and body.
  • Regression tests cover the behavioral change.
  • mvn verify passed as part of the command below.
  • Integration tests passed with mvn -Prun-its verify.

Summary

ArtifactMatcher.match() identifies dependencies that are excluded and not restored by an include override. enforceBytecodeVersion previously kept those matches for analysis, reversing the intended filtering behavior.

This change negates that matcher result so excluded dependencies are skipped while explicit includes still override broad exclusions. It adds regression coverage for both excludes-only configuration and include overrides.

Verification

  • mvn -Prun-its verify — passed (151 plugin integration tests and 1 extension integration test; all reactor modules successful)
  • mvn -pl enforcer-rules -am -Dtest=EnforceBytecodeVersionTest -Dsurefire.failIfNoSpecifiedTests=false test — passed (28 tests)
  • git diff --check — passed

Fixes #985

Invert the ArtifactMatcher result so excluded dependencies are skipped while include overrides remain eligible for bytecode checks. Add regression coverage for excludes with and without include overrides.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes enforceBytecodeVersion dependency filtering so that dependencies matching configured excludes are actually skipped from bytecode analysis, while explicit includes continue to override broader excludes (aligning the rule’s filtering with ArtifactMatcher semantics and the documented behavior in the issue).

Changes:

  • Invert ArtifactMatcher.match(...) usage in EnforceBytecodeVersion#filterDependencies(...) so “matched” artifacts are excluded from analysis.
  • Add regression tests covering “excludes-only” filtering and “includes override excludes” behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/EnforceBytecodeVersion.java Fixes filtering predicate so excluded dependencies are not analyzed.
enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/dependency/EnforceBytecodeVersionTest.java Adds targeted regression tests for the excludes/includes filtering behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +82 to +85
Method method = EnforceBytecodeVersion.class.getDeclaredMethod("filterDependencies", List.class);
method.setAccessible(true);
return (List<Dependency>) method.invoke(rule, dependencies);
}

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.

I agree with the diagnosis, but the fix should probably be to use an integration test rather than a unit test.

@elharo elharo 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.

needs an integration test

Signed-off-by: w3lld1 <42353747+w3lld1@users.noreply.github.com>
@w3lld1

w3lld1 commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

Thanks — replaced the reflective unit coverage with the existing integration-test project in 3d8b7108. It now exercises broad exclusion plus an explicit include override through the plugin configuration. The full current CI matrix is green on this head.

if (includes != null || excludes != null) {
ArtifactMatcher artifactMatcher = new ArtifactMatcher(excludes, includes);
includeExcludeMatcher = d -> artifactMatcher.match(ArtifactUtils.toArtifact(d));
includeExcludeMatcher = d -> !artifactMatcher.match(ArtifactUtils.toArtifact(d));

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.

It's not obvious from the code whether the not is needed or not. The word "filter" is ambiguous. It needs comments explaining what is expected that leaves no room for interpretation.

Avoiding lambdas would also make this clearer. As is I can't really tell what it's doing or what it's intended to do which is how we ended up with a bug in the first place.

return new Dependency(new DefaultArtifact(groupId + ":" + artifactId + ":jar:1.0"), "compile");
}

private static void setField(EnforceBytecodeVersion rule, String name, List<String> value) throws Exception {

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.

don't use reflection

Signed-off-by: w3lld1 <42353747+w3lld1@users.noreply.github.com>
@w3lld1

w3lld1 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Thanks — addressed both follow-ups in 49171b5b:

  • replaced the ambiguous negated predicate with an explicit loop that names and skips excluded dependencies, with a comment documenting ArtifactMatcher semantics;
  • removed the reflection-based unit tests; the regression remains covered by the existing integration-test project.

Fresh validation on the pushed commit:

  • focused EnforceBytecodeVersionTest: 26 passed;
  • enforce-bytecode-version-excluded-deps invoker integration test: passed;
  • Checkstyle, Spotless, RAT, and git diff --check: passed.

@elharo elharo 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.

It should be possible to test this with an integration test without using reflection

@w3lld1

w3lld1 commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

The current head already uses the existing invoker integration-test project without reflection. Commit 49171b5b removed the reflective unit tests; maven-enforcer-plugin/src/it/projects/enforce-bytecode-version-excluded-deps/pom.xml now covers both the broad exclusion and explicit include override through plugin configuration. The invoker test and the full CI matrix pass on this head.

@slawekjaranowski

Copy link
Copy Markdown
Member

@elharo please look again

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment on lines 37 to 45
<enforceBytecodeVersion>
<maxJdkVersion>1.5</maxJdkVersion>
<excludes>
<exclude>org.mindrot:jbcrypt:*:*</exclude>
<exclude>*:*</exclude>
</excludes>
<includes>
<include>com.google.code.findbugs:jsr305</include>
</includes>
</enforceBytecodeVersion>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should not change this test .... it should be pass ... but it is wrong

org/mindrot/jbcrypt/BCrypt.class is compiled to JDK 1.5 so test will bass even wrong exclusion ...

we can change

<maxJdkVersion>1.5</maxJdkVersion>

to

<maxJdkVersion>1.4</maxJdkVersion>

@slawekjaranowski slawekjaranowski left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

still fail

@w3lld1

w3lld1 commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks — fixed the integration test in 4b0b810. It now excludes all dependencies at maxJdkVersion 1.4 without an include override. That makes the test fail if exclusion filtering regresses because jbcrypt targets Java 5, while keeping the intended successful-build assertion.

Fresh validation on the pushed commit:

  • mvn -T 2 -Prun-its -pl maven-enforcer-plugin -am -Dinvoker.test=enforce-bytecode-version-excluded-deps -DskipTests verify — BUILD SUCCESS; 1 integration test passed
  • Checkstyle, Spotless, RAT, and git diff --check passed

Signed-off-by: w3lld1 <42353747+w3lld1@users.noreply.github.com>
@w3lld1
w3lld1 force-pushed the fix/enforce-bytecode-excludes branch from 241d311 to 4b0b810 Compare September 2, 2026 15:45
The enforce-bytecode-version-excluded-deps project excluded every
dependency with *:* at maxJdkVersion 1.4, so it passed just as well when
filterDependencies() returned nothing at all.

Narrow the exclude to commons-lang3, the only dependency targeting a JDK
above the threshold, and keep jsr305 as a dependency that is really
analysed and passes.

Add enforce-bytecode-version-included-deps for the case where an include
overrides a wide exclude - there the build has to fail on commons-lang3
alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@slawekjaranowski

Copy link
Copy Markdown
Member

@w3lld1 thanks for contribution, I have added next IT

@slawekjaranowski
slawekjaranowski merged commit 4991d9c into apache:master Sep 14, 2026
17 checks passed
@github-actions github-actions Bot added this to the 3.6.4 milestone Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

enforceBytecodeVersion: exclude is broken without include

4 participants