Skip to content

Commit 81fde59

Browse files
authored
Merge pull request #2 from brunoborges/brunoborges-fuzzy-journey
Test javac problem matcher through Maven and Gradle builds
2 parents e21b0fe + 22b341f commit 81fde59

16 files changed

Lines changed: 668 additions & 0 deletions

File tree

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
name: javac problem matcher with Maven & Gradle
2+
3+
# The javac problem matcher registered by setup-java (##[add-matcher] java.json)
4+
# only understands javac's *native* diagnostic format:
5+
#
6+
# File.java:12: warning|error: message
7+
#
8+
# (matcher regex, owner=javac: ^([^:]+):(\d+): (warning|error): (.+?)$)
9+
#
10+
# This workflow demonstrates how the two major build tools interact with it:
11+
#
12+
# * Gradle passes javac diagnostics through unchanged, so they DO match the
13+
# matcher and show up as GitHub annotations.
14+
# * The Maven compiler plugin reformats diagnostics to
15+
# [WARNING] /path/File.java:[line,col] message
16+
# which does NOT match the matcher, so Maven builds are NOT annotated even
17+
# though the compiler reports the same warnings/errors.
18+
#
19+
# Each job captures the build log and asserts the number of matcher-format lines,
20+
# so the workflow is self-verifying (not just visual). Open a run and compare the
21+
# Gradle job's Annotations panel (populated) with the Maven job's (empty).
22+
23+
on:
24+
push:
25+
branches: [main]
26+
pull_request:
27+
workflow_dispatch:
28+
29+
permissions:
30+
contents: read
31+
32+
env:
33+
# Exact javac matcher regex from actions/setup-java .github/java.json, as a
34+
# POSIX ERE for grep. [^:]+ = file (no colon), then :line:, then severity.
35+
MATCHER_RE: '^[^:]+:[0-9]+: (warning|error): .+$'
36+
37+
jobs:
38+
gradle-is-annotated:
39+
name: 'Gradle build IS annotated - ${{ matrix.os }}'
40+
runs-on: ${{ matrix.os }}
41+
strategy:
42+
fail-fast: false
43+
matrix:
44+
os: [ubuntu-latest]
45+
steps:
46+
- uses: actions/checkout@v4
47+
- name: Set up Java (registers the javac problem matcher)
48+
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
49+
with:
50+
distribution: temurin
51+
java-version: '21'
52+
53+
- name: Gradle compile with warnings (matcher should annotate them)
54+
working-directory: javac-matcher-gradle
55+
shell: bash
56+
run: |
57+
set -euo pipefail
58+
# compileJava emits warnings but succeeds; tee so the matcher sees the log too.
59+
./gradlew --no-daemon --console=plain clean compileJava 2>&1 | tee warn.log
60+
hits=$(grep -Ec "$MATCHER_RE" warn.log || true)
61+
echo "matcher-format lines: $hits"
62+
if [ "$hits" -lt 1 ]; then
63+
echo "::error::expected Gradle warnings in native javac format (matcher would annotate)"
64+
exit 1
65+
fi
66+
echo "OK: $hits Gradle warning line(s) match the javac matcher -> annotated"
67+
68+
- name: Gradle compile with errors (matcher should annotate them)
69+
id: compile
70+
continue-on-error: true
71+
working-directory: javac-matcher-gradle
72+
shell: bash
73+
run: ./gradlew --no-daemon --console=plain compileErrorsJava 2>&1 | tee err.log
74+
75+
- name: Confirm Gradle errors failed the build and match the matcher
76+
working-directory: javac-matcher-gradle
77+
shell: bash
78+
run: |
79+
set -euo pipefail
80+
echo "compile outcome: ${{ steps.compile.outcome }}"
81+
if [ "${{ steps.compile.outcome }}" != "failure" ]; then
82+
echo "::error::expected Gradle compileErrorsJava to fail"
83+
exit 1
84+
fi
85+
hits=$(grep -Ec "$MATCHER_RE" err.log || true)
86+
echo "matcher-format lines: $hits"
87+
if [ "$hits" -lt 1 ]; then
88+
echo "::error::expected Gradle errors in native javac format (matcher would annotate)"
89+
exit 1
90+
fi
91+
echo "OK: $hits Gradle error line(s) match the javac matcher -> annotated"
92+
93+
maven-is-not-annotated:
94+
name: 'Maven build is NOT annotated - ${{ matrix.os }}'
95+
runs-on: ${{ matrix.os }}
96+
strategy:
97+
fail-fast: false
98+
matrix:
99+
os: [ubuntu-latest]
100+
steps:
101+
- uses: actions/checkout@v4
102+
- name: Set up Java (registers the javac problem matcher)
103+
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5.5.0
104+
with:
105+
distribution: temurin
106+
java-version: '21'
107+
108+
- name: Maven compile with warnings (matcher must NOT annotate them)
109+
working-directory: javac-matcher-maven
110+
shell: bash
111+
run: |
112+
set -euo pipefail
113+
mvn -B clean compile 2>&1 | tee warn.log
114+
matcher=$(grep -Ec "$MATCHER_RE" warn.log || true)
115+
diags=$(grep -Ec '\.java:\[[0-9]+,[0-9]+\]' warn.log || true)
116+
echo "matcher-format lines: $matcher (expect 0), maven [line,col] diagnostics: $diags (expect >0)"
117+
if [ "$diags" -lt 1 ]; then
118+
echo "::error::expected the Maven compiler to report warnings ([WARNING] File.java:[l,c] ...)"
119+
exit 1
120+
fi
121+
if [ "$matcher" -ne 0 ]; then
122+
echo "::error::Maven output unexpectedly matched the javac matcher"
123+
exit 1
124+
fi
125+
echo "OK: Maven reported $diags warning(s), but 0 lines match the matcher -> not annotated"
126+
127+
- name: Maven compile with errors (fails; matcher must NOT annotate them)
128+
id: compile
129+
continue-on-error: true
130+
working-directory: javac-matcher-maven
131+
shell: bash
132+
run: mvn -B -Perrors clean compile 2>&1 | tee err.log
133+
134+
- name: Confirm Maven errors failed the build but were not matcher-annotated
135+
working-directory: javac-matcher-maven
136+
shell: bash
137+
run: |
138+
set -euo pipefail
139+
echo "compile outcome: ${{ steps.compile.outcome }}"
140+
if [ "${{ steps.compile.outcome }}" != "failure" ]; then
141+
echo "::error::expected Maven -Perrors compile to fail"
142+
exit 1
143+
fi
144+
matcher=$(grep -Ec "$MATCHER_RE" err.log || true)
145+
diags=$(grep -Ec '\.java:\[[0-9]+,[0-9]+\]' err.log || true)
146+
echo "matcher-format lines: $matcher (expect 0), maven [line,col] diagnostics: $diags (expect >0)"
147+
if [ "$diags" -lt 1 ]; then
148+
echo "::error::expected the Maven compiler to report errors ([ERROR] File.java:[l,c] ...)"
149+
exit 1
150+
fi
151+
if [ "$matcher" -ne 0 ]; then
152+
echo "::error::Maven error output unexpectedly matched the javac matcher"
153+
exit 1
154+
fi
155+
echo "OK: Maven reported $diags error(s) in the log, but 0 lines match the matcher -> not annotated"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
target/
22
*.class
3+
.gradle/
4+
build/
5+
*.log

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,28 @@ Both are expected to pass: together they document exactly what changed.
3535
- `.github/workflows/` — one workflow per feature, each running on Ubuntu, Windows and macOS.
3636
- `maven-sample-project/` — a tiny Maven project with one external dependency, used by
3737
`maven-args.yml` to prove that transfer-progress logs are suppressed by default.
38+
- `javac-matcher/` — standalone `.java` sources (warnings + errors) compiled directly with
39+
`javac` by `javac-problem-matcher.yml`.
40+
- `javac-matcher-maven/` / `javac-matcher-gradle/` — the same warning/error sources built
41+
through Maven and Gradle, used by `javac-matcher-build-tools.yml` (below).
42+
43+
## javac problem matcher vs build tools
44+
45+
The `javac` problem matcher registered by setup-java only understands javac's **native**
46+
diagnostic format (`File.java:12: warning|error: message`). Whether your build gets
47+
annotated therefore depends on the build tool:
48+
49+
| Build tool | Compiler output | Matched by `javac` matcher? |
50+
|------------|-----------------|-----------------------------|
51+
| Direct `javac` | `File.java:12: warning: …` | ✅ annotated |
52+
| **Gradle** | `File.java:12: warning: …` (passed through) | ✅ annotated |
53+
| **Maven** (compiler plugin) | `[WARNING] /path/File.java:[12,5] …` | ❌ not annotated |
54+
55+
[`javac-matcher-build-tools.yml`](.github/workflows/javac-matcher-build-tools.yml) proves
56+
this by capturing each build log and asserting the number of matcher-format lines (0 for
57+
Maven, >0 for Gradle) — so it fails loudly if the behavior ever changes.
3858

3959
## Running
4060

61+
4162
Push to `main`, open a PR, or trigger any workflow manually via **workflow_dispatch**.

javac-matcher-gradle/build.gradle

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
plugins {
2+
id 'java'
3+
}
4+
5+
// Exercises the javac problem matcher registered by setup-java when the build is
6+
// driven by Gradle. Gradle passes javac diagnostics through in their native form
7+
// "/path/File.java:line: warning|error: message", which the matcher regex
8+
// ^([^:]+):(\d+): (warning|error): (.+?)$ DOES match, so Gradle builds ARE
9+
// annotated. See .github/workflows/javac-matcher-build-tools.yml.
10+
//
11+
// ./gradlew compileJava -> compiles the warning sources (succeeds, warns)
12+
// ./gradlew compileErrorsJava -> compiles the failing sources (fails)
13+
14+
java {
15+
toolchain {
16+
languageVersion = JavaLanguageVersion.of(21)
17+
}
18+
}
19+
20+
sourceSets {
21+
// Failing sources live in their own source set so they can be compiled in a
22+
// dedicated step without breaking the (successful) warning compilation.
23+
errors {
24+
java {
25+
srcDir 'src/errors/java'
26+
}
27+
}
28+
}
29+
30+
tasks.withType(JavaCompile).configureEach {
31+
options.compilerArgs += ['-Xlint:all']
32+
options.deprecation = true
33+
}
47.3 KB
Binary file not shown.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
4+
networkTimeout=10000
5+
retries=0
6+
retryBackOffMs=500
7+
validateDistributionUrl=true
8+
zipStoreBase=GRADLE_USER_HOME
9+
zipStorePath=wrapper/dists

0 commit comments

Comments
 (0)