Skip to content

Commit c2bfe49

Browse files
joaodinissfclaude
andcommitted
ci: pin ddk-target into the scoped reactor and gate on report presence
The target-definition artifact is referenced by target-platform- configuration, not by any bundle MANIFEST, so -am never pulls ddk-target into a scoped reactor. Tycho then falls back to the local-repository copy of the .target, which fails on a cold cache and — worse — silently resolves a stale target definition on a warm one (verified: a June install of the sequenceNumber-29 target still pointed at the 2026-03 release train while the tree's points at 2026-06). The scope script now always prepends ../ddk-target to the -pl list, so the current target definition always comes from the reactor. The gate additionally verifies that every scanned module produced its SARIF (and that a full scan produced any at all): --fail-never swallows even target-resolution failures, so without a presence check a dead build uploads nothing and counts zero violations — a vacuous green. Verified locally against a repository with no installed ddk-target: the previous flags reproduce the resolution failure with zero SARIFs; the pinned reactor analyses the changed module in 34s and resolves the current platform (jdt.core 3.46.0, not the stale 3.45.0). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 922c60a commit c2bfe49

2 files changed

Lines changed: 33 additions & 5 deletions

File tree

.github/scripts/compute-spotbugs-skip.sh

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ while IFS= read -r f; do
3434
case "$f" in
3535
pom.xml | ddk-parent/* | .mvn/* | *.target | .github/* | *[Ss]pot[Bb]ugs*[Ee]xclude*)
3636
echo "Build/config change ($f) -> full SpotBugs scan (no skips)."
37+
if [ -n "${GITHUB_ENV:-}" ]; then
38+
echo "SPOTBUGS_FULL_SCAN=true" >> "$GITHUB_ENV"
39+
fi
3740
exit 0
3841
;;
3942
esac
@@ -64,15 +67,21 @@ inject_skip() {
6467
rm -f "$pom.bak"
6568
}
6669

67-
# 5) Skip every reactor module that was not touched by this PR.
70+
# 5) Skip every reactor module that was not touched by this PR. Kept modules with a
71+
# bundle MANIFEST are expected to produce an analysis report — the gate checks this
72+
# so a swallowed resolution/compile failure can never pass as "nothing to scan".
6873
kept=0
6974
skipped=0
7075
kept_pl=""
76+
expect_reports=""
7177
while IFS= read -r mod; do
7278
[ -n "$mod" ] || continue
7379
if printf '%s\n' "${changed_mods}" | grep -qx "$mod"; then
7480
kept=$((kept + 1))
7581
kept_pl="${kept_pl:+${kept_pl},}../${mod}"
82+
if [ -f "${mod}/META-INF/MANIFEST.MF" ]; then
83+
expect_reports="${expect_reports:+${expect_reports} }${mod}"
84+
fi
7685
else
7786
inject_skip "$mod"
7887
skipped=$((skipped + 1))
@@ -81,11 +90,16 @@ done <<EOF
8190
${module_dirs}
8291
EOF
8392

84-
# 6) Scope the reactor to the changed modules + their upstream dependencies. With no
85-
# changed reactor module (e.g. a docs-only PR) the full reactor builds with every
86-
# analysis skipped — same result, no flags needed.
93+
# 6) Scope the reactor to the changed modules + their upstream dependencies. ddk-target
94+
# is always kept in the -pl list: the target-definition artifact is referenced by
95+
# target-platform-configuration, not by any MANIFEST, so -am never pulls it — without
96+
# it in the reactor Tycho falls back to a local-repository copy, which fails on a
97+
# cold cache and can silently resolve a stale target definition on a warm one.
98+
# With no changed reactor module (e.g. a docs-only PR) the full reactor builds with
99+
# every analysis skipped — same result, no flags needed.
87100
if [ "$kept" -gt 0 ] && [ -n "${GITHUB_ENV:-}" ]; then
88-
echo "SPOTBUGS_SCOPE_ARGS=-pl ${kept_pl} -am" >> "$GITHUB_ENV"
101+
echo "SPOTBUGS_SCOPE_ARGS=-pl ../ddk-target,${kept_pl} -am" >> "$GITHUB_ENV"
102+
echo "SPOTBUGS_EXPECT_REPORTS=${expect_reports}" >> "$GITHUB_ENV"
89103
fi
90104

91105
echo "SpotBugs scope: scanning ${kept} changed module(s), skipping ${skipped} unchanged."

.github/workflows/verify.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,22 @@ jobs:
179179
fi
180180
181181
- name: Gate on SpotBugs violations
182+
# Presence checks close the vacuous-green hole: --fail-never swallows even
183+
# target-platform resolution failures, so "no SARIF produced" must only ever
184+
# mean "every module was skip-injected", never "the build silently died".
182185
run: |
183186
set -eu
187+
for mod in ${SPOTBUGS_EXPECT_REPORTS:-}; do
188+
if [ ! -s "${mod}/target/spotbugsSarif.json" ]; then
189+
echo "::error::${mod} was scanned but produced no SpotBugs SARIF — a build failure was swallowed by --fail-never."
190+
exit 1
191+
fi
192+
done
193+
if [ "${SPOTBUGS_FULL_SCAN:-}" = "true" ] && \
194+
[ "$(find . -path '*/target/spotbugsSarif.json' | wc -l)" -eq 0 ]; then
195+
echo "::error::Full scan produced no SpotBugs SARIFs — a build failure was swallowed by --fail-never."
196+
exit 1
197+
fi
184198
sb_total=$(jq '[.runs[].results[]?] | length' .sarif-merged/spotbugs.sarif 2>/dev/null || echo 0)
185199
echo "SpotBugs SARIF violations: $sb_total"
186200
if [ "$sb_total" != "0" ]; then

0 commit comments

Comments
 (0)