11name : verify
22on :
33 pull_request :
4+
5+ # Code Scanning needs write access to upload SARIF results for inline annotations.
6+ permissions :
7+ contents : read
8+ security-events : write
9+
410jobs :
5- pmd :
11+ # Fast, early-fail lint lane: PMD + Checkstyle (+ CPD). Turns red in a few
12+ # minutes on any violation, independent of the long build below, so a stray
13+ # PMD/Checkstyle issue is reported immediately rather than after `verify`.
14+ #
15+ # `compile` is in the same invocation as the analysis goals: PMD's
16+ # type-resolving rules (e.g. InvalidLogMessageFormat on the SLF4J
17+ # trailing-Throwable idiom) need Tycho's aux-classpath, which a fresh `mvn`
18+ # does not inherit from a prior step's target/classes.
19+ #
20+ # `--fail-never` lets every module produce its report (no Maven cascade-skip),
21+ # so the uploaded SARIF — and therefore the inline annotations — are complete.
22+ # The trade-off: --fail-never suppresses even compile and target-resolution
23+ # failures (mvn exits 0 on a broken build), so each expected SARIF report is
24+ # validated for successful analysis before findings are counted.
25+ # Compilation itself is independently gated by maven-verify.
26+ lint :
627 runs-on : ubuntu-24.04
728 steps :
829 - uses : actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -12,10 +33,96 @@ jobs:
1233 java-version : ' 21'
1334 - name : Set up Workspace Environment Variable
1435 run : echo "WORKSPACE=${{ github.workspace }}" >> $GITHUB_ENV
15- - name : PMD Check
16- run : mvn pmd:pmd pmd:cpd pmd:check pmd:cpd-check -f ./ddk-parent/pom.xml --batch-mode --fail-at-end
17- checkstyle :
36+ - name : Restore Maven dependency cache
37+ # Restore-only, mirroring snapshot.yml's producer cache exactly (path and
38+ # key are hashed into the cache version — see the maven-verify step).
39+ uses : actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
40+ with :
41+ path : ~/.m2/repository
42+ key : ${{ runner.os }}-maven-publish-${{ hashFiles('**/pom.xml', '**/*.target') }}
43+ restore-keys : ${{ runner.os }}-maven-publish-
44+
45+ - name : PMD + Checkstyle reports (SARIF)
46+ # PMD: SarifRenderer FQCN — emits pmd.sarif.json AND keeps pmd.xml.
47+ # Checkstyle: output.format=sarif — SARIF content in checkstyle-result.xml.
48+ # CPD is excluded here: the global -Dformat flag uses PMD's Renderer
49+ # hierarchy and would ClassCastException CPD's CPDReportRenderer.
50+ run : |
51+ mvn -T 2C -f ./ddk-parent/pom.xml --batch-mode --fail-never \
52+ compile \
53+ pmd:pmd checkstyle:checkstyle \
54+ -Dformat=net.sourceforge.pmd.renderers.SarifRenderer \
55+ -Dcheckstyle.output.format=sarif
56+
57+ - name : CPD report (separate invocation — no SARIF support)
58+ # CPD has no SARIF renderer; emits cpd.xml only. Run standalone so the
59+ # PMD -Dformat flag isn't in scope.
60+ # NOTE: the CPD token threshold is governed by pmd.cpd.min in
61+ # ddk-parent/pom.xml.
62+ run : |
63+ mvn -T 2C -f ./ddk-parent/pom.xml --batch-mode --fail-never \
64+ compile \
65+ pmd:cpd-check
66+
67+ - name : Merge per-module SARIFs (PMD + Checkstyle)
68+ if : always()
69+ # Merge only expected module reports into one run per analyzer.
70+ run : |
71+ set -euo pipefail
72+ source .github/scripts/sarif.sh
73+ source_modules=$(sarif_source_modules)
74+ merge_sarif pmd.sarif.json .sarif-merged/pmd.sarif "${LINT_EXPECT_REPORTS:-$source_modules}"
75+ merge_sarif checkstyle-result.xml .sarif-merged/checkstyle.sarif "${LINT_EXPECT_REPORTS:-$source_modules}"
76+
77+ - name : Gate on PMD / CPD / Checkstyle violations
78+ # Require successful reports from every expected module before counting findings.
79+ run : |
80+ set -euo pipefail
81+ source .github/scripts/sarif.sh
82+ source_modules=$(sarif_source_modules)
83+ cpd_reports=()
84+ for mod in ${LINT_EXPECT_REPORTS:-$source_modules}; do
85+ validate_sarif "${mod}/target/pmd.sarif.json"
86+ validate_sarif "${mod}/target/checkstyle-result.xml"
87+ if [ ! -s "${mod}/target/cpd.xml" ]; then
88+ echo "::error::${mod} produced no cpd.xml — a build failure was swallowed by --fail-never."
89+ exit 1
90+ fi
91+ cpd_reports+=("${mod}/target/cpd.xml")
92+ done
93+ for f in .sarif-merged/pmd.sarif .sarif-merged/checkstyle.sarif; do
94+ validate_sarif "$f"
95+ done
96+ if [ ${#cpd_reports[@]} -eq 0 ]; then
97+ echo "::error::No expected CPD reports — the analysis silently failed."
98+ exit 1
99+ fi
100+ sarif_total=$(jq -s '[.[].runs[].results[]] | length' \
101+ .sarif-merged/pmd.sarif .sarif-merged/checkstyle.sarif)
102+ cpd_total=$(awk '/<duplication / {total++} END {print total+0}' "${cpd_reports[@]}")
103+ echo "PMD/Checkstyle SARIF violations: $sarif_total"
104+ echo "CPD duplications: $cpd_total"
105+ if [ "$sarif_total" != "0" ] || [ "$cpd_total" != "0" ]; then
106+ echo "::error::Static analysis found violations (PMD/CPD/Checkstyle)."
107+ exit 1
108+ fi
109+
110+ - name : Upload PMD/Checkstyle SARIF to Code Scanning
111+ if : always()
112+ # Annotation-only, never the gate: a fork PR gets a read-only token and
113+ # upload-sarif 403s, which must not red an otherwise-clean lane.
114+ continue-on-error : true
115+ uses : github/codeql-action/upload-sarif@7fd177fa680c9881b53cdab4d346d32574c9f7f4 # v3.35.4
116+ with :
117+ sarif_file : .sarif-merged
118+ category : lint
119+
120+ # SpotBugs is the slow critical-path analysis (the experiments' durable
121+ # finding), so it runs in its own parallel lane and never delays `lint`.
122+ spotbugs :
18123 runs-on : ubuntu-24.04
124+ env :
125+ MAVEN_OPTS : -Xmx4g
19126 steps :
20127 - uses : actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
21128 - uses : actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
@@ -24,14 +131,69 @@ jobs:
24131 java-version : ' 21'
25132 - name : Set up Workspace Environment Variable
26133 run : echo "WORKSPACE=${{ github.workspace }}" >> $GITHUB_ENV
27- - name : Checkstyle Check
28- run : mvn checkstyle:checkstyle checkstyle:check -f ./ddk-parent/pom.xml --batch-mode --fail-at-end
134+ - name : Restore Maven dependency cache
135+ # Restore-only, mirroring snapshot.yml's producer cache exactly (path and
136+ # key are hashed into the cache version — see the maven-verify step).
137+ uses : actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
138+ with :
139+ path : ~/.m2/repository
140+ key : ${{ runner.os }}-maven-publish-${{ hashFiles('**/pom.xml', '**/*.target') }}
141+ restore-keys : ${{ runner.os }}-maven-publish-
142+
143+ - name : SpotBugs report (SARIF)
144+ # sarifOutput=true emits spotbugsSarif.json (also writes spotbugsXml.xml).
145+ run : |
146+ mvn -T 2C -f ./ddk-parent/pom.xml --batch-mode --fail-never \
147+ compile \
148+ spotbugs:spotbugs \
149+ -Dspotbugs.sarifOutput=true
150+
151+ - name : Merge per-module SpotBugs SARIFs
152+ if : always()
153+ run : |
154+ set -euo pipefail
155+ source .github/scripts/sarif.sh
156+ source_modules=$(sarif_source_modules)
157+ merge_sarif spotbugsSarif.json .sarif-merged/spotbugs.sarif "${SPOTBUGS_EXPECT_REPORTS:-$source_modules}"
158+
159+ - name : Gate on SpotBugs violations
160+ # Require successful reports from every expected module before counting findings.
161+ run : |
162+ set -euo pipefail
163+ source .github/scripts/sarif.sh
164+ source_modules=$(sarif_source_modules)
165+ for mod in ${SPOTBUGS_EXPECT_REPORTS:-$source_modules}; do
166+ validate_sarif "${mod}/target/spotbugsSarif.json"
167+ done
168+ validate_sarif .sarif-merged/spotbugs.sarif
169+ sb_total=$(jq '[.runs[].results[]] | length' .sarif-merged/spotbugs.sarif)
170+ echo "SpotBugs SARIF violations: $sb_total"
171+ if [ "$sb_total" != "0" ]; then
172+ echo "::error::SpotBugs found violations."
173+ exit 1
174+ fi
175+
176+ - name : Upload SpotBugs SARIF to Code Scanning
177+ if : always()
178+ # Annotation-only, never the gate: a fork PR gets a read-only token and
179+ # upload-sarif 403s, which must not red an otherwise-clean lane.
180+ continue-on-error : true
181+ uses : github/codeql-action/upload-sarif@7fd177fa680c9881b53cdab4d346d32574c9f7f4 # v3.35.4
182+ with :
183+ sarif_file : .sarif-merged
184+ category : spotbugs
185+
29186 line-endings :
30187 runs-on : ubuntu-24.04
31188 steps :
32189 - uses : actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
33190 - name : Check LF line endings
34191 run : bash .github/scripts/check-line-endings.sh
192+
193+ # Build + tests only. Static analysis now lives in the `lint` and `spotbugs`
194+ # jobs, so the redundant checkstyle/pmd/spotbugs goals are dropped from here —
195+ # this is the wall-clock long pole and no longer re-runs analysis.
196+ # No `-T 2C`: tests are not known to pass reliably under reactor parallelism.
35197 maven-verify :
36198 runs-on : ubuntu-24.04
37199 steps :
74236 # all downloaded artifacts cached.
75237 run : rm -rf ~/.m2/repository/.cache/tycho/https/dsldevkit.github.io ~/.m2/repository/.cache/tycho/https/ddk.tools.avaloq.com
76238 - name : Build with Maven within a virtual X Server Environment
77- # Run pmd:pmd and pmd:cpd first to generate reports for all modules, then run pmd:check and pmd:cpd-check
78- # This ensures all violations are collected and reported before the build fails
79- run : xvfb-run mvn clean verify checkstyle:check pmd:pmd pmd:cpd pmd:check pmd:cpd-check spotbugs:check -f ./ddk-parent/pom.xml --batch-mode --fail-at-end
239+ run : xvfb-run mvn clean verify -f ./ddk-parent/pom.xml --batch-mode --fail-at-end
80240 - name : Fail on missing surefire reports
81241 if : always()
82242 run : bash .github/scripts/check-surefire-reports.sh
0 commit comments