feat: migrate to SonarQube 2026.1 LTA#8
Conversation
…yzers Build does NOT compile after this commit — engine 11.x removed org.sonarsource.sonarlint.core.analysis.api.ActiveRule and changed two other signatures. Phase 3 of the LTA migration plan adds the adapter classes; Phase 4 wires them in. This commit is the version checkpoint, intentionally pre-adapter.
Engine 11.3 ships zero references to org.sonar.api.notifications.AnalysisWarnings but the bundled HTML/Java/Python/PHP sensors Spring-autowire it. This is the host-side implementation that lives in the sonar-predictor-host plugin JAR (added in Task 10). Also adds logback-classic 1.5.13 and assertj-core 3.27.7 as test-scope deps required by the ListAppender-based log-capture test.
- language.getPluginKey() -> language.getPlugin().getKey() (11.x rename)
- pass Set.of("sonarpredict-host") to PluginsLoader.load() as the
additionalAllowedPlugins arg, so our host plugin is admitted into
the analysis container's extension scan (belt-and-suspenders; the
isNotSensor disjunct alone is also sufficient — see spec §4.1)
Engine 11.x removed org.sonarsource.sonarlint.core.analysis.api.ActiveRule (the 10.x internal class). The public org.sonar.api.batch.rule.ActiveRule is the replacement; SimpleActiveRule.of(...) builds instances of the public interface in one call.
engine.Issue.getRuleKey() returns org.sonar.api.rule.RuleKey in 11.x (was String in 10.x). Add .toString() at the IssueMapper call site that feeds the protocol's String ruleKey field. This is the third and final adapter required to make the project compile on the LTA 2026.1 toolchain. Also fix AnalysisServiceTest: SonarLanguage.getPluginKey() removed in 11.x; replaced with getPlugin().getKey() via the new SonarPlugin type.
Second maven-jar-plugin execution scoped to the hostplugin package produces target/sonar-predictor-<v>-host.jar in prepare-package. Manifest declares Plugin-Class/Plugin-Key/Sonar-Version so the sonarlint plugin loader treats it identically to a SonarSource analyzer plugin.
… wires Three corrections surfaced by the full 335-test gate (Task 14 of the LTA 2026.1 migration plan); none was caught by the spec's javap analysis: 1. PluginRuntime.loadFrom — second arg to PluginsLoader.load is disabledPluginsForAnalysis, not additionalAllowedPlugins as the spec assumed. Passing "sonarpredict-host" actively EXCLUDED our host plugin from every Spring analysis container, leaving AnalysisWarnings unwired and reproducing the original "wall". Reverted to Set.of(). 2. NoOpAnalysisWarnings @SonarLintSide(lifespan = INSTANCE -> SINGLE_ANALYSIS). The per-analysis AnalysisContainer calls install(ContainerLifespan.ANALYSIS), which matches the SINGLE_ANALYSIS string constant — not INSTANCE. HtmlSensor, the sensor that triggered the original NoSuchBeanDefinitionException, lives in this same container. 3. host-plugin-jar maven execution moved from prepare-package to process-test-classes, plus a maven-antrun copy-host-plugin-for-tests step that seeds the dev plugins/ dir with the host JAR. Required so the surefire-time daemon tests (which use AnalysisService's no-arg ctor = plugins/) can find the host plugin without a full assembly run. HostPluginIntegrationTest refactored to use @tempdir + hardlink-or-copy the vendored analyzer JARs plus the host JAR, filtering out *-host.jar from the vendored glob to avoid a duplicate FileAlreadyExistsException when antrun has already populated plugins/. After these three corrections, full mvn verify reports 335/335 tests passing, JaCoCo report intact, and the unpacked dist bundle analyzes a Java fixture cleanly with zero NoSuchBeanDefinitionException occurrences.
7ed07f2 to
3c1296e
Compare
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
… class files)
LTA 2026.1's sonarlint-analysis-engine is compiled for Java 21. A javac
on JDK 17 cannot read its class files and bails out with:
cannot access org.sonarsource.sonarlint.core.analysis.AnalysisScheduler
bad class file: .../sonarlint-analysis-engine-11.3.0.85510.jar(...)
class file has wrong version 65.0, should be 61.0
The local 335-test gate masked this because the dev machine was on JDK
25. CI on JDK 17 surfaced it on the first push.
Changes:
- pom.xml: maven.compiler.release/source/target 17 -> 21, with comment
documenting the LTA-imposed minimum.
- .github/workflows/{ci,parity,publish,sonar}.yml: setup-java java-version
'17' -> '21' (all four pipelines).
- src/main/staging/bin/sonar: MIN_MAJOR 17 -> 21, renamed is_java_17_plus
-> is_java_min_plus, updated user-facing messages.
- src/main/staging/bin/sonar.bat: matched changes (GEQ 17 -> GEQ 21,
messages).
- README.md: prerequisites table 'Java 17+' -> 'Java 21+'.
…le (3 HIGH)
Socket Security raised three HIGH-severity obfuscatedFile alerts against
ch.qos.logback:{logback-classic,logback-core}:1.5.13 on PR #8. Logback's
optimized class files trip Socket's static-analysis pattern detector;
it's almost certainly a false positive against a widely-trusted library,
but the right answer is to not depend on it from a project that has no
need for a concrete SLF4J binding.
The dep was added by Task 5 (NoOpAnalysisWarnings TDD) solely so the
unit test could capture log output via logback's ListAppender. Two test
sites used logback APIs; both refactored to stay on slf4j-api only:
- NoOpAnalysisWarnings gains a package-private mutable `log` field that
defaults to the static slf4j Logger but can be replaced by tests with
a Mockito-mocked org.slf4j.Logger. The production class still uses
slf4j-api exclusively. NoOpAnalysisWarningsTest now verifies via
verify(logger).warn(...) calls (5 tests, +1 for null-message behavior).
- EngineLog gains a static current() accessor that returns the most
recently installed instance. HostPluginIntegrationTest now reads
EngineLog.current().messages() directly to assert no
NoSuchBeanDefinitionException, instead of capturing via logback's
ROOT logger ListAppender.
pom.xml: ch.qos.logback:logback-classic:1.5.13 dep removed entirely;
mvn dependency:tree confirms logback no longer reaches the test
classpath via any transitive route.
Verified: mvn test = 336/336 pass on the host JDK 21 (was 335; the
refactored NoOpAnalysisWarningsTest gained one additional test for
null-message behavior).
…ld (S3077) SonarCloud's quality gate flagged the volatile EngineLog reference added in the previous commit: java:S3077 — Use a thread-safe type; adding 'volatile' is not enough to make this field thread-safe. Switched to AtomicReference<EngineLog>. The rule's intent is that mutable-state shared between threads should use the j.u.c.atomic types even when each individual read/write is atomic; volatile only handles visibility, not compound operations a future caller might add. Tests unchanged (336/336).
|



Summary
sonarlint-analysis-engine10.24.0.81415 → 11.3.0.85510 and pin the 10 analyzer plugins to their LTA 2026.1-bundled versionssonar-predictor-hostplugin JAR shipped alongside the analyzer JARs in the offline bundle. Registers aNoOpAnalysisWarningsbean the new sensors Spring-autowire — without it, the engine 11.x bump fails withNoSuchBeanDefinitionExceptionSimpleActiveRulerecord,SonarLanguage.getPlugin().getKey()rename,Issue.getRuleKey().toString()pom.xmlso future LTA bumps are pom-onlyDesign
Per the design doc at
docs/superpowers/specs/2026-05-24-sonar-lta-2026.1-migration-design.md(gitignored locally — lives in the worktree). Three-advisor brainstorm (codex / claude / agy) converged on this approach over patched-engine (Codex v1 C) and Byte Buddy premain agent (Agy v1 D) alternatives. Wiring code we own = ~90 LOC across 3 small files + a tiny manifest declaration. No JVM flags, no agents, no vendored modifications to any SonarSource artifact.Critical findings (recorded for future LTA upgrades)
PluginsLoader.load(config, X)'s 2nd arg isdisabledPluginsForAnalysis, NOTadditionalAllowedPluginsas the spec assumed. Using it as an allow-list actually excluded the host plugin from every analysis container. Reverted toSet.of().@SonarLintSide(lifespan = ...)needsSINGLE_ANALYSIS(which maps toContainerLifespan.ANALYSIS) for the per-analysisAnalysisContainerscope, NOTINSTANCE.HtmlSensorand the other autowiring sensors live in that container.process-test-classes+ amaven-antruncopy-host-plugin-for-testsstep to seedplugins/for surefire-time tests. The originalprepare-packagephase missed surefire entirely.Test plan (all verified locally)
mvn clean verifygreen — 335/335 tests pass (323 baseline + 12 new)HostJarManifestTestpins the host JAR's 6 manifest entries + exactly 2 .class filesHostPluginIntegrationTestconfirmsLoadedPluginspicks upsonarpredict-hostwith zeroNoSuchBeanDefinitionExceptionbin/sonaragainst a Java null-deref fixture, S2201 and S1220 caught cleanly, zero missing-bean errors in stderr