From a809bcf7ff61b115953dc2ea8a9dc9b67cf0edcd Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sun, 24 May 2026 04:31:35 +0000 Subject: [PATCH 1/4] refactor!: collapse 4-module reactor into single Maven project; drop skill+plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Claude Code / Copilot CLI plugin path and the agent skill concept are gone. The reactor (protocol+daemon+cli+dist) is collapsed into one Maven project at root with src/{main,test}/{java,resources}. Distribution is now a single zip shipped on GitHub Release + Maven Central. Deletions plugin/ (.claude-plugin/plugin.json, SKILL.md, bin/sonar copies, config.env, agents/sonar-scanner-{claude,copilot}.md) .claude-plugin/marketplace.json protocol/, daemon/, cli/, dist/ as separate Maven modules — their sources hoist into the single root tree, sub-poms deleted. Source-tree moves (git mv preserves history) protocol/src/main/java/... -> src/main/java/dev/sonarcli/protocol/ daemon/src/main/java/... -> src/main/java/dev/sonarcli/daemon/ cli/src/main/java/... -> src/main/java/dev/sonarcli/cli/ *the same for src/test/java/ daemon/src/test/resources/fixtures/ -> src/test/resources/daemon/fixtures/ cli/src/test/resources/fixtures/ -> src/test/resources/cli/fixtures/ (separated to avoid the Clean.java fixture collision; test FIXTURES paths updated accordingly in 11 test classes) dist/src/assembly/skill.xml -> src/main/assembly/dist.xml (rewritten) dist/src/main/scripts/sonar{,.bat} -> src/main/staging/bin/sonar{,.bat} Build (pom.xml) packaging=jar (so the default lifecycle binds compile/test/jar auto) maven-shade-plugin: two executions producing target/sonar-predictor-cli.jar (Main-Class dev.sonarcli.cli.SonarCommand) target/sonar-predictor-daemon.jar (Main-Class dev.sonarcli.daemon.DaemonMain) maven-dependency-plugin: two executions copy the 10 SonarSource analyzer plugin jars into ./plugins/ (for tests) and target/plugins/ (for assembly) maven-assembly-plugin: produces target/sonar-predictor-dist-${version}.zip with bin/+lib/+plugins/ jacoco: single coverage report at target/site/jacoco/jacoco.xml release profile: source+javadoc jars (Central requirement) + GPG sign + central-publishing-maven-plugin + build-helper attaches the dist zip + src zip with classifiers dist/src. Version bump 0.1.0-SNAPSHOT -> 0.2.0-SNAPSHOT (signals breaking distribution change) CI (.github/workflows) publish.yml: drop the config.env version-pin sync step (no config.env any more), deploy single project, GH Release attaches target/sonar-predictor-dist-${version}.zip sonar.yml + parity.yml: derive version from pom.xml at runtime; point SONAR_PREDICTOR_HOME at target/sonar-predictor-dist-/sonar-predictor; build cmd drops the -pl/-am reactor flags. README rewritten: install via GitHub Release / Maven Central / build from source. Claude Code + Copilot marketplace sections removed. Stale-language sweep: "skill bundle" -> "distribution bundle" / "plugin/engine" -> "analyzer/engine" in DaemonLauncher javadoc, SetupCommand javadoc, bin/sonar + bin/sonar.bat. .gitignore: daemon/plugins/*.jar -> plugins/*.jar Verify mvn -B -ntp clean verify -> BUILD SUCCESS 323 tests pass, 0 failures, 0 errors target/sonar-predictor-dist-0.2.0-SNAPSHOT.zip = 161 MB, 18 entries bin/sonar --help -> exit 0, prints help --- .claude-plugin/marketplace.json | 24 -- .github/workflows/parity.yml | 49 +-- .github/workflows/publish.yml | 63 ++-- .github/workflows/sonar.yml | 68 ++-- .gitignore | 2 +- README.md | 209 ++++++------ cli/pom.xml | 73 ----- daemon/pom.xml | 157 --------- dist/README.md | 80 ----- dist/pom.xml | 178 ----------- dist/src/assembly/skill-zip.xml | 64 ---- dist/src/assembly/skill.xml | 71 ----- dist/src/main/skill/SKILL.md | 18 -- plugin/.claude-plugin/plugin.json | 20 -- plugin/agents/sonar-scanner-claude.md | 83 ----- plugin/agents/sonar-scanner-copilot.md | 83 ----- plugin/skills/sonar-predictor/SKILL.md | 24 -- plugin/skills/sonar-predictor/bin/sonar | 270 ---------------- plugin/skills/sonar-predictor/bin/sonar.bat | 124 -------- plugin/skills/sonar-predictor/config.env | 46 --- pom.xml | 300 ++++++++++++++---- protocol/pom.xml | 27 -- src/main/assembly/dist.xml | 66 ++++ .../java/dev/sonarcli/cli/DaemonClient.java | 0 .../java/dev/sonarcli/cli/DaemonControl.java | 0 .../dev/sonarcli/cli/DaemonException.java | 0 .../java/dev/sonarcli/cli/DaemonLauncher.java | 8 +- .../main/java/dev/sonarcli/cli/DaemonRpc.java | 0 .../java/dev/sonarcli/cli/FileResolver.java | 0 .../java/dev/sonarcli/cli/IssueGrouping.java | 0 .../java/dev/sonarcli/cli/JsonReporter.java | 0 .../sonarcli/cli/LauncherDaemonControl.java | 0 .../main/java/dev/sonarcli/cli/Reporter.java | 0 .../dev/sonarcli/cli/RuleMetadataIndex.java | 0 .../java/dev/sonarcli/cli/SarifReporter.java | 0 .../main/java/dev/sonarcli/cli/Severity.java | 0 .../java/dev/sonarcli/cli/SonarCommand.java | 0 .../java/dev/sonarcli/cli/TextReporter.java | 0 .../cli/coverage/CloverCoverageParser.java | 0 .../cli/coverage/CoberturaCoverageParser.java | 0 .../cli/coverage/CoverageException.java | 0 .../sonarcli/cli/coverage/CoverageFormat.java | 0 .../cli/coverage/CoverageImporter.java | 0 .../sonarcli/cli/coverage/CoverageParser.java | 0 .../sonarcli/cli/coverage/CoverageReport.java | 0 .../sonarcli/cli/coverage/CoverageXml.java | 0 .../sonarcli/cli/coverage/FileCoverage.java | 0 .../cli/coverage/GoCoverageParser.java | 0 .../cli/coverage/JacocoCoverageParser.java | 0 .../cli/coverage/LcovCoverageParser.java | 0 .../cli/coverage/SimpleCovCoverageParser.java | 0 .../sonarcli/cli/setup/DownloadException.java | 0 .../dev/sonarcli/cli/setup/Downloader.java | 0 .../java/dev/sonarcli/cli/setup/Manifest.java | 0 .../sonarcli/cli/setup/PluginProvisioner.java | 0 .../dev/sonarcli/cli/setup/RuntimeLayout.java | 0 .../dev/sonarcli/cli/setup/SetupCommand.java | 4 +- .../dev/sonarcli/cli/setup/SetupRunner.java | 0 .../main/java/dev/sonarcli/cli/setup/Tar.java | 0 .../dev/sonarcli/daemon/AnalysisService.java | 0 .../main/java/dev/sonarcli/daemon/Daemon.java | 0 .../java/dev/sonarcli/daemon/DaemonMain.java | 0 .../dev/sonarcli/daemon/DaemonServer.java | 0 .../dev/sonarcli/daemon/DaemonVersion.java | 0 .../java/dev/sonarcli/daemon/EngineLog.java | 0 .../dev/sonarcli/daemon/FileInputFile.java | 0 .../java/dev/sonarcli/daemon/IssueMapper.java | 0 .../dev/sonarcli/daemon/LanguageDetector.java | 0 .../dev/sonarcli/daemon/PluginRuntime.java | 0 .../java/dev/sonarcli/daemon/PluginsDir.java | 0 .../dev/sonarcli/daemon/QualityProfile.java | 0 .../daemon/QualityProfileException.java | 0 .../sonarcli/daemon/RequestDispatcher.java | 0 .../java/dev/sonarcli/daemon/RuleCatalog.java | 0 .../daemon/RuleParameterDefaults.java | 0 .../dev/sonarcli/daemon/SonarWayProfiles.java | 0 .../dev/sonarcli/daemon/TestPathDetector.java | 0 .../main/java/dev/sonarcli/protocol/Json.java | 0 .../dev/sonarcli/protocol/MessageCodec.java | 0 .../java/dev/sonarcli/protocol/Method.java | 0 .../sonarcli/protocol/ProtocolException.java | 0 .../dev/sonarcli/protocol/SocketPaths.java | 0 .../dev/sonarcli/protocol/WireMessage.java | 0 .../protocol/dto/AnalysisWarning.java | 0 .../sonarcli/protocol/dto/AnalyzeRequest.java | 0 .../protocol/dto/AnalyzeResponse.java | 0 .../java/dev/sonarcli/protocol/dto/Issue.java | 0 .../sonarcli/protocol/dto/PingResponse.java | 0 .../sonarcli/protocol/dto/RuleMetadata.java | 0 {cli/src => src}/main/resources/manifest.json | 0 .../scripts => src/main/staging/bin}/sonar | 4 +- .../main/staging/bin}/sonar.bat | 6 +- .../dev/sonarcli/cli/CliIntegrationTest.java | 2 +- .../java/dev/sonarcli/cli/CommandTest.java | 0 .../dev/sonarcli/cli/CoverageCliTest.java | 2 +- .../dev/sonarcli/cli/DaemonClientTest.java | 2 +- .../dev/sonarcli/cli/DaemonLauncherTest.java | 0 .../dev/sonarcli/cli/FileResolverTest.java | 0 .../test/java/dev/sonarcli/cli/HelpTest.java | 0 .../sonarcli/cli/InstallHookCommandTest.java | 0 .../dev/sonarcli/cli/IssueGroupingTest.java | 0 .../java/dev/sonarcli/cli/ReportersTest.java | 0 .../sonarcli/cli/RuleMetadataIndexTest.java | 0 .../dev/sonarcli/cli/RulesCommandTest.java | 0 .../dev/sonarcli/cli/SarifReporterTest.java | 0 .../coverage/CloverSimplecovParsersTest.java | 2 +- .../cli/coverage/CoverageFormatTest.java | 0 .../cli/coverage/CoverageImporterTest.java | 2 +- .../cli/coverage/TextCoverageParsersTest.java | 2 +- .../cli/coverage/XmlCoverageParsersTest.java | 2 +- .../sonarcli/cli/setup/DownloaderTest.java | 0 .../dev/sonarcli/cli/setup/ManifestTest.java | 0 .../cli/setup/PluginProvisionerTest.java | 0 .../sonarcli/cli/setup/RuntimeLayoutTest.java | 0 .../sonarcli/cli/setup/SetupCommandTest.java | 0 .../dev/sonarcli/cli/setup/TarWriter.java | 0 .../sonarcli/daemon/AnalysisServiceTest.java | 2 +- .../daemon/DaemonIntegrationTest.java | 2 +- .../dev/sonarcli/daemon/DaemonMainTest.java | 0 .../dev/sonarcli/daemon/DaemonServerTest.java | 2 +- .../dev/sonarcli/daemon/EngineLogTest.java | 0 .../sonarcli/daemon/FileInputFileTest.java | 0 .../dev/sonarcli/daemon/IssueMapperTest.java | 0 .../sonarcli/daemon/LanguageDetectorTest.java | 0 .../sonarcli/daemon/PluginRuntimeTest.java | 0 .../dev/sonarcli/daemon/PluginsDirTest.java | 0 .../sonarcli/daemon/QualityProfileTest.java | 0 .../daemon/RequestDispatcherTest.java | 2 +- .../dev/sonarcli/daemon/RuleCatalogTest.java | 0 .../daemon/RuleParameterDefaultsTest.java | 0 .../sonarcli/daemon/SonarWayProfilesTest.java | 0 .../sonarcli/daemon/TestPathDetectorTest.java | 0 .../java/dev/sonarcli/protocol/JsonTest.java | 0 .../protocol/MessageCodecEdgeCasesTest.java | 0 .../sonarcli/protocol/MessageCodecTest.java | 0 .../dev/sonarcli/protocol/MethodTest.java | 0 .../sonarcli/protocol/SocketPathsTest.java | 0 .../sonarcli/protocol/WireMessageTest.java | 0 .../protocol/dto/AnalysisWarningTest.java | 0 .../protocol/dto/AnalyzeRequestTest.java | 0 .../protocol/dto/AnalyzeResponseTest.java | 0 .../dev/sonarcli/protocol/dto/IssueTest.java | 0 .../protocol/dto/PingResponseTest.java | 0 .../protocol/dto/RuleMetadataTest.java | 0 .../cli}/fixtures/coverage/.resultset.json | 0 .../cli}/fixtures/coverage/clover.xml | 0 .../cli}/fixtures/coverage/cobertura.xml | 0 .../cli}/fixtures/coverage/go-cover.out | 0 .../cli}/fixtures/coverage/jacoco.xml | 0 .../cli}/fixtures/coverage/lcov.info | 0 .../resources/cli}/fixtures/java/Clean.java | 0 .../cli}/fixtures/java/ConsolePrinter.java | 0 .../cli}/fixtures/java/UtilityClass.java | 0 .../cli}/fixtures/profiles/only-s1118.xml | 0 .../test/resources/daemon}/fixtures/go/bad.go | 0 .../daemon}/fixtures/go/idiomatic.go | 0 .../daemon}/fixtures/java/Clean.java | 0 .../daemon}/fixtures/java/ConsolePrinter.java | 0 .../daemon}/fixtures/java/UtilityClass.java | 0 .../test/resources/daemon}/fixtures/js/bad.js | 0 .../resources/daemon}/fixtures/python/bad.py | 0 .../test/resources/daemon}/fixtures/ts/bad.ts | 0 162 files changed, 519 insertions(+), 1624 deletions(-) delete mode 100644 .claude-plugin/marketplace.json delete mode 100644 cli/pom.xml delete mode 100644 daemon/pom.xml delete mode 100644 dist/README.md delete mode 100644 dist/pom.xml delete mode 100644 dist/src/assembly/skill-zip.xml delete mode 100644 dist/src/assembly/skill.xml delete mode 100644 dist/src/main/skill/SKILL.md delete mode 100644 plugin/.claude-plugin/plugin.json delete mode 100644 plugin/agents/sonar-scanner-claude.md delete mode 100644 plugin/agents/sonar-scanner-copilot.md delete mode 100644 plugin/skills/sonar-predictor/SKILL.md delete mode 100755 plugin/skills/sonar-predictor/bin/sonar delete mode 100644 plugin/skills/sonar-predictor/bin/sonar.bat delete mode 100644 plugin/skills/sonar-predictor/config.env delete mode 100644 protocol/pom.xml create mode 100644 src/main/assembly/dist.xml rename {cli/src => src}/main/java/dev/sonarcli/cli/DaemonClient.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/DaemonControl.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/DaemonException.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/DaemonLauncher.java (98%) rename {cli/src => src}/main/java/dev/sonarcli/cli/DaemonRpc.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/FileResolver.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/IssueGrouping.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/JsonReporter.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/LauncherDaemonControl.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/Reporter.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/RuleMetadataIndex.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/SarifReporter.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/Severity.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/SonarCommand.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/TextReporter.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/CloverCoverageParser.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/CoberturaCoverageParser.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/CoverageException.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/CoverageFormat.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/CoverageImporter.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/CoverageParser.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/CoverageReport.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/CoverageXml.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/FileCoverage.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/GoCoverageParser.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/JacocoCoverageParser.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/LcovCoverageParser.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/coverage/SimpleCovCoverageParser.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/setup/DownloadException.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/setup/Downloader.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/setup/Manifest.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/setup/PluginProvisioner.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/setup/RuntimeLayout.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/setup/SetupCommand.java (95%) rename {cli/src => src}/main/java/dev/sonarcli/cli/setup/SetupRunner.java (100%) rename {cli/src => src}/main/java/dev/sonarcli/cli/setup/Tar.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/AnalysisService.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/Daemon.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/DaemonMain.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/DaemonServer.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/DaemonVersion.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/EngineLog.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/FileInputFile.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/IssueMapper.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/LanguageDetector.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/PluginRuntime.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/PluginsDir.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/QualityProfile.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/QualityProfileException.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/RequestDispatcher.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/RuleCatalog.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/RuleParameterDefaults.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/SonarWayProfiles.java (100%) rename {daemon/src => src}/main/java/dev/sonarcli/daemon/TestPathDetector.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/Json.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/MessageCodec.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/Method.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/ProtocolException.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/SocketPaths.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/WireMessage.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/dto/AnalysisWarning.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/dto/AnalyzeRequest.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/dto/AnalyzeResponse.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/dto/Issue.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/dto/PingResponse.java (100%) rename {protocol/src => src}/main/java/dev/sonarcli/protocol/dto/RuleMetadata.java (100%) rename {cli/src => src}/main/resources/manifest.json (100%) rename {dist/src/main/scripts => src/main/staging/bin}/sonar (95%) rename {dist/src/main/scripts => src/main/staging/bin}/sonar.bat (91%) rename {cli/src => src}/test/java/dev/sonarcli/cli/CliIntegrationTest.java (99%) rename {cli/src => src}/test/java/dev/sonarcli/cli/CommandTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/CoverageCliTest.java (99%) rename {cli/src => src}/test/java/dev/sonarcli/cli/DaemonClientTest.java (98%) rename {cli/src => src}/test/java/dev/sonarcli/cli/DaemonLauncherTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/FileResolverTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/HelpTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/InstallHookCommandTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/IssueGroupingTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/ReportersTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/RuleMetadataIndexTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/RulesCommandTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/SarifReporterTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/coverage/CloverSimplecovParsersTest.java (98%) rename {cli/src => src}/test/java/dev/sonarcli/cli/coverage/CoverageFormatTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/coverage/CoverageImporterTest.java (98%) rename {cli/src => src}/test/java/dev/sonarcli/cli/coverage/TextCoverageParsersTest.java (98%) rename {cli/src => src}/test/java/dev/sonarcli/cli/coverage/XmlCoverageParsersTest.java (97%) rename {cli/src => src}/test/java/dev/sonarcli/cli/setup/DownloaderTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/setup/ManifestTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/setup/PluginProvisionerTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/setup/RuntimeLayoutTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/setup/SetupCommandTest.java (100%) rename {cli/src => src}/test/java/dev/sonarcli/cli/setup/TarWriter.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/AnalysisServiceTest.java (99%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/DaemonIntegrationTest.java (99%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/DaemonMainTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/DaemonServerTest.java (99%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/EngineLogTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/FileInputFileTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/IssueMapperTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/LanguageDetectorTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/PluginRuntimeTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/PluginsDirTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/QualityProfileTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/RequestDispatcherTest.java (99%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/RuleCatalogTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/RuleParameterDefaultsTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/SonarWayProfilesTest.java (100%) rename {daemon/src => src}/test/java/dev/sonarcli/daemon/TestPathDetectorTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/JsonTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/MessageCodecEdgeCasesTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/MessageCodecTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/MethodTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/SocketPathsTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/WireMessageTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/dto/AnalysisWarningTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/dto/AnalyzeRequestTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/dto/AnalyzeResponseTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/dto/IssueTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/dto/PingResponseTest.java (100%) rename {protocol/src => src}/test/java/dev/sonarcli/protocol/dto/RuleMetadataTest.java (100%) rename {cli/src/test/resources => src/test/resources/cli}/fixtures/coverage/.resultset.json (100%) rename {cli/src/test/resources => src/test/resources/cli}/fixtures/coverage/clover.xml (100%) rename {cli/src/test/resources => src/test/resources/cli}/fixtures/coverage/cobertura.xml (100%) rename {cli/src/test/resources => src/test/resources/cli}/fixtures/coverage/go-cover.out (100%) rename {cli/src/test/resources => src/test/resources/cli}/fixtures/coverage/jacoco.xml (100%) rename {cli/src/test/resources => src/test/resources/cli}/fixtures/coverage/lcov.info (100%) rename {cli/src/test/resources => src/test/resources/cli}/fixtures/java/Clean.java (100%) rename {cli/src/test/resources => src/test/resources/cli}/fixtures/java/ConsolePrinter.java (100%) rename {cli/src/test/resources => src/test/resources/cli}/fixtures/java/UtilityClass.java (100%) rename {cli/src/test/resources => src/test/resources/cli}/fixtures/profiles/only-s1118.xml (100%) rename {daemon/src/test/resources => src/test/resources/daemon}/fixtures/go/bad.go (100%) rename {daemon/src/test/resources => src/test/resources/daemon}/fixtures/go/idiomatic.go (100%) rename {daemon/src/test/resources => src/test/resources/daemon}/fixtures/java/Clean.java (100%) rename {daemon/src/test/resources => src/test/resources/daemon}/fixtures/java/ConsolePrinter.java (100%) rename {daemon/src/test/resources => src/test/resources/daemon}/fixtures/java/UtilityClass.java (100%) rename {daemon/src/test/resources => src/test/resources/daemon}/fixtures/js/bad.js (100%) rename {daemon/src/test/resources => src/test/resources/daemon}/fixtures/python/bad.py (100%) rename {daemon/src/test/resources => src/test/resources/daemon}/fixtures/ts/bad.ts (100%) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json deleted file mode 100644 index 2fecfdd..0000000 --- a/.claude-plugin/marketplace.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "sonar-predict", - "owner": { - "name": "Amit Kumar", - "url": "https://github.com/RandomCodeSpace" - }, - "plugins": [ - { - "name": "sonar-predictor", - "source": "./plugin", - "description": "Offline SonarSource quality gate — runs the genuine SonarSource analyzers locally (no network, no server) to catch bugs, code smells, vulnerabilities and security hotspots. The plugin itself is lightweight (kilobytes); the heavy analyzer bundle is fetched from Maven Central on first invocation and cached locally for every subsequent run.", - "homepage": "https://github.com/RandomCodeSpace/sonar-predict", - "license": "Apache-2.0", - "keywords": [ - "code-quality", - "static-analysis", - "sonarsource", - "linter", - "quality-gate", - "offline" - ] - } - ] -} diff --git a/.github/workflows/parity.yml b/.github/workflows/parity.yml index c92f44b..f3fed7e 100644 --- a/.github/workflows/parity.yml +++ b/.github/workflows/parity.yml @@ -3,11 +3,9 @@ name: Scan parity (self-scan ↔ SonarQube Cloud) # Runs BOTH scans on the same commit and diffs their issue lists. Every PR # answers: "does our daemon find what SonarSource's own pipeline finds?". # -# This workflow supersedes .github/workflows/sonarqube-cloud.yml — that file -# was removed in the same commit; the Cloud scan now happens here, alongside -# the self-scan and the parity comparison. The standalone self-scan -# (sonar.yml) is kept because it works on fork PRs (no SONAR_TOKEN needed), -# whereas this one requires the token and so skips for forks. +# The standalone self-scan (sonar.yml) is kept because it works on fork PRs +# (no SONAR_TOKEN needed), whereas this one requires the token and so skips +# for forks. # # Setup required (one-time, by the repo admin): # 1. Sign in to https://sonarcloud.io with the repo's GitHub org. @@ -41,8 +39,9 @@ jobs: # self-scan workflow still gates fork PRs on our daemon's findings. if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }} env: - # Same dist-assembly heap concern as sonar.yml — 2 GB to keep the - # 150 MB skill-bundle zip step from OOMing maven-assembly-plugin. + # The assembly step packages the ~150 MB distribution bundle (CLI + + # daemon fat jars + 10 analyzer plugins). 2 GB heap keeps maven-assembly-plugin + # from OOMing while it zips the bundle. MAVEN_OPTS: -Xmx2g steps: - name: Checkout @@ -89,24 +88,34 @@ jobs: fi echo "SONAR_TOKEN configured." - # Single build that both scans then consume. `verify` also produces - # the per-module JaCoCo XMLs that both scans use as coverage evidence. - - name: Build and test (generates JaCoCo XML) - run: mvn -B -ntp -pl '!dist' verify -Dsurefire.failIfNoSpecifiedTests=false + # Single build that both scans then consume. `verify` produces the + # JaCoCo XML that both scans use as coverage evidence, plus the + # distribution bundle the self-scan invokes via its bin/sonar launcher. + - name: Build and test (generates JaCoCo XML + distribution bundle) + run: mvn -B -ntp clean verify -Dsurefire.failIfNoSpecifiedTests=false - - name: Build dist (skill bundle for self-scan) - run: mvn -B -ntp -pl dist -am package -DskipTests + # Derive the project version from pom.xml so SONAR_PREDICTOR_HOME below + # tracks pom bumps without anyone touching CI. + - name: Derive project version + id: version + run: | + set -euo pipefail + VERSION=$(mvn -B -ntp -q -DforceStdout help:evaluate -Dexpression=project.version) + if [ -z "${VERSION}" ]; then + echo "::error::could not derive project.version from pom.xml" + exit 1 + fi + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "Project version: ${VERSION}" # --- (A) Self-scan ------------------------------------------------------ - name: Run self-scan run: | set +e - export SONAR_PREDICTOR_HOME="$(pwd)/dist/target/skill/sonar-predictor" - ./plugin/skills/sonar-predictor/bin/sonar agent-scan analyze . \ - --coverage protocol/target/site/jacoco/jacoco.xml \ - --coverage daemon/target/site/jacoco/jacoco.xml \ - --coverage cli/target/site/jacoco/jacoco.xml + export SONAR_PREDICTOR_HOME="$(pwd)/target/sonar-predictor-dist-${{ steps.version.outputs.version }}/sonar-predictor" + "$SONAR_PREDICTOR_HOME/bin/sonar" agent-scan analyze . \ + --coverage target/site/jacoco/jacoco.xml rc=$? set -e echo "Self-scan exit code: $rc (0=clean, 1=issues found, 2+=tool error)" @@ -122,13 +131,13 @@ jobs: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mvn -B -ntp -pl '!dist' \ + mvn -B -ntp \ org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ -Dsonar.projectKey="${SONAR_PROJECT_KEY}" \ -Dsonar.organization="${SONAR_ORGANIZATION}" \ -Dsonar.host.url="${SONAR_HOST_URL}" \ -Dsonar.qualitygate.wait=false \ - -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml,../protocol/target/site/jacoco/jacoco.xml,../daemon/target/site/jacoco/jacoco.xml,../cli/target/site/jacoco/jacoco.xml + -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml # SonarQube Cloud processes the scan asynchronously after upload. Poll # the last completed analysis until the timestamp moves past the start diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 148c5e7..bf15ccc 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,17 +4,17 @@ name: Publish to Maven Central + GitHub Release # from the Actions tab with an explicit version. # # On a run it: -# 1. derives the release version from the tag (v0.1.0 -> 0.1.0) — Maven +# 1. derives the release version from the tag (v0.2.0 -> 0.2.0) — Maven # Central rejects -SNAPSHOT, so versions:set strips it, -# 2. builds, tests, GPG-signs and deploys protocol/daemon/cli to Maven -# Central via the Sonatype Central Portal (the dist module sets -# maven.deploy.skip=true so it is built but never staged), -# 3. creates a GitHub Release carrying two bundles: a whole-repo source -# zip (git archive of HEAD) and the assembled skill bundle zip. The -# plugin itself is installed via the in-repo /plugin/ directory through -# Claude Code's / Copilot CLI's marketplace (see /.claude-plugin/ -# marketplace.json); its skill launcher downloads the analyzer bundle -# on first run from the Maven Central artifact this workflow publishes. +# 2. builds, tests, GPG-signs and deploys the parent pom + attached source +# zip + attached distribution zip to Maven Central via the Sonatype +# Central Portal. This is a single-module project with packaging=pom; +# its deploy attaches: parent pom + source zip (classifier=src) + dist +# zip (classifier=dist). No daemon/cli JARs are published to Central, +# 3. creates a GitHub Release carrying two assets: a whole-repo source +# zip (git archive of HEAD) and the assembled distribution bundle +# (sonar-predictor-dist-.zip — bin/sonar{,.bat} + lib/*.jar + +# plugins/*.jar). Users install by downloading + extracting the zip. # # Required repo secrets: # OSS_NEXUS_USER - Sonatype Central Portal token username @@ -30,7 +30,7 @@ on: workflow_dispatch: inputs: version: - description: 'Release version (e.g. 0.1.0) — required for manual runs' + description: 'Release version (e.g. 0.2.0) — required for manual runs' required: true type: string @@ -75,7 +75,7 @@ jobs: if [ -n "${INPUT_VERSION:-}" ]; then VERSION="${INPUT_VERSION}" else - # github.ref_name is the tag, e.g. v0.1.0 -> 0.1.0 + # github.ref_name is the tag, e.g. v0.2.0 -> 0.2.0 VERSION="${GITHUB_REF_NAME#v}" fi if [ -z "${VERSION}" ]; then @@ -92,18 +92,6 @@ jobs: -DnewVersion="${{ steps.version.outputs.version }}" \ -DgenerateBackupPoms=false - - name: Sync skill bundle version pin to the release version - # The skill launcher reads SONAR_BUNDLE_VERSION from config.env to - # decide which sonar-predictor-dist-.zip to fetch from - # Maven Central on first invocation. If config.env is stale, an - # installed plugin downloads the wrong bundle. Forcing the pin to - # match the tag here removes that trap from every future release. - run: | - set -euo pipefail - CONFIG=plugin/skills/sonar-predictor/config.env - sed -i "s|^SONAR_BUNDLE_VERSION=.*|SONAR_BUNDLE_VERSION=${{ steps.version.outputs.version }}|" "${CONFIG}" - grep '^SONAR_BUNDLE_VERSION' "${CONFIG}" - - name: Build the source bundle (whole-repo git archive of HEAD) # Built BEFORE the deploy: the release profile's build-helper plugin # attaches this zip (from the repo root) to the Maven Central upload, @@ -124,21 +112,7 @@ jobs: MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} run: | set -euo pipefail - mvn -B -ntp -Prelease deploy - - - name: Locate the skill bundle zip - id: bundle - run: | - set -euo pipefail - VERSION="${{ steps.version.outputs.version }}" - SKILL_ZIP="dist/target/sonar-predict-skill-${VERSION}.zip" - if [ ! -f "${SKILL_ZIP}" ]; then - echo "::error::skill bundle not found at ${SKILL_ZIP}" - ls -la dist/target || true - exit 1 - fi - echo "skill_zip=${SKILL_ZIP}" >> "$GITHUB_OUTPUT" - echo "Skill bundle: ${SKILL_ZIP}" + mvn -B -ntp -Prelease clean deploy - name: Create the GitHub Release env: @@ -147,14 +121,19 @@ jobs: set -euo pipefail VERSION="${{ steps.version.outputs.version }}" SRC_ZIP="sonar-predict-${VERSION}-src.zip" - SKILL_ZIP="${{ steps.bundle.outputs.skill_zip }}" + DIST_ZIP="target/sonar-predictor-dist-${VERSION}.zip" + if [ ! -f "${DIST_ZIP}" ]; then + echo "::error::distribution bundle not found at ${DIST_ZIP}" + ls -la target || true + exit 1 + fi if [ -n "${GITHUB_REF_NAME:-}" ] && [ "${GITHUB_REF_TYPE:-}" = "tag" ]; then TAG="${GITHUB_REF_NAME}" else TAG="v${VERSION}" fi gh release create "${TAG}" \ - --title "sonar-predict ${VERSION}" \ + --title "sonar-predictor ${VERSION}" \ --generate-notes \ "${SRC_ZIP}" \ - "${SKILL_ZIP}" + "${DIST_ZIP}" diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 54bb3e0..2173489 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -9,8 +9,9 @@ permissions: # passes through the same gate, so the bar we apply to others applies to us. # # We deliberately do NOT use the previously released bundle from Maven Central. -# SONAR_PREDICTOR_HOME is repointed at dist/target/skill/sonar-predictor so the -# scan exercises the branch's analyzer code, not yesterday's release. +# SONAR_PREDICTOR_HOME is repointed at the freshly-built exploded distribution +# under target/ so the scan exercises this branch's analyzer code, not +# yesterday's release. on: pull_request: @@ -24,11 +25,11 @@ jobs: name: Self-scan runs-on: ubuntu-latest env: - # The dist-assembly step packages the ~150 MB skill bundle (CLI + daemon - # fat jars + 10 analyzer plugins). Maven's default heap is too small for - # that on ubuntu-latest — we'd get 'Execution exception: Java heap space' - # from maven-assembly-plugin:single. 2 GB is plenty and well under the - # runner's ~7 GB available memory. + # The assembly step packages the ~150 MB distribution bundle (CLI + + # daemon fat jars + 10 analyzer plugins). Maven's default heap is too + # small for that on ubuntu-latest — we'd get 'Execution exception: + # Java heap space' from maven-assembly-plugin:single. 2 GB is plenty + # and well under the runner's ~7 GB available memory. MAVEN_OPTS: -Xmx2g steps: # fetch-depth: 0 keeps the full history available so we can switch to @@ -52,9 +53,9 @@ jobs: with: node-version: '20' - # Cache the local Maven repo across runs. Keyed on every pom.xml in the - # tree so a dependency change invalidates cleanly; restore-keys lets a - # partial cache hit still seed most of ~/.m2. + # Cache the local Maven repo across runs. Keyed on the pom.xml so a + # dependency change invalidates cleanly; restore-keys lets a partial + # cache hit still seed most of ~/.m2. - name: Cache Maven repository uses: actions/cache@v4 with: @@ -63,26 +64,33 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - # Build + test the whole reactor except `dist` (the bundle module is - # packaged separately below). `verify` runs the integration tests AND - # produces the JaCoCo XML reports we feed back into the scan as coverage - # evidence. failIfNoSpecifiedTests=false keeps modules with no tests - # from breaking the reactor. - - name: Build and test (generates JaCoCo XML reports) - run: mvn -B -ntp -pl '!dist' verify -Dsurefire.failIfNoSpecifiedTests=false + # Single-module build. `verify` runs the integration tests AND produces + # the JaCoCo XML report we feed back into the scan as coverage evidence, + # plus the distribution bundle the self-scan invokes below. + - name: Build and test (generates JaCoCo XML + distribution bundle) + run: mvn -B -ntp -Dmaven.test.skip=false clean verify -Dsurefire.failIfNoSpecifiedTests=false - # Now build the skill bundle. -am pulls in upstream modules if they - # weren't already installed by the previous step. -DskipTests because - # the tests already ran — re-running them here just wastes minutes. - - name: Build dist (skill bundle this scan will use) - run: mvn -B -ntp -pl dist -am package -DskipTests + # Derive the project version from pom.xml so SONAR_PREDICTOR_HOME below + # tracks pom bumps without anyone touching CI. + - name: Derive project version + id: version + run: | + set -euo pipefail + VERSION=$(mvn -B -ntp -q -DforceStdout help:evaluate -Dexpression=project.version) + if [ -z "${VERSION}" ]; then + echo "::error::could not derive project.version from pom.xml" + exit 1 + fi + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "Project version: ${VERSION}" # The actual self-scan. We override SONAR_PREDICTOR_HOME so the wrapper # script picks up THIS branch's freshly-built daemon jar and analyzer - # plugins, not whatever happens to be installed globally. Three JaCoCo - # XMLs are passed in as coverage evidence — one per Java module that - # produces coverage. agent-scan writes JSON to .sonar-predictor/scan.json - # and prints a human summary on stdout; we want both. + # plugins from the assembly's exploded staging directory, not whatever + # happens to be installed globally. One JaCoCo XML is passed in as + # coverage evidence (single module = one report). agent-scan writes + # JSON to .sonar-predictor/scan.json and prints a human summary on + # stdout; we want both. # # IMPORTANT: the CLI uses three-state exit codes # 0 = clean (no findings at the floor) @@ -95,11 +103,9 @@ jobs: - name: Run self-scan run: | set +e - export SONAR_PREDICTOR_HOME="$(pwd)/dist/target/skill/sonar-predictor" - ./plugin/skills/sonar-predictor/bin/sonar agent-scan analyze . \ - --coverage protocol/target/site/jacoco/jacoco.xml \ - --coverage daemon/target/site/jacoco/jacoco.xml \ - --coverage cli/target/site/jacoco/jacoco.xml + export SONAR_PREDICTOR_HOME="$(pwd)/target/sonar-predictor-dist-${{ steps.version.outputs.version }}/sonar-predictor" + "$SONAR_PREDICTOR_HOME/bin/sonar" agent-scan analyze . \ + --coverage target/site/jacoco/jacoco.xml rc=$? set -e echo "Self-scan exit code: $rc (0=clean, 1=issues found, 2+=tool error)" diff --git a/.gitignore b/.gitignore index c3b257c..a2d54d2 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ dependency-reduced-pom.xml # Analyzer plugin JARs (~160 MB) dropped here for dev runs of the daemon # module. Not committed to keep the repo lean. The distribution build (dist # module) fetches its own copies through Maven and does not use this directory. -daemon/plugins/*.jar +plugins/*.jar # sonar-predictor scan output, written by `bin/sonar agent-scan`. Never commit. .sonar-predictor/ diff --git a/README.md b/README.md index 22ceb01..d2093c6 100644 --- a/README.md +++ b/README.md @@ -1,155 +1,138 @@ -

sonar-predictor

+# sonar-predictor -

- Catch SonarQube-class issues on your machine — before you push.
- An offline static-analysis quality gate that runs the genuine SonarSource analyzers locally, - built for AI agents and humans alike. -

+Offline, no-server, pre-push code-quality gate. Runs the genuine SonarSource analyzers +(the same engines behind SonarQube and SonarLint) entirely on your machine — no account, +no network at analysis time — to catch bugs, code smells, vulnerabilities and security +hotspots before they reach git and the CI round-trip. Scan-only: reads source, never +modifies a file. -

- CI - Maven Central - Release - License -

+## Languages -

- Java 17+ - 12 languages - 100% offline - Agent-native -

+Java, Kotlin, Python, JavaScript, TypeScript, PHP, Ruby, Scala, Go, HTML, XML. ---- +JavaScript / TypeScript analysis additionally requires Node.js 18.17+ on `PATH`; without +it those languages are skipped. -## What it is +## Install -`sonar-predictor` runs the **genuine SonarSource analyzers** — the same engines behind -SonarQube and SonarLint — entirely on your machine, with no server and no network. It's a -fast **pre-push quality gate**: an AI agent (or you) runs it right after writing code, to -catch bugs, code smells, vulnerabilities and security hotspots *before* they reach git and -the slow CI round-trip. +A single zip — `sonar-predictor-dist-0.2.0.zip` — contains everything: launchers +(`bin/sonar`, `bin/sonar.bat`), shaded CLI + daemon jars (`lib/`), and the 10 SonarSource +analyzer plugins (`plugins/`). Pick one route. -It is **scan-only** — it reads your source and reports findings, and never modifies a file. +### Option A: GitHub Release -## Features - -- 🔍 **Genuine SonarSource rules** — embeds `sonarlint-analysis-engine`; the issues match what a SonarQube server would raise. -- 🌐 **100% offline** — no server, no account, no network calls at analysis time. -- ⚡ **Warm daemon** — a long-lived JVM keeps the engine hot; repeat scans are sub-second. -- 🧩 **12 languages** — Java · Kotlin · Python · JavaScript · TypeScript · CSS · PHP · Ruby · Scala · Go · HTML · XML. -- 🤖 **Agent-native** — ships as a self-contained Claude Code skill; machine-readable SARIF and token-lean JSON output. -- 📊 **Coverage import** — JaCoCo, Cobertura, LCOV, Go, Clover, SimpleCov — with a `--coverage-min` gate. -- 🎯 **Quality-profile import** — point `--config profile.xml` at a SonarQube quality profile to match your server's exact ruleset. -- 🚦 **Honest exit codes** — `0` clean · `1` issues found · `2` tool error — drop-in for a git `pre-push` hook. +```bash +curl -LO https://github.com/RandomCodeSpace/sonar-predict/releases/download/v0.2.0/sonar-predictor-dist-0.2.0.zip +unzip sonar-predictor-dist-0.2.0.zip +./sonar-predictor/bin/sonar --help +``` -## Quick start +Or grab the asset by hand from +. -`sonar-predictor` installs as a Claude Code / GitHub Copilot CLI plugin from this repo's built-in marketplace. The plugin is tiny (kilobytes); the analyzer bundle is fetched lazily from Maven Central on first scan and cached locally for every subsequent run. +### Option B: Maven Central -``` -/plugin marketplace add RandomCodeSpace/sonar-predict -/plugin install sonar-predictor@sonar-predict +```bash +mvn dependency:get \ + -Dartifact=io.github.randomcodespace.sonarpredict:sonar-predictor:0.2.0:zip:dist \ + -Dtransitive=false +unzip ~/.m2/repository/io/github/randomcodespace/sonarpredict/sonar-predictor/0.2.0/sonar-predictor-0.2.0-dist.zip +./sonar-predictor/bin/sonar --help ``` -The same two commands work on Claude Code and Copilot CLI — they share the `.claude-plugin` format. Two named scanner subagents come with the plugin: `sonar-scanner-claude` (model: haiku) and `sonar-scanner-copilot` (model: gpt-5-mini); selection is by agent name. +### Option C: Build from source -Prefer the raw CLI? Grab the skill bundle directly from the [latest release](https://github.com/RandomCodeSpace/sonar-predict/releases/latest) and run `./bin/sonar` from the unpacked directory. The first invocation auto-discovers Java 17+ (or downloads one if none is found); every subsequent call is offline. +```bash +git clone https://github.com/RandomCodeSpace/sonar-predict.git +cd sonar-predict +mvn -B clean package +# output: target/sonar-predictor-dist-0.2.0-SNAPSHOT.zip +``` ## Usage -```sh -sonar check ... # check specific files -sonar check --diff [ref] # check only the current git changeset (the agent path) -sonar analyze # scan a whole project -sonar rules show java:S1118 # full metadata for a rule -sonar install-hook # wire it as a git pre-push hook -sonar --help # the complete command reference -``` +```bash +# Analyze the current git changeset (the agent / pre-push workflow) +./bin/sonar check --diff --format json -Pick the output with `--format sarif|json|text` (SARIF is the default). Add -`--config ` to analyze with an imported SonarQube quality profile, or -`--coverage ` to fold in a coverage report. +# Analyze explicit files +./bin/sonar check path/to/file.java path/to/other.py --format json -```sh -sonar --format json check --diff -sonar --coverage target/site/jacoco/jacoco.xml --coverage-min 80 analyze . +# Analyze a whole directory +./bin/sonar analyze /path/to/project --format json ``` -## Corporate / air-gapped setup +Output formats: `--format sarif|json|text` (SARIF is the default). Add `--config +` to use an imported SonarQube quality profile, or `--coverage ` +(plus `--coverage-min N`) to fold in a JaCoCo / Cobertura / LCOV / Go / Clover / +SimpleCov coverage report. -The plugin's launcher reads a single configuration file at `plugin/skills/sonar-predictor/config.env`. Edit it (or set the same-named environment variable, which takes precedence) to point at a corporate Maven proxy, a private JRE mirror, or a vendored bundle version — no code changes. +## Exit codes -| Key | What it controls | -|-----|------------------| -| `SONAR_MAVEN_REPO_URL` | Where the analyzer bundle is downloaded from. Default: Maven Central. | -| `SONAR_BUNDLE_VERSION` | Bundle version pin. Bump in lockstep with each plugin release. | -| `SONAR_MIN_JAVA_VERSION` | Minimum Java major version required. Default: `17`. | -| `SONAR_JRE_URL_TEMPLATE` | JRE source for auto-download (when none is on the system). Tokens `{os}` `{arch}` `{version}` are substituted at runtime. Default: Adoptium Temurin API. | -| `SONAR_JRE_VERSION` | JRE version to fetch. Default: `17`. | -| `SONAR_DISABLE_JRE_AUTODOWNLOAD` | Set to `1` to refuse the JRE auto-download (corp-policy escape hatch). | +| Code | Meaning | +|------|---------| +| `0` | clean — no issues | +| `1` | issues found | +| `2` | tool error | -For a fully pre-staged install — no network at all on the developer machine — extract a skill bundle by hand into a known location and point the launcher at it: +Drop-in for a git `pre-push` hook; `sonar install-hook` wires one up for you. -```sh -export SONAR_PREDICTOR_HOME=/opt/sonar-predictor -``` +## How it works -The forking workflow: clone this repo, edit `plugin/skills/sonar-predictor/config.env`, push to your fork, `/plugin marketplace add /sonar-predict`. One file. +A short-lived `sonar` CLI talks to a long-lived analysis daemon over a local Unix +domain socket. The daemon keeps the SonarLint analysis engine and analyzer plugins +warm, so the first call costs a few seconds and every call after is sub-second. The +daemon exits on its own after 50 minutes idle. -## How it works +## Triage guidance -``` - sonar (thin CLI) ──local Unix socket──▶ sonar-daemon (long-lived JVM) - args · diff detection embeds sonarlint-analysis-engine - output formatting loads the 12 analyzer plugins -``` +When `check` reports findings, fix in this order: -A short-lived `sonar` CLI talks to a long-lived analysis **daemon** over a local Unix domain -socket. The daemon keeps the SonarSource engine and analyzer plugins **warm**, so the first -call costs a few seconds and every call after is sub-second. The daemon exits on its own -after 50 minutes idle. +1. **Type** — `BUG` and `VULNERABILITY` first, then `SECURITY_HOTSPOT`, then + `CODE_SMELL`. +2. **Severity** — within a type, fix `CRITICAL` and `MAJOR` before `MINOR` / `INFO`. + +The JSON output carries both fields on every issue. ## Prerequisites | Requirement | For | |---|---| -| **Java 17+** (JDK or JRE) | running the CLI and daemon — auto-discovered | -| **Linux or macOS** | the daemon uses Unix domain sockets (Windows support is in progress) | +| **Java 17+** (JDK or JRE) | running the CLI and daemon — auto-discovered (`JAVA_HOME` → `PATH` → common install locations) | +| **Linux or macOS** | the daemon uses Unix domain sockets (Windows support is on the roadmap) | | **`git`** | the `check --diff` workflow | -| **Node.js 18.17+** | JavaScript / TypeScript / CSS analysis | - -Nothing is downloaded at analysis time — the tool is fully offline once the bundle is unzipped. - -## Build from source +| **Node.js 18.17+** | JavaScript / TypeScript analysis | +| **~1 GB RAM, ~165 MB disk** | the daemon embeds the analysis engine | -```sh -git clone https://github.com/RandomCodeSpace/sonar-predict.git -cd sonar-predict -mvn package -# self-contained skill bundle → dist/target/skill/sonar-predictor/ -``` - -A Maven multi-module build (Java 17): `protocol` (wire DTOs), `daemon` (analysis engine host), -`cli` (the `sonar` command), `dist` (the skill bundle). The library modules are published to -Maven Central under `io.github.randomcodespace.sonarpredict`. +Nothing is downloaded at analysis time — the tool is fully offline once the zip is +unpacked. ## Scope -`sonar-predictor` predicts the **rule-based** findings of a SonarQube server — bugs, code -smells, vulnerabilities and security hotspots — and imports coverage. It is a fast local -first-pass, **not** a replacement for release-time gates: the SonarQube server's deep -cross-file taint analysis, Fortify, and dependency/CVE scanning remain their own tools. +`sonar-predictor` predicts the **rule-based** findings of a SonarQube server — bugs, +code smells, vulnerabilities and security hotspots — and imports coverage. It is a fast +local first-pass, **not** a replacement for release-time gates: the server's deep +cross-file taint analysis, Fortify, and dependency / CVE scanning remain their own +tools. ## License & third-party components -This project (the CLI, daemon, protocol, dist module, plugin scaffolding) is licensed under the [Apache License 2.0](LICENSE). - -The SonarSource analyzers and engine that `sonar-predictor` invokes at runtime are **third-party components with their own licenses**, listed in [NOTICE](NOTICE). Headline points: - -- **`sonarlint-analysis-engine`** (the embedded analysis runtime, by SonarSource) — **LGPL v3**. -- **SonarSource language analyzers** (`sonar-java`, `sonar-python`, `sonar-javascript`, `sonar-php`, `sonar-kotlin`, `sonar-go`, `sonar-ruby`, `sonar-scala`, `sonar-html`, `sonar-xml`) — **SONAR Source-Available License v1.0 (SSALv1)** since SonarSource's 2024 license change. Source-available, free for internal use, with restrictions on operating a competing "Service Offering". - -The plugin **does not redistribute** these JARs — its launcher fetches them from Maven Central on first invocation (the same channel SonarSource themselves publish to). Editing `SONAR_MAVEN_REPO_URL` to a corporate mirror that proxies Maven Central is equivalent. None of this project's source code is derived from SonarSource code. - -For a deeper inventory and the legal text of each license, see [NOTICE](NOTICE). If your environment's policy needs the analyzer JARs to come from somewhere other than Maven Central, the corporate / air-gapped setup above is your knob. +This project's source (CLI, daemon, build) is licensed under the +[Apache License 2.0](LICENSE). + +The SonarSource analyzers and engine that `sonar-predictor` invokes at runtime are +third-party components with their own licenses, listed in [NOTICE](NOTICE). Headline +points: + +- **`sonarlint-analysis-engine`** (the embedded analysis runtime, by SonarSource) — + **LGPL v3**. +- **SonarSource language analyzers** (`sonar-java`, `sonar-python`, + `sonar-javascript`, `sonar-php`, `sonar-kotlin`, `sonar-go`, `sonar-ruby`, + `sonar-scala`, `sonar-html`, `sonar-xml`) — **SONAR Source-Available License v1.0 + (SSALv1)** since SonarSource's 2024 license change. Source-available, free for + internal use, with restrictions on operating a competing "Service Offering". + +These JARs are redistributed unchanged inside the `plugins/` directory of the +distribution zip, fetched from Maven Central at build time. None of this project's +source code is derived from SonarSource code. For the legal text of each license, see +[NOTICE](NOTICE). diff --git a/cli/pom.xml b/cli/pom.xml deleted file mode 100644 index d432c40..0000000 --- a/cli/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - 4.0.0 - - - io.github.randomcodespace.sonarpredict - sonar-predictor-parent - 0.1.0-SNAPSHOT - - - sonar-predictor-cli - sonar-predictor :: cli - - - - - io.github.randomcodespace.sonarpredict - sonar-predictor-protocol - 0.1.0-SNAPSHOT - - - info.picocli - picocli - - - org.junit.jupiter - junit-jupiter - test - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.3 - - - package - shade - - - - dev.sonarcli.cli.SonarCommand - - ${project.version} - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - diff --git a/daemon/pom.xml b/daemon/pom.xml deleted file mode 100644 index dfbbf8d..0000000 --- a/daemon/pom.xml +++ /dev/null @@ -1,157 +0,0 @@ - - - 4.0.0 - - - io.github.randomcodespace.sonarpredict - sonar-predictor-parent - 0.1.0-SNAPSHOT - - - sonar-predictor-daemon - sonar-predictor :: daemon - - - - io.github.randomcodespace.sonarpredict - sonar-predictor-protocol - 0.1.0-SNAPSHOT - - - org.sonarsource.sonarlint.core - sonarlint-analysis-engine - - - org.junit.jupiter - junit-jupiter - test - - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.8.1 - - - copy-analyzer-plugins - process-test-resources - copy - - ${project.basedir}/plugins - false - - - org.sonarsource.java - sonar-java-plugin - ${sonar.plugin.java.version} - jar - - - org.sonarsource.python - sonar-python-plugin - ${sonar.plugin.python.version} - jar - - - org.sonarsource.javascript - sonar-javascript-plugin - ${sonar.plugin.javascript.version} - jar - - - org.sonarsource.php - sonar-php-plugin - ${sonar.plugin.php.version} - jar - - - org.sonarsource.kotlin - sonar-kotlin-plugin - ${sonar.plugin.kotlin.version} - jar - - - org.sonarsource.slang - sonar-go-plugin - ${sonar.plugin.go.version} - jar - - - org.sonarsource.slang - sonar-ruby-plugin - ${sonar.plugin.ruby.version} - jar - - - org.sonarsource.slang - sonar-scala-plugin - ${sonar.plugin.scala.version} - jar - - - org.sonarsource.html - sonar-html-plugin - ${sonar.plugin.html.version} - jar - - - org.sonarsource.xml - sonar-xml-plugin - ${sonar.plugin.xml.version} - jar - - - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.3 - - - package - shade - - - - dev.sonarcli.daemon.DaemonMain - - - ${project.version} - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - diff --git a/dist/README.md b/dist/README.md deleted file mode 100644 index 66ba386..0000000 --- a/dist/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# sonar-predictor :: dist - -The distribution module. It assembles the **skill bundle** that `sonar-predictor`'s plugin launcher downloads at first run. - -## What this module builds - -```sh -mvn package -``` - -produces, under `dist/target/`: - -- `skill/sonar-predictor/` — the exploded skill bundle: - - `SKILL.md` — the agent-facing skill definition - - `bin/sonar`, `bin/sonar.bat` — launchers that auto-discover a Java 17+ runtime - - `lib/` — the CLI and daemon shaded fat jars - - `plugins/` — the 10 SonarSource analyzer plugins -- `sonar-predict-skill-.zip` — the same tree zipped, attached to the GitHub Release and **published to Maven Central as `io.github.randomcodespace.sonarpredict:sonar-predictor-dist::zip`**. The plugin's bootstrap launcher pulls this artifact (from Maven Central, or a corporate proxy of it) on first invocation. - -The analyzer plugins are resolved through Maven, so any mirror, Nexus, or corporate proxy configured in your `settings.xml` is honored — there are no hardcoded download URLs in the build. - -## How users install `sonar-predictor` - -End users do not interact with this module directly. They install the plugin from the in-repo `/plugin/` directory through their AI tool's marketplace: - -``` -/plugin marketplace add RandomCodeSpace/sonar-predict -/plugin install sonar-predictor@sonar-predict -``` - -The plugin's launcher (`/plugin/skills/sonar-predictor/bin/sonar`) downloads the bundle this module builds from Maven Central, verifies its SHA-1, caches it under `~/.cache/sonar-predictor//`, and execs the cached `bin/sonar` on every subsequent call. - -For raw / non-plugin use (manual or air-gapped install), the same skill bundle zip is attached to each GitHub Release. - -## Prerequisites at runtime - -**Required:** -- **Java 17+** (JDK or JRE) — the CLI and daemon are JVM processes. `bin/sonar` auto-discovers it (`JAVA_HOME` → `PATH` → common install locations); the plugin's bootstrap also auto-downloads one from `SONAR_JRE_URL_TEMPLATE` (defaulting to Adoptium Temurin) if none is found. -- **Linux or macOS** — the daemon uses Unix domain sockets. Windows is not yet supported (the TCP-socket fallback is a TODO). -- A writable temp directory and ~1 GB free RAM (the daemon embeds the analysis engine; idle ~150–350 MB, up to ~1 GB during JS/TS analysis). -- ~165 MB disk for the bundle. - -**For specific features:** -- **`git`** on `PATH` — required for `sonar check --diff` (the primary agent workflow). -- **Node.js 18.17+** on `PATH` — required for JavaScript/TypeScript/CSS analysis. Without it those 3 languages are skipped. - -**Not required after first invocation:** no network, no per-language SDK or compiler, no Maven. - -## Releasing - -A release is cut by pushing a version tag. The `.github/workflows/publish.yml` GitHub Actions pipeline then: - -1. derives the release version from the tag (`v0.1.0` → `0.1.0`) and strips `-SNAPSHOT`, -2. builds, tests, GPG-signs and deploys the library modules `protocol`, `daemon` and `cli` to Maven Central via the Sonatype Central Portal, -3. publishes this `dist` module's skill bundle zip to Maven Central as `sonar-predictor-dist::zip` (this is the artifact the plugin's bootstrap downloads), -4. creates a GitHub Release carrying two bundles: - - `sonar-predict--src.zip` — the whole repository as a `git archive` of `HEAD`, - - `sonar-predict-skill-.zip` — the assembled skill bundle. - -To cut release `X.Y.Z`: - -```sh -git tag vX.Y.Z -git push origin vX.Y.Z -``` - -When the release is cut, bump the plugin launcher's pinned bundle version in `plugin/skills/sonar-predictor/config.env` (`SONAR_BUNDLE_VERSION`) in the same commit, so a freshly installed plugin downloads the bundle that matches it. - -The workflow can also be run manually from the **Actions** tab (`workflow_dispatch`), supplying the version explicitly. - -### Required repository secrets - -| Secret | Purpose | -|--------|---------| -| `OSS_NEXUS_USER` | Sonatype Central Portal token username | -| `OSS_NEXUS_PASS` | Sonatype Central Portal token password | -| `MAVEN_GPG_PRIVATE_KEY` | ASCII-armored GPG private key used to sign artifacts | -| `MAVEN_GPG_PASSPHRASE` | Passphrase for that GPG key (omit if the key has none) | - -`GITHUB_TOKEN` is provided automatically. The `io.github.randomcodespace` namespace must be registered and verified on the Sonatype Central Portal. diff --git a/dist/pom.xml b/dist/pom.xml deleted file mode 100644 index c5bc100..0000000 --- a/dist/pom.xml +++ /dev/null @@ -1,178 +0,0 @@ - - - 4.0.0 - - - io.github.randomcodespace.sonarpredict - sonar-predictor-parent - 0.1.0-SNAPSHOT - - - sonar-predictor-dist - sonar-predictor :: dist - - - - - - - io.github.randomcodespace.sonarpredict - sonar-predictor-cli - ${project.version} - - - io.github.randomcodespace.sonarpredict - sonar-predictor-daemon - ${project.version} - - - - - - true - true - true - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.8.1 - - - copy-analyzer-plugins - prepare-package - copy - - ${project.build.directory}/plugins - false - - - org.sonarsource.java - sonar-java-plugin - ${sonar.plugin.java.version} - jar - - - org.sonarsource.python - sonar-python-plugin - ${sonar.plugin.python.version} - jar - - - org.sonarsource.javascript - sonar-javascript-plugin - ${sonar.plugin.javascript.version} - jar - - - org.sonarsource.php - sonar-php-plugin - ${sonar.plugin.php.version} - jar - - - org.sonarsource.kotlin - sonar-kotlin-plugin - ${sonar.plugin.kotlin.version} - jar - - - org.sonarsource.slang - sonar-go-plugin - ${sonar.plugin.go.version} - jar - - - org.sonarsource.slang - sonar-ruby-plugin - ${sonar.plugin.ruby.version} - jar - - - org.sonarsource.slang - sonar-scala-plugin - ${sonar.plugin.scala.version} - jar - - - org.sonarsource.html - sonar-html-plugin - ${sonar.plugin.html.version} - jar - - - org.sonarsource.xml - sonar-xml-plugin - ${sonar.plugin.xml.version} - jar - - - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.7.1 - - - - build-skill-dir - package - single - - false - skill - - src/assembly/skill.xml - - - - - - build-skill-zip - package - single - - false - sonar-predict-skill-${project.version} - - src/assembly/skill-zip.xml - - - - - - - - diff --git a/dist/src/assembly/skill-zip.xml b/dist/src/assembly/skill-zip.xml deleted file mode 100644 index 784f32f..0000000 --- a/dist/src/assembly/skill-zip.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - skill-zip - - - - zip - - - sonar-predictor - true - - - - ${project.basedir}/src/main/skill - . - - SKILL.md - - - - ${project.basedir}/src/main/scripts - bin - - sonar - - 0755 - - - ${project.basedir}/src/main/scripts - bin - - sonar.bat - - 0644 - - - ${project.build.directory}/plugins - plugins - - *.jar - - - - - - - lib - false - false - ${artifact.artifactId}.jar - - io.github.randomcodespace.sonarpredict:sonar-predictor-cli - io.github.randomcodespace.sonarpredict:sonar-predictor-daemon - - - - diff --git a/dist/src/assembly/skill.xml b/dist/src/assembly/skill.xml deleted file mode 100644 index 66686e4..0000000 --- a/dist/src/assembly/skill.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - skill-dir - - - - dir - - - sonar-predictor - true - - - - - ${project.basedir}/src/main/skill - . - - SKILL.md - - - - - - ${project.basedir}/src/main/scripts - bin - - sonar - - 0755 - - - ${project.basedir}/src/main/scripts - bin - - sonar.bat - - 0644 - - - - - ${project.build.directory}/plugins - plugins - - *.jar - - - - - - - - lib - false - false - ${artifact.artifactId}.jar - - io.github.randomcodespace.sonarpredict:sonar-predictor-cli - io.github.randomcodespace.sonarpredict:sonar-predictor-daemon - - - - diff --git a/dist/src/main/skill/SKILL.md b/dist/src/main/skill/SKILL.md deleted file mode 100644 index fd65439..0000000 --- a/dist/src/main/skill/SKILL.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -name: sonar-predictor -description: Use after writing or modifying source code, before committing or pushing — runs genuine SonarSource analyzers offline as a fast local quality gate to catch bugs, code smells, vulnerabilities and security hotspots. Also use when the user asks to check code quality, run sonar, or analyze a file or diff. ---- - -# sonar-predictor - -An offline SonarSource pre-push quality gate — runs the genuine analyzers locally, no network, no server. - -**Scan-only.** This skill only *scans and reports* — it reads source and emits findings, and never modifies any file. Applying fixes is the calling agent's job, not this tool's; running it is a safe, read-only operation. - -Run `./bin/sonar` from this skill's base directory (the folder with this `SKILL.md`), or by its absolute path — it is not on `PATH`. **Read the tool's own help before invoking it:** `./bin/sonar --help` lists the commands and the global options, and `./bin/sonar --help` gives a command's own options and exact argument order. The skill scans a git changeset or explicit files and directories and reports in a chosen format — the help states the precise flags and where each one goes. That generated help is the single source of truth; this `SKILL.md` deliberately does not restate command syntax, which would drift. Do not guess flag names or their placement — read the help. - -Exit codes: `0` clean, `1` issues found, `2` tool error. - -Acting on findings: fix `BUG`/`VULNERABILITY`/`SECURITY_HOTSPOT` and `CRITICAL`/`MAJOR` first. This is a fast first-pass gate, not the release gate — fix the real issues and move on. - -**Plugin-bundled agent variants.** When this skill ships inside the `sonar-predictor` plugin, two named scanner subagents come with it: invoke `sonar-scanner-claude` on Claude Code (model: haiku) or `sonar-scanner-copilot` on GitHub Copilot CLI (model: gpt-5-mini). Selection is by agent name — pick the one matching your platform. diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json deleted file mode 100644 index 74286f7..0000000 --- a/plugin/.claude-plugin/plugin.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "sonar-predictor", - "version": "0.1.3", - "description": "Offline SonarSource quality gate — runs the genuine SonarSource analyzers locally (no network, no server) to catch bugs, code smells, vulnerabilities and security hotspots. Ships two named scanner agent variants (sonar-scanner-claude on Claude Code, sonar-scanner-copilot on GitHub Copilot CLI) and a thin sonar-predictor skill whose launcher fetches the analyzer bundle (~150 MB) from Maven Central on first invocation and caches it for every subsequent run.", - "author": { - "name": "Amit Kumar", - "url": "https://github.com/RandomCodeSpace" - }, - "homepage": "https://github.com/RandomCodeSpace/sonar-predict", - "repository": "https://github.com/RandomCodeSpace/sonar-predict", - "license": "Apache-2.0", - "keywords": [ - "code-quality", - "static-analysis", - "sonarsource", - "linter", - "quality-gate", - "offline" - ] -} diff --git a/plugin/agents/sonar-scanner-claude.md b/plugin/agents/sonar-scanner-claude.md deleted file mode 100644 index b3e3f7f..0000000 --- a/plugin/agents/sonar-scanner-claude.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -name: sonar-scanner-claude -description: Claude-Code variant of the sonar-scanner agent. Mechanical offline code-quality scanner — invokes the sonar-predictor skill over an assigned directory, repository, file list, or git changeset and returns a concise findings summary. Scan-only; never edits code. Built to be fanned out as parallel instances (one per module or repo) on a cheap model, keeping raw analyzer output out of the orchestrator's context. -model: haiku -tools: Bash, Read, Glob, Skill ---- - -You are a mechanical code-quality scanner. You invoke the `sonar-predictor` -skill over the scope you are given and report what it found. You never modify -code and never apply fixes — scan and summarize only. The scan is read-only -and safe. - -## Scope - -You are given a scope: a directory, a repository, a file list, or "the git -changeset". Scan exactly that — no more, no less. - -## Running the scanner — `bin/sonar agent-scan` - -Invoke the `sonar-predictor` skill (via the `Skill` tool). The skill's -`bin/sonar agent-scan [scope]` subcommand writes the full JSON output to -`.sonar-predictor/scan.json` at the project root and adds that path to -`.gitignore` on first use, so the analyzer's large output never enters your -context. It prints a compact summary on stdout — issue count, severity -breakdown, file path. - -Default scope is the current git changeset (no arg). Pass explicit scope -after `agent-scan`: - -- `agent-scan` — git changeset (default) -- `agent-scan check src/Main.java` — specific files -- `agent-scan analyze src/` — whole directory - -Read `bin/sonar --help` for the underlying command vocabulary if you need -something unusual; don't guess flag names. - -Exit codes: `0` clean, `1` issues found (a normal result, not a failure), -`2` tool error. - -## Non-standard test layouts — `--test-path GLOB` - -The daemon auto-detects standard test paths per language (`src/test/**`, -`tests/**`, `__tests__/**`, `spec/**`, plus per-language filename -conventions like `*Test.java`, `*_test.go`, `test_*.py`, `*.spec.ts`, -`*_spec.rb`). For those, no flag is needed — `Main`-only rules (`java:S100`, -`java:S106`, `java:S1118`, …) already skip the test files correctly. - -**Look at the project layout before scanning.** If you see non-standard -test directories or filename conventions — e.g. `src/integration/`, `e2e/`, -`fixtures/`, `cypress/`, an `acceptance/` tree — pass them as repeatable -`--test-path GLOB` *global* options so the analyzer skips `Main`-only rules -on them too. Globs are standard Java NIO globs against `/`-separated paths. - -```sh -# Augment the built-in detection for a project with cypress e2e + integration: -./bin/sonar --test-path 'src/integration/**' --test-path 'cypress/**' agent-scan analyze . -``` - -Skip this flag when the layout is conventional. Don't over-classify: the -goal is to not flag intentional test conventions, not to silence rules. - -## What to report - -The stdout summary from `agent-scan` is your top-line: issue count, severity -counts, and the `.sonar-predictor/scan.json` path. Report that verbatim plus -a one-line verdict. - -If your caller wants drill-down (specific files, specific rules, criticals -only), query the JSON file with `jq` — never read it raw. Issues are nested -under `.files[].issues[]`: - -```sh -jq -rc '[.files[]?.issues[]?.type] | group_by(.) | map("\(.[0])=\(length)") | join(" ")' .sonar-predictor/scan.json -jq -r '["BLOCKER","CRITICAL","MAJOR","MINOR","INFO"] as $r - | [.files[] as $f | $f.issues[] - | {s:.severity,k:.ruleKey,f:($f.file|split("/")|last),l:.startLine,m:.message}] - | sort_by(.s as $x | $r|index($x)) | .[0:8][] - | " \(.s) \(.k) \(.f):\(.l) \(.m[0:80])"' .sonar-predictor/scan.json -jq -rc '.warnings' .sonar-predictor/scan.json -``` - -Never dump raw JSON, never do a file-by-file walk. Concise, actionable summary -only. diff --git a/plugin/agents/sonar-scanner-copilot.md b/plugin/agents/sonar-scanner-copilot.md deleted file mode 100644 index de4f586..0000000 --- a/plugin/agents/sonar-scanner-copilot.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -name: sonar-scanner-copilot -description: GitHub-Copilot-CLI variant of the sonar-scanner agent. Mechanical offline code-quality scanner — invokes the sonar-predictor skill over an assigned scope and returns a concise findings summary. Scan-only; never edits code. Uses GPT-5-mini for this mechanical task. Built to be fanned out as parallel instances, keeping raw analyzer output out of the orchestrator's context. -model: gpt-5-mini -tools: bash, view, glob, skill ---- - -You are a mechanical code-quality scanner. You invoke the `sonar-predictor` -skill over the scope you are given and report what it found. You never modify -code and never apply fixes — scan and summarize only. The scan is read-only -and safe. - -## Scope - -You are given a scope: a directory, a repository, a file list, or "the git -changeset". Scan exactly that — no more, no less. - -## Running the scanner — `bin/sonar agent-scan` - -Invoke the `sonar-predictor` skill (via the `skill` tool). The skill's -`bin/sonar agent-scan [scope]` subcommand writes the full JSON output to -`.sonar-predictor/scan.json` at the project root and adds that path to -`.gitignore` on first use, so the analyzer's large output never enters your -context. It prints a compact summary on stdout — issue count, severity -breakdown, file path. - -Default scope is the current git changeset (no arg). Pass explicit scope -after `agent-scan`: - -- `agent-scan` — git changeset (default) -- `agent-scan check src/Main.java` — specific files -- `agent-scan analyze src/` — whole directory - -Read `bin/sonar --help` for the underlying command vocabulary if you need -something unusual; don't guess flag names. - -Exit codes: `0` clean, `1` issues found (a normal result, not a failure), -`2` tool error. - -## Non-standard test layouts — `--test-path GLOB` - -The daemon auto-detects standard test paths per language (`src/test/**`, -`tests/**`, `__tests__/**`, `spec/**`, plus per-language filename -conventions like `*Test.java`, `*_test.go`, `test_*.py`, `*.spec.ts`, -`*_spec.rb`). For those, no flag is needed — `Main`-only rules (`java:S100`, -`java:S106`, `java:S1118`, …) already skip the test files correctly. - -**Look at the project layout before scanning.** If you see non-standard -test directories or filename conventions — e.g. `src/integration/`, `e2e/`, -`fixtures/`, `cypress/`, an `acceptance/` tree — pass them as repeatable -`--test-path GLOB` *global* options so the analyzer skips `Main`-only rules -on them too. Globs are standard Java NIO globs against `/`-separated paths. - -```sh -# Augment the built-in detection for a project with cypress e2e + integration: -./bin/sonar --test-path 'src/integration/**' --test-path 'cypress/**' agent-scan analyze . -``` - -Skip this flag when the layout is conventional. Don't over-classify: the -goal is to not flag intentional test conventions, not to silence rules. - -## What to report - -The stdout summary from `agent-scan` is your top-line: issue count, severity -counts, and the `.sonar-predictor/scan.json` path. Report that verbatim plus -a one-line verdict. - -If your caller wants drill-down (specific files, specific rules, criticals -only), query the JSON file with `jq` — never `view` it raw. Issues are nested -under `.files[].issues[]`: - -```sh -jq -rc '[.files[]?.issues[]?.type] | group_by(.) | map("\(.[0])=\(length)") | join(" ")' .sonar-predictor/scan.json -jq -r '["BLOCKER","CRITICAL","MAJOR","MINOR","INFO"] as $r - | [.files[] as $f | $f.issues[] - | {s:.severity,k:.ruleKey,f:($f.file|split("/")|last),l:.startLine,m:.message}] - | sort_by(.s as $x | $r|index($x)) | .[0:8][] - | " \(.s) \(.k) \(.f):\(.l) \(.m[0:80])"' .sonar-predictor/scan.json -jq -rc '.warnings' .sonar-predictor/scan.json -``` - -Never dump raw JSON, never do a file-by-file walk. Concise, actionable summary -only. diff --git a/plugin/skills/sonar-predictor/SKILL.md b/plugin/skills/sonar-predictor/SKILL.md deleted file mode 100644 index c384ec0..0000000 --- a/plugin/skills/sonar-predictor/SKILL.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: sonar-predictor -description: Use after writing or modifying source code, before committing or pushing — runs genuine SonarSource analyzers offline as a fast local quality gate to catch bugs, code smells, vulnerabilities and security hotspots. Also use when the user asks to check code quality, run sonar, or analyze a file or diff. ---- - -# sonar-predictor - -An offline SonarSource pre-push quality gate — runs the genuine analyzers locally, no network, no server. - -**Scan-only.** This skill only *scans and reports* — it reads source and emits findings, and never modifies any file. Applying fixes is the calling agent's job, not this tool's; running it is a safe, read-only operation. - -Run `./bin/sonar` from this skill's base directory (the folder with this `SKILL.md`), or by its absolute path — it is not on `PATH`. The first invocation downloads the analyzer bundle (~150 MB) from Maven Central into a user cache; every subsequent call runs from that cache with no network. **Read the tool's own help before invoking it:** `./bin/sonar --help` lists the commands and the global options, and `./bin/sonar --help` gives a command's own options and exact argument order. The skill scans a git changeset or explicit files and directories and reports in a chosen format — the help states the precise flags and where each one goes. That generated help is the single source of truth; this `SKILL.md` deliberately does not restate command syntax, which would drift. Do not guess flag names or their placement — read the help. - -**Agent invocation pattern — `./bin/sonar agent-scan [scope]`.** A wrapper subcommand that bakes the out-of-context discipline into the tool: it runs the scan with `--format json` redirected to `.sonar-predictor/scan.json` at the project root, adds `.sonar-predictor/` to `.gitignore` on first use (when inside a git repo), and prints a compact summary to stdout — issue count, severity breakdown, file path. The calling agent reports that summary and points its caller at the file; deeper drill-down happens with `jq` on the file, on demand. With no scope argument, `agent-scan` defaults to `check --diff` (the git changeset); pass an explicit scope (`agent-scan analyze src/`, `agent-scan check src/Main.java`, etc.) to scan something else. All flags forward to the underlying CLI. - -**Test vs production classification.** The analyzer applies SonarSource's standard `Main` vs `Test` rule scope, so `Main`-only rules (`java:S100` method naming, `java:S106` System.out, `java:S1118` utility-class ctor, ...) skip test files. The daemon auto-detects tests by language-conventional paths and filenames: `src/test/**`, `tests/**`, `__tests__/**`, `spec/**` for any language; plus per-language filename conventions (`*Test.java`, `*_test.go`, `test_*.py`, `*.spec.ts`, `*_spec.rb`, etc.). **When a project's layout is non-standard, an agent passes `--test-path GLOB` (repeatable, global option)** so non-conventional dirs are also treated as tests — e.g., `./bin/sonar --test-path 'src/integration/**' --test-path 'e2e/**' agent-scan analyze .`. Patterns are standard Java NIO globs against `/`-separated paths. Standalone invocations without an agent fall back to the built-in detector. - -Exit codes: `0` clean, `1` issues found, `2` tool error. - -Acting on findings: fix `BUG`/`VULNERABILITY`/`SECURITY_HOTSPOT` and `CRITICAL`/`MAJOR` first. This is a fast first-pass gate, not the release gate — fix the real issues and move on. - -**Configuration / corporate environments.** The launcher reads `config.env` next to this `SKILL.md` — Maven proxy URL, JRE download URL, bundle and Java version pins. Edit it (or override with same-named env vars) to point at a corporate Nexus / Artifactory mirror and a private JRE source. The defaults use Maven Central and Adoptium Temurin's public API. `SONAR_PREDICTOR_HOME=/path/to/extracted/sonar-predictor` skips the bundle download entirely for fully air-gapped / pre-staged installs. - -**Plugin-bundled agent variants.** Two named scanner subagents ship with this plugin: invoke `sonar-scanner-claude` on Claude Code (model: haiku) or `sonar-scanner-copilot` on GitHub Copilot CLI (model: gpt-5-mini). Selection is by agent name — pick the one matching your platform. diff --git a/plugin/skills/sonar-predictor/bin/sonar b/plugin/skills/sonar-predictor/bin/sonar deleted file mode 100755 index a959ee3..0000000 --- a/plugin/skills/sonar-predictor/bin/sonar +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/env bash -# Bootstrap wrapper for the sonar-predictor skill bundle. -# -# On first invocation: -# 1. loads ../config.env (corporate Maven proxy, JRE mirror, version pin), -# 2. downloads sonar-predictor-dist-.zip from SONAR_MAVEN_REPO_URL, -# verifies its SHA-1 sidecar, and unpacks it into the user cache, -# 3. ensures a Java >= SONAR_MIN_JAVA_VERSION is available — downloading -# one from SONAR_JRE_URL_TEMPLATE into the user cache if not found -# (the bundle's own launcher already searches JAVA_HOME / PATH / common -# install dirs; this only kicks in when that comes up empty), -# 4. exec's the cached launcher. -# Every subsequent call exec's the cached launcher directly with no network. -# -# Override the bundle location for air-gapped / pre-staged installs: -# SONAR_PREDICTOR_HOME=/path/to/extracted/sonar-predictor -# -# All other knobs (Maven proxy, JRE source, version pin, min Java) live in -# ../config.env; each one is also an env-var override. - -set -euo pipefail - -# -------- 1. load config ----------------------------------------------------- - -HERE="$(cd "$(dirname "$0")" && pwd)" -CONFIG="$HERE/../config.env" - -if [ -f "$CONFIG" ]; then - # Parse KEY=VALUE lines; env vars already in scope take precedence. - while IFS='=' read -r key value; do - case "$key" in - ''|'#'*) continue ;; - esac - key="${key%%[[:space:]]*}" - if [ -z "${!key:-}" ]; then - printf -v "$key" '%s' "$value" - export "$key" - fi - done < "$CONFIG" -fi - -# Defaults if config.env is missing or empty. -: "${SONAR_MAVEN_REPO_URL:=https://repo1.maven.org/maven2}" -: "${SONAR_BUNDLE_VERSION:=0.1.1}" -: "${SONAR_MIN_JAVA_VERSION:=17}" -: "${SONAR_JRE_URL_TEMPLATE:=https://api.adoptium.net/v3/binary/latest/{version}/ga/{os}/{arch}/jre/hotspot/normal/eclipse}" -: "${SONAR_JRE_VERSION:=17}" -: "${SONAR_DISABLE_JRE_AUTODOWNLOAD:=}" - -VERSION="$SONAR_BUNDLE_VERSION" -GROUP_PATH="io/github/randomcodespace/sonarpredict" -ARTIFACT="sonar-predictor-dist" -BUNDLE_URL_BASE="${SONAR_MAVEN_REPO_URL%/}/${GROUP_PATH}/${ARTIFACT}/${VERSION}" - -CACHE_ROOT="${XDG_CACHE_HOME:-$HOME/.cache}/sonar-predictor" -if [ -n "${SONAR_PREDICTOR_HOME:-}" ]; then - SKILL_DIR="$SONAR_PREDICTOR_HOME" -else - SKILL_DIR="$CACHE_ROOT/$VERSION" -fi -REAL_SONAR="$SKILL_DIR/bin/sonar" - -# -------- helpers ------------------------------------------------------------ - -require_cmd() { - if ! command -v "$1" >/dev/null 2>&1; then - echo "sonar-predictor: required command '$1' not found on PATH" >&2 - exit 2 - fi -} - -sha1_of() { - if command -v sha1sum >/dev/null 2>&1; then - sha1sum "$1" | awk '{print $1}' - elif command -v shasum >/dev/null 2>&1; then - shasum -a 1 "$1" | awk '{print $1}' - else - echo "sonar-predictor: no sha1sum or shasum found — cannot verify bundle" >&2 - exit 2 - fi -} - -java_major_of() { - local v raw maj - v="$("$1" -version 2>&1 | head -1)" || return 1 - raw="$(printf '%s' "$v" | sed -E 's/^[^"]*"([^"]+)".*/\1/')" - [ -n "$raw" ] || return 1 - maj="$(printf '%s' "$raw" | cut -d. -f1)" - if [ "$maj" = "1" ]; then - maj="$(printf '%s' "$raw" | cut -d. -f2)" - fi - printf '%s' "$maj" -} - -found_java_meets_min() { - # The bundle's own launcher searches JAVA_HOME, PATH and common dirs. We - # only need to know whether *some* working Java >= the minimum exists; if - # so, we hand off to it. Otherwise we install one and set JAVA_HOME so the - # bundle's launcher picks it up. - local cand major - for cand in \ - "${JAVA_HOME:-}/bin/java" \ - "$(command -v java 2>/dev/null || true)" \ - /usr/lib/jvm/*/bin/java \ - /usr/java/*/bin/java \ - /Library/Java/JavaVirtualMachines/*/Contents/Home/bin/java \ - "${HOME:-/nonexistent}"/.sdkman/candidates/java/*/bin/java \ - /opt/java/*/bin/java \ - /opt/*/bin/java - do - [ -x "$cand" ] || continue - major="$(java_major_of "$cand" 2>/dev/null || true)" - [ -n "$major" ] || continue - if [ "$major" -ge "$SONAR_MIN_JAVA_VERSION" ] 2>/dev/null; then - return 0 - fi - done - return 1 -} - -detect_os_arch() { - case "$(uname -s)" in - Linux*) OS=linux ;; - Darwin*) OS=mac ;; - *) echo "sonar-predictor: unsupported OS '$(uname -s)' for JRE auto-download" >&2; exit 2 ;; - esac - case "$(uname -m)" in - x86_64|amd64) ARCH=x64 ;; - aarch64|arm64) ARCH=aarch64 ;; - *) echo "sonar-predictor: unsupported arch '$(uname -m)' for JRE auto-download" >&2; exit 2 ;; - esac -} - -install_jre() { - local jre_dir="$CACHE_ROOT/jre/$SONAR_JRE_VERSION" - if [ -x "$jre_dir/bin/java" ]; then - export JAVA_HOME="$jre_dir" - return 0 - fi - - case "${SONAR_DISABLE_JRE_AUTODOWNLOAD:-}" in - 1|true|yes|TRUE|YES) - echo "sonar-predictor: no Java >= $SONAR_MIN_JAVA_VERSION found, and SONAR_DISABLE_JRE_AUTODOWNLOAD is set" >&2 - exit 2 - ;; - esac - - require_cmd curl - require_cmd tar - detect_os_arch - - local url="$SONAR_JRE_URL_TEMPLATE" - url="${url//\{os\}/$OS}" - url="${url//\{arch\}/$ARCH}" - url="${url//\{version\}/$SONAR_JRE_VERSION}" - - echo "sonar-predictor: no Java $SONAR_MIN_JAVA_VERSION+ found — downloading JRE $SONAR_JRE_VERSION ($OS/$ARCH) from $url" >&2 - mkdir -p "$(dirname "$jre_dir")" - - local tmp; tmp="$(mktemp -d)" - curl -fsSL --retry 3 -o "$tmp/jre.tgz" "$url" - ( cd "$tmp" && tar -xzf jre.tgz ) - - # Find the JRE root (the dir whose bin/java is executable). Handles both - # Linux layout (.../jdk-17.../bin/java) and macOS layout - # (.../jdk-17.../Contents/Home/bin/java). - local java_path home - java_path="$(find "$tmp" -mindepth 2 -path '*/bin/java' -type f -executable 2>/dev/null | head -1 || true)" - if [ -z "$java_path" ]; then - echo "sonar-predictor: downloaded JRE has no bin/java; archive layout unrecognised" >&2 - rm -rf "$tmp" - exit 2 - fi - home="${java_path%/bin/java}" - mv "$home" "$jre_dir" - rm -rf "$tmp" - - if [ ! -x "$jre_dir/bin/java" ]; then - echo "sonar-predictor: JRE install completed but $jre_dir/bin/java is missing" >&2 - exit 2 - fi - export JAVA_HOME="$jre_dir" -} - -# -------- 2. ensure bundle is cached ---------------------------------------- - -if [ ! -x "$REAL_SONAR" ]; then - require_cmd curl - require_cmd unzip - - echo "sonar-predictor: first run — downloading $VERSION bundle from $SONAR_MAVEN_REPO_URL..." >&2 - mkdir -p "$(dirname "$SKILL_DIR")" - TMP="$(mktemp -d)" - trap 'rm -rf "$TMP"' EXIT - - curl -fsSL --retry 3 -o "$TMP/bundle.zip" "$BUNDLE_URL_BASE/$ARTIFACT-$VERSION.zip" - curl -fsSL --retry 3 -o "$TMP/bundle.zip.sha1" "$BUNDLE_URL_BASE/$ARTIFACT-$VERSION.zip.sha1" - - EXPECTED="$(awk '{print $1}' "$TMP/bundle.zip.sha1")" - ACTUAL="$(sha1_of "$TMP/bundle.zip")" - if [ "$EXPECTED" != "$ACTUAL" ]; then - echo "sonar-predictor: SHA-1 verification failed (expected $EXPECTED, got $ACTUAL)" >&2 - exit 2 - fi - - unzip -q "$TMP/bundle.zip" -d "$TMP/extracted" - if [ ! -d "$TMP/extracted/sonar-predictor" ]; then - echo "sonar-predictor: unexpected bundle layout (no sonar-predictor/ at zip root)" >&2 - exit 2 - fi - - mv "$TMP/extracted/sonar-predictor" "$SKILL_DIR" 2>/dev/null || true - trap - EXIT - rm -rf "$TMP" - - if [ ! -x "$REAL_SONAR" ]; then - echo "sonar-predictor: bootstrap completed but $REAL_SONAR is not executable" >&2 - exit 2 - fi -fi - -# -------- 3. ensure a usable Java is available ------------------------------ - -if ! found_java_meets_min; then - install_jre -fi - -# -------- 4. hand off ------------------------------------------------------- - -if [ -n "${JAVA_HOME:-}" ]; then - export JAVA_HOME - export PATH="$JAVA_HOME/bin:$PATH" -fi - -# The `agent-scan` subcommand bakes the out-of-context discipline into the -# tool: run the scan with JSON output written to .sonar-predictor/scan.json at -# the project root, add that path to .gitignore on first use, and print a -# compact summary on stdout. -# -# No external dependencies (no jq, no awk JSON-parsing): the CLI's --save flag -# writes the report to the target file and emits the summary itself. The -# wrapper here is just glue — argument defaults, .gitignore housekeeping. -agent_scan() { - local scan_file=".sonar-predictor/scan.json" - - # Add the scan dir to .gitignore on first use, only inside a git repo. - if git rev-parse --git-dir >/dev/null 2>&1; then - if [ ! -f .gitignore ] || ! grep -qF '.sonar-predictor/' .gitignore; then - printf '\n# sonar-predictor scan output (do not commit)\n.sonar-predictor/\n' >> .gitignore - fi - fi - - # No args -> default to `check --diff` (the git changeset). - if [ $# -eq 0 ]; then - set -- check --diff - fi - - # CLI does the work: --save writes the JSON report to the target file and - # prints the compact "N issues written to / severity ... / type ..." - # summary on stdout. Stderr from the analyzer flows through unfiltered. - "$REAL_SONAR" --format json --save "$scan_file" "$@" -} - -if [ "${1:-}" = "agent-scan" ]; then - shift - agent_scan "$@" - exit "$?" -fi - -exec "$REAL_SONAR" "$@" diff --git a/plugin/skills/sonar-predictor/bin/sonar.bat b/plugin/skills/sonar-predictor/bin/sonar.bat deleted file mode 100644 index 98b4430..0000000 --- a/plugin/skills/sonar-predictor/bin/sonar.bat +++ /dev/null @@ -1,124 +0,0 @@ -@echo off -rem Bootstrap wrapper for the sonar-predictor skill bundle (Windows). -rem -rem Loads ../config.env (KEY=VALUE lines, # for comments) and uses the -rem configured Maven proxy + bundle version to download the analyzer bundle -rem on first invocation. Env vars of the same name take precedence over the -rem file. -rem -rem Java auto-install is NOT yet supported on Windows — install Java 17+ -rem manually (or set JAVA_HOME). The bundle's own launcher will discover it. -rem -rem Override the bundle location for air-gapped / pre-staged installs: -rem set SONAR_PREDICTOR_HOME=C:\path\to\extracted\sonar-predictor - -setlocal enabledelayedexpansion - -rem ---- 1. load config.env (env vars already set win) ---- -set "CONFIG=%~dp0..\config.env" -if exist "%CONFIG%" ( - for /f "usebackq eol=# tokens=1,* delims==" %%a in ("%CONFIG%") do ( - if not "%%a"=="" if not defined %%a set "%%a=%%b" - ) -) - -rem ---- defaults ---- -if not defined SONAR_MAVEN_REPO_URL set "SONAR_MAVEN_REPO_URL=https://repo1.maven.org/maven2" -if not defined SONAR_BUNDLE_VERSION set "SONAR_BUNDLE_VERSION=0.1.1" - -set "VERSION=%SONAR_BUNDLE_VERSION%" -set "ARTIFACT=sonar-predictor-dist" -set "BUNDLE_URL_BASE=%SONAR_MAVEN_REPO_URL%/io/github/randomcodespace/sonarpredict/sonar-predictor-dist/%VERSION%" - -if defined SONAR_PREDICTOR_HOME ( - set "SKILL_DIR=%SONAR_PREDICTOR_HOME%" -) else ( - if defined LOCALAPPDATA ( - set "SKILL_DIR=%LOCALAPPDATA%\sonar-predictor\%VERSION%" - ) else ( - set "SKILL_DIR=%USERPROFILE%\.cache\sonar-predictor\%VERSION%" - ) -) - -set "REAL_SONAR=%SKILL_DIR%\bin\sonar.bat" - -if exist "%REAL_SONAR%" goto :exec - -echo sonar-predictor: first run -- downloading %VERSION% bundle from %SONAR_MAVEN_REPO_URL%... 1>&2 - -set "TMP=%TEMP%\sonar-predictor-bootstrap-%RANDOM%-%RANDOM%" -mkdir "%TMP%" || (echo sonar-predictor: failed to create temp dir 1>&2 & exit /b 2) - -set "ZIP=%TMP%\bundle.zip" -set "SHA=%TMP%\bundle.zip.sha1" - -powershell -NoProfile -ExecutionPolicy Bypass -Command ^ - "$ProgressPreference='SilentlyContinue'; try { Invoke-WebRequest -Uri '%BUNDLE_URL_BASE%/%ARTIFACT%-%VERSION%.zip' -OutFile '%ZIP%' } catch { exit 2 }" -if errorlevel 1 (echo sonar-predictor: bundle download failed 1>&2 & rmdir /S /Q "%TMP%" & exit /b 2) - -powershell -NoProfile -ExecutionPolicy Bypass -Command ^ - "$ProgressPreference='SilentlyContinue'; try { Invoke-WebRequest -Uri '%BUNDLE_URL_BASE%/%ARTIFACT%-%VERSION%.zip.sha1' -OutFile '%SHA%' } catch { exit 2 }" -if errorlevel 1 (echo sonar-predictor: SHA-1 download failed 1>&2 & rmdir /S /Q "%TMP%" & exit /b 2) - -for /f "tokens=1" %%i in (%SHA%) do set "EXPECTED=%%i" -for /f "tokens=1" %%i in ('powershell -NoProfile -Command "(Get-FileHash -Algorithm SHA1 '%ZIP%').Hash.ToLower()"') do set "ACTUAL=%%i" -if /i not "!EXPECTED!"=="!ACTUAL!" ( - echo sonar-predictor: SHA-1 verification failed ^(expected !EXPECTED!, got !ACTUAL!^) 1>&2 - rmdir /S /Q "%TMP%" - exit /b 2 -) - -powershell -NoProfile -ExecutionPolicy Bypass -Command ^ - "$ProgressPreference='SilentlyContinue'; try { Expand-Archive -Force -Path '%ZIP%' -DestinationPath '%TMP%\extracted' } catch { exit 2 }" -if errorlevel 1 (echo sonar-predictor: extraction failed 1>&2 & rmdir /S /Q "%TMP%" & exit /b 2) - -if not exist "%TMP%\extracted\sonar-predictor" ( - echo sonar-predictor: unexpected bundle layout ^(no sonar-predictor\ at zip root^) 1>&2 - rmdir /S /Q "%TMP%" - exit /b 2 -) - -for %%I in ("%SKILL_DIR%") do set "PARENT=%%~dpI" -if not exist "%PARENT%" mkdir "%PARENT%" -move /Y "%TMP%\extracted\sonar-predictor" "%SKILL_DIR%" >nul -rmdir /S /Q "%TMP%" - -if not exist "%REAL_SONAR%" ( - echo sonar-predictor: bootstrap completed but %REAL_SONAR% is missing 1>&2 - exit /b 2 -) - -:exec -if /i "%~1"=="agent-scan" ( - shift /1 - call :agent_scan %* - exit /b %ERRORLEVEL% -) -call "%REAL_SONAR%" %* -exit /b %ERRORLEVEL% - -rem agent-scan: write JSON to .sonar-predictor\scan.json, gitignore that -rem dir on first use, print a short pointer on stdout. -:agent_scan -set "SCAN_FILE=.sonar-predictor\scan.json" -if not exist ".sonar-predictor" mkdir ".sonar-predictor" - -git rev-parse --git-dir >nul 2>&1 -if not errorlevel 1 ( - if not exist .gitignore ( - >>.gitignore echo .sonar-predictor/ - ) else ( - findstr /C:".sonar-predictor/" .gitignore >nul 2>&1 || >>.gitignore echo .sonar-predictor/ - ) -) - -if "%~1"=="" ( - call "%REAL_SONAR%" --format json check --diff > "%SCAN_FILE%" 2>&1 -) else ( - call "%REAL_SONAR%" --format json %* > "%SCAN_FILE%" 2>&1 -) -set RC=%ERRORLEVEL% - -echo sonar-predictor: scan complete -^> %SCAN_FILE% -echo query: jq ^"...^" %SCAN_FILE% -exit /b %RC% diff --git a/plugin/skills/sonar-predictor/config.env b/plugin/skills/sonar-predictor/config.env deleted file mode 100644 index f9e0fd9..0000000 --- a/plugin/skills/sonar-predictor/config.env +++ /dev/null @@ -1,46 +0,0 @@ -# sonar-predictor — bootstrap configuration -# -# Fork-and-go: this is the only file you need to edit to point the launcher -# at a corporate Maven proxy, a private JRE mirror, or a vendored bundle -# version. The launcher reads this file before doing anything. -# -# Format: KEY=VALUE per line, # for comments, no quotes, no shell expansion. -# Both the bash launcher (bin/sonar) and the Windows launcher (bin/sonar.bat) -# parse this file the same way. -# -# An environment variable of the same name takes precedence over the value -# set here — set one to override without editing this file. - -# --- Analyzer bundle source ---------------------------------------------------- - -# Maven proxy / repository where sonar-predictor-dist-.zip lives. -# Public default: Maven Central. Corporate Nexus / Artifactory example: -# SONAR_MAVEN_REPO_URL=https://nexus.corp.example.com/repository/maven-public -SONAR_MAVEN_REPO_URL=https://repo1.maven.org/maven2 - -# Bundle version. Bumped in lockstep with each plugin release. A fork can pin -# to a vendored / mirrored version without touching the launcher. -SONAR_BUNDLE_VERSION=0.1.3 - -# --- Java runtime -------------------------------------------------------------- - -# Minimum Java major version the analyzer requires. -SONAR_MIN_JAVA_VERSION=17 - -# If no Java >= SONAR_MIN_JAVA_VERSION is found on PATH, in JAVA_HOME, or in -# the common install locations the bundle's launcher already searches, the -# bootstrap downloads a JRE from this URL. Tokens are substituted at download: -# {os} linux | mac (Windows JRE auto-install is not yet supported) -# {arch} x64 | aarch64 -# {version} the value of SONAR_JRE_VERSION -# -# Public default: Adoptium Temurin API (302-redirects to a GitHub release). -# Corporate mirror example (predictable archive layout): -# SONAR_JRE_URL_TEMPLATE=https://artifacts.corp.example.com/temurin/{version}/jre-{os}-{arch}.tar.gz -SONAR_JRE_URL_TEMPLATE=https://api.adoptium.net/v3/binary/latest/{version}/ga/{os}/{arch}/jre/hotspot/normal/eclipse -SONAR_JRE_VERSION=17 - -# Set to 1 (or true, yes) to skip the JRE auto-download even if no Java is -# found — for environments with a policy against the bootstrap fetching -# binaries. The launcher will then print an error and exit instead. -SONAR_DISABLE_JRE_AUTODOWNLOAD= diff --git a/pom.xml b/pom.xml index 53d69f5..df1311f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,13 +5,23 @@ 4.0.0 io.github.randomcodespace.sonarpredict - sonar-predictor-parent - 0.1.0-SNAPSHOT - pom + sonar-predictor + 0.2.0-SNAPSHOT + + jar sonar-predictor - SonarSource-powered code analysis predictor: a daemon + CLI that - runs the SonarLint analysis engine locally and is distributed as a - self-contained Claude Code agent skill. + Offline, no-server, pre-push code-quality gate. Embeds the genuine + SonarSource analyzers (SonarLint engine + 10 language plugins) and runs them + locally. Ships as a single distribution zip with launchers, fat jars and + analyzer plugins. https://github.com/RandomCodeSpace/sonar-predict 2026 @@ -43,16 +53,12 @@ https://github.com/RandomCodeSpace/sonar-predict/issues - - protocol - daemon - cli - dist - - 17 + 17 + 17 UTF-8 + 2.17.2 5.10.2 10.24.0.81415 @@ -60,9 +66,9 @@ 8.15.0.39343 5.5.0.23291 @@ -103,6 +109,28 @@ + + + + com.fasterxml.jackson.core + jackson-databind + + + info.picocli + picocli + + + org.sonarsource.sonarlint.core + sonarlint-analysis-engine + + + org.junit.jupiter + junit-jupiter + test + + + @@ -127,13 +155,18 @@ - + + org.apache.maven.plugins + maven-compiler-plugin + + + org.jacoco jacoco-maven-plugin @@ -149,6 +182,174 @@ + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.8.1 + + + copy-analyzer-plugins-for-tests + process-test-resources + copy + + ${project.basedir}/plugins + false + + org.sonarsource.javasonar-java-plugin${sonar.plugin.java.version}jar + org.sonarsource.pythonsonar-python-plugin${sonar.plugin.python.version}jar + org.sonarsource.javascriptsonar-javascript-plugin${sonar.plugin.javascript.version}jar + org.sonarsource.phpsonar-php-plugin${sonar.plugin.php.version}jar + org.sonarsource.kotlinsonar-kotlin-plugin${sonar.plugin.kotlin.version}jar + org.sonarsource.slangsonar-go-plugin${sonar.plugin.go.version}jar + org.sonarsource.slangsonar-ruby-plugin${sonar.plugin.ruby.version}jar + org.sonarsource.slangsonar-scala-plugin${sonar.plugin.scala.version}jar + org.sonarsource.htmlsonar-html-plugin${sonar.plugin.html.version}jar + org.sonarsource.xmlsonar-xml-plugin${sonar.plugin.xml.version}jar + + + + + copy-analyzer-plugins-for-dist + prepare-package + copy + + ${project.build.directory}/plugins + false + + org.sonarsource.javasonar-java-plugin${sonar.plugin.java.version}jar + org.sonarsource.pythonsonar-python-plugin${sonar.plugin.python.version}jar + org.sonarsource.javascriptsonar-javascript-plugin${sonar.plugin.javascript.version}jar + org.sonarsource.phpsonar-php-plugin${sonar.plugin.php.version}jar + org.sonarsource.kotlinsonar-kotlin-plugin${sonar.plugin.kotlin.version}jar + org.sonarsource.slangsonar-go-plugin${sonar.plugin.go.version}jar + org.sonarsource.slangsonar-ruby-plugin${sonar.plugin.ruby.version}jar + org.sonarsource.slangsonar-scala-plugin${sonar.plugin.scala.version}jar + org.sonarsource.htmlsonar-html-plugin${sonar.plugin.html.version}jar + org.sonarsource.xmlsonar-xml-plugin${sonar.plugin.xml.version}jar + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.3 + + + shade-cli + package + shade + + + sonar-predictor-cli + true + cli + + + dev.sonarcli.cli.SonarCommand + + ${project.version} + + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + shade-daemon + package + shade + + sonar-predictor-daemon + true + daemon + + + dev.sonarcli.daemon.DaemonMain + + ${project.version} + + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.7.1 + + + build-dist-zip + package + single + + false + sonar-predictor-dist-${project.version} + + src/main/assembly/dist.xml + + + + + @@ -156,15 +357,18 @@ release + org.apache.maven.plugins maven-source-plugin @@ -173,9 +377,7 @@ attach-sources package - - jar-no-fork - + jar-no-fork @@ -185,9 +387,6 @@ maven-javadoc-plugin 3.10.1 - none false @@ -195,9 +394,7 @@ attach-javadoc package - - jar - + jar @@ -210,9 +407,7 @@ sign-artifacts verify - - sign - + sign @@ -230,32 +425,31 @@ org.codehaus.mojo build-helper-maven-plugin 3.6.0 - - false - attach-source-zip + attach-deploy-artifacts package attach-artifact + + ${project.build.directory}/sonar-predictor-dist-${project.version}.zip + zip + dist + ${project.basedir}/sonar-predict-${project.version}-src.zip zip diff --git a/protocol/pom.xml b/protocol/pom.xml deleted file mode 100644 index 71f5f35..0000000 --- a/protocol/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - 4.0.0 - - - io.github.randomcodespace.sonarpredict - sonar-predictor-parent - 0.1.0-SNAPSHOT - - - sonar-predictor-protocol - sonar-predictor :: protocol - - - - com.fasterxml.jackson.core - jackson-databind - - - org.junit.jupiter - junit-jupiter - test - - - diff --git a/src/main/assembly/dist.xml b/src/main/assembly/dist.xml new file mode 100644 index 0000000..7e17ec3 --- /dev/null +++ b/src/main/assembly/dist.xml @@ -0,0 +1,66 @@ + + + dist + + + + zip + dir + + + sonar-predictor + true + + + + + ${project.basedir}/src/main/staging/bin + bin + + sonar + + 0755 + + + ${project.basedir}/src/main/staging/bin + bin + + sonar.bat + + 0644 + + + + + ${project.build.directory}/plugins + plugins + + *.jar + + + + + + ${project.build.directory} + lib + + sonar-predictor-cli.jar + sonar-predictor-daemon.jar + + + + diff --git a/cli/src/main/java/dev/sonarcli/cli/DaemonClient.java b/src/main/java/dev/sonarcli/cli/DaemonClient.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/DaemonClient.java rename to src/main/java/dev/sonarcli/cli/DaemonClient.java diff --git a/cli/src/main/java/dev/sonarcli/cli/DaemonControl.java b/src/main/java/dev/sonarcli/cli/DaemonControl.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/DaemonControl.java rename to src/main/java/dev/sonarcli/cli/DaemonControl.java diff --git a/cli/src/main/java/dev/sonarcli/cli/DaemonException.java b/src/main/java/dev/sonarcli/cli/DaemonException.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/DaemonException.java rename to src/main/java/dev/sonarcli/cli/DaemonException.java diff --git a/cli/src/main/java/dev/sonarcli/cli/DaemonLauncher.java b/src/main/java/dev/sonarcli/cli/DaemonLauncher.java similarity index 98% rename from cli/src/main/java/dev/sonarcli/cli/DaemonLauncher.java rename to src/main/java/dev/sonarcli/cli/DaemonLauncher.java index db482e0..5917ffa 100644 --- a/cli/src/main/java/dev/sonarcli/cli/DaemonLauncher.java +++ b/src/main/java/dev/sonarcli/cli/DaemonLauncher.java @@ -48,7 +48,7 @@ * resolved jar (its {@code daemon/plugins/} is the dev-default plugin set). * *

Java runtime. The daemon launches with the {@code java} named by - * {@code -Dsonar.java.exe} when set — the skill bundle's {@code bin/sonar} + * {@code -Dsonar.java.exe} when set — the distribution's {@code bin/sonar} * launcher sets it to a Java 17+ runtime it auto-discovered. With the property * absent the daemon launches with the current/system {@code java} that started * the CLI. No JRE is provisioned or bundled. @@ -63,7 +63,7 @@ public final class DaemonLauncher { /** * System property naming the {@code java} executable used to spawn the - * daemon. The skill bundle's {@code bin/sonar} launcher sets it to the + * daemon. The distribution's {@code bin/sonar} launcher sets it to the * Java 17+ runtime it auto-discovered, so the daemon launches on a * verified-compatible JVM rather than whichever {@code java} happens to be * on {@code PATH}. Absent, the launcher falls back to the current JVM's @@ -208,7 +208,7 @@ private Process spawn() { *

Plugins directory resolution. The daemon is told where its * analyzer plugins live via {@code -Dsonar.plugins.dir}. The directory is * taken, in order, from: an explicit {@code -Dsonar.plugins.dir} on the - * CLI (the skill bundle's launcher sets this to {@code /plugins}); + * CLI (the distribution's launcher sets this to {@code /plugins}); * else a verified provisioned {@code ~/.sonar//} runtime created * by {@code sonar setup}. With neither, the dev default applies: the * daemon resolves a {@code plugins/} directory relative to its working @@ -235,7 +235,7 @@ static List buildSpawnCommand(Path jar, RuntimeLayout provisioned) { * {@code null} when the daemon should use its working-directory default. * *

An explicit {@code -Dsonar.plugins.dir} on the CLI wins — that is how - * the skill bundle's {@code bin/sonar} launcher points at {@code + * the distribution's {@code bin/sonar} launcher points at {@code * /plugins}. Otherwise a verified provisioned runtime's plugins * directory is used. * diff --git a/cli/src/main/java/dev/sonarcli/cli/DaemonRpc.java b/src/main/java/dev/sonarcli/cli/DaemonRpc.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/DaemonRpc.java rename to src/main/java/dev/sonarcli/cli/DaemonRpc.java diff --git a/cli/src/main/java/dev/sonarcli/cli/FileResolver.java b/src/main/java/dev/sonarcli/cli/FileResolver.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/FileResolver.java rename to src/main/java/dev/sonarcli/cli/FileResolver.java diff --git a/cli/src/main/java/dev/sonarcli/cli/IssueGrouping.java b/src/main/java/dev/sonarcli/cli/IssueGrouping.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/IssueGrouping.java rename to src/main/java/dev/sonarcli/cli/IssueGrouping.java diff --git a/cli/src/main/java/dev/sonarcli/cli/JsonReporter.java b/src/main/java/dev/sonarcli/cli/JsonReporter.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/JsonReporter.java rename to src/main/java/dev/sonarcli/cli/JsonReporter.java diff --git a/cli/src/main/java/dev/sonarcli/cli/LauncherDaemonControl.java b/src/main/java/dev/sonarcli/cli/LauncherDaemonControl.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/LauncherDaemonControl.java rename to src/main/java/dev/sonarcli/cli/LauncherDaemonControl.java diff --git a/cli/src/main/java/dev/sonarcli/cli/Reporter.java b/src/main/java/dev/sonarcli/cli/Reporter.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/Reporter.java rename to src/main/java/dev/sonarcli/cli/Reporter.java diff --git a/cli/src/main/java/dev/sonarcli/cli/RuleMetadataIndex.java b/src/main/java/dev/sonarcli/cli/RuleMetadataIndex.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/RuleMetadataIndex.java rename to src/main/java/dev/sonarcli/cli/RuleMetadataIndex.java diff --git a/cli/src/main/java/dev/sonarcli/cli/SarifReporter.java b/src/main/java/dev/sonarcli/cli/SarifReporter.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/SarifReporter.java rename to src/main/java/dev/sonarcli/cli/SarifReporter.java diff --git a/cli/src/main/java/dev/sonarcli/cli/Severity.java b/src/main/java/dev/sonarcli/cli/Severity.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/Severity.java rename to src/main/java/dev/sonarcli/cli/Severity.java diff --git a/cli/src/main/java/dev/sonarcli/cli/SonarCommand.java b/src/main/java/dev/sonarcli/cli/SonarCommand.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/SonarCommand.java rename to src/main/java/dev/sonarcli/cli/SonarCommand.java diff --git a/cli/src/main/java/dev/sonarcli/cli/TextReporter.java b/src/main/java/dev/sonarcli/cli/TextReporter.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/TextReporter.java rename to src/main/java/dev/sonarcli/cli/TextReporter.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/CloverCoverageParser.java b/src/main/java/dev/sonarcli/cli/coverage/CloverCoverageParser.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/CloverCoverageParser.java rename to src/main/java/dev/sonarcli/cli/coverage/CloverCoverageParser.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/CoberturaCoverageParser.java b/src/main/java/dev/sonarcli/cli/coverage/CoberturaCoverageParser.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/CoberturaCoverageParser.java rename to src/main/java/dev/sonarcli/cli/coverage/CoberturaCoverageParser.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/CoverageException.java b/src/main/java/dev/sonarcli/cli/coverage/CoverageException.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/CoverageException.java rename to src/main/java/dev/sonarcli/cli/coverage/CoverageException.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/CoverageFormat.java b/src/main/java/dev/sonarcli/cli/coverage/CoverageFormat.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/CoverageFormat.java rename to src/main/java/dev/sonarcli/cli/coverage/CoverageFormat.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/CoverageImporter.java b/src/main/java/dev/sonarcli/cli/coverage/CoverageImporter.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/CoverageImporter.java rename to src/main/java/dev/sonarcli/cli/coverage/CoverageImporter.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/CoverageParser.java b/src/main/java/dev/sonarcli/cli/coverage/CoverageParser.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/CoverageParser.java rename to src/main/java/dev/sonarcli/cli/coverage/CoverageParser.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/CoverageReport.java b/src/main/java/dev/sonarcli/cli/coverage/CoverageReport.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/CoverageReport.java rename to src/main/java/dev/sonarcli/cli/coverage/CoverageReport.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/CoverageXml.java b/src/main/java/dev/sonarcli/cli/coverage/CoverageXml.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/CoverageXml.java rename to src/main/java/dev/sonarcli/cli/coverage/CoverageXml.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/FileCoverage.java b/src/main/java/dev/sonarcli/cli/coverage/FileCoverage.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/FileCoverage.java rename to src/main/java/dev/sonarcli/cli/coverage/FileCoverage.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/GoCoverageParser.java b/src/main/java/dev/sonarcli/cli/coverage/GoCoverageParser.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/GoCoverageParser.java rename to src/main/java/dev/sonarcli/cli/coverage/GoCoverageParser.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/JacocoCoverageParser.java b/src/main/java/dev/sonarcli/cli/coverage/JacocoCoverageParser.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/JacocoCoverageParser.java rename to src/main/java/dev/sonarcli/cli/coverage/JacocoCoverageParser.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/LcovCoverageParser.java b/src/main/java/dev/sonarcli/cli/coverage/LcovCoverageParser.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/LcovCoverageParser.java rename to src/main/java/dev/sonarcli/cli/coverage/LcovCoverageParser.java diff --git a/cli/src/main/java/dev/sonarcli/cli/coverage/SimpleCovCoverageParser.java b/src/main/java/dev/sonarcli/cli/coverage/SimpleCovCoverageParser.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/coverage/SimpleCovCoverageParser.java rename to src/main/java/dev/sonarcli/cli/coverage/SimpleCovCoverageParser.java diff --git a/cli/src/main/java/dev/sonarcli/cli/setup/DownloadException.java b/src/main/java/dev/sonarcli/cli/setup/DownloadException.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/setup/DownloadException.java rename to src/main/java/dev/sonarcli/cli/setup/DownloadException.java diff --git a/cli/src/main/java/dev/sonarcli/cli/setup/Downloader.java b/src/main/java/dev/sonarcli/cli/setup/Downloader.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/setup/Downloader.java rename to src/main/java/dev/sonarcli/cli/setup/Downloader.java diff --git a/cli/src/main/java/dev/sonarcli/cli/setup/Manifest.java b/src/main/java/dev/sonarcli/cli/setup/Manifest.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/setup/Manifest.java rename to src/main/java/dev/sonarcli/cli/setup/Manifest.java diff --git a/cli/src/main/java/dev/sonarcli/cli/setup/PluginProvisioner.java b/src/main/java/dev/sonarcli/cli/setup/PluginProvisioner.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/setup/PluginProvisioner.java rename to src/main/java/dev/sonarcli/cli/setup/PluginProvisioner.java diff --git a/cli/src/main/java/dev/sonarcli/cli/setup/RuntimeLayout.java b/src/main/java/dev/sonarcli/cli/setup/RuntimeLayout.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/setup/RuntimeLayout.java rename to src/main/java/dev/sonarcli/cli/setup/RuntimeLayout.java diff --git a/cli/src/main/java/dev/sonarcli/cli/setup/SetupCommand.java b/src/main/java/dev/sonarcli/cli/setup/SetupCommand.java similarity index 95% rename from cli/src/main/java/dev/sonarcli/cli/setup/SetupCommand.java rename to src/main/java/dev/sonarcli/cli/setup/SetupCommand.java index 55000b3..16359fa 100644 --- a/cli/src/main/java/dev/sonarcli/cli/setup/SetupCommand.java +++ b/src/main/java/dev/sonarcli/cli/setup/SetupCommand.java @@ -19,7 +19,7 @@ * After {@code setup} the tool makes no network calls. * *

Options. {@code --repo } substitutes a Maven mirror for the - * plugin/engine downloads; {@code --offline } provisions the whole + * analyzer/engine downloads; {@code --offline } provisions the whole * runtime from a local {@code .tar.gz} bundle with no network at all. * *

Exit codes. {@code 0} on success; {@code 2} on any provisioning @@ -42,7 +42,7 @@ public final class SetupCommand implements Callable { public record RunnerInputs(Manifest manifest, String repoBase, RuntimeLayout layout) {} @Option(names = "--repo", paramLabel = "URL", - description = "Maven repository base URL for plugin/engine downloads.") + description = "Maven repository base URL for analyzer/engine downloads.") private String repo = PluginProvisioner.MAVEN_CENTRAL; @Option(names = "--offline", paramLabel = "ARCHIVE", diff --git a/cli/src/main/java/dev/sonarcli/cli/setup/SetupRunner.java b/src/main/java/dev/sonarcli/cli/setup/SetupRunner.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/setup/SetupRunner.java rename to src/main/java/dev/sonarcli/cli/setup/SetupRunner.java diff --git a/cli/src/main/java/dev/sonarcli/cli/setup/Tar.java b/src/main/java/dev/sonarcli/cli/setup/Tar.java similarity index 100% rename from cli/src/main/java/dev/sonarcli/cli/setup/Tar.java rename to src/main/java/dev/sonarcli/cli/setup/Tar.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/AnalysisService.java b/src/main/java/dev/sonarcli/daemon/AnalysisService.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/AnalysisService.java rename to src/main/java/dev/sonarcli/daemon/AnalysisService.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/Daemon.java b/src/main/java/dev/sonarcli/daemon/Daemon.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/Daemon.java rename to src/main/java/dev/sonarcli/daemon/Daemon.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/DaemonMain.java b/src/main/java/dev/sonarcli/daemon/DaemonMain.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/DaemonMain.java rename to src/main/java/dev/sonarcli/daemon/DaemonMain.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/DaemonServer.java b/src/main/java/dev/sonarcli/daemon/DaemonServer.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/DaemonServer.java rename to src/main/java/dev/sonarcli/daemon/DaemonServer.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/DaemonVersion.java b/src/main/java/dev/sonarcli/daemon/DaemonVersion.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/DaemonVersion.java rename to src/main/java/dev/sonarcli/daemon/DaemonVersion.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/EngineLog.java b/src/main/java/dev/sonarcli/daemon/EngineLog.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/EngineLog.java rename to src/main/java/dev/sonarcli/daemon/EngineLog.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/FileInputFile.java b/src/main/java/dev/sonarcli/daemon/FileInputFile.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/FileInputFile.java rename to src/main/java/dev/sonarcli/daemon/FileInputFile.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/IssueMapper.java b/src/main/java/dev/sonarcli/daemon/IssueMapper.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/IssueMapper.java rename to src/main/java/dev/sonarcli/daemon/IssueMapper.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/LanguageDetector.java b/src/main/java/dev/sonarcli/daemon/LanguageDetector.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/LanguageDetector.java rename to src/main/java/dev/sonarcli/daemon/LanguageDetector.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/PluginRuntime.java b/src/main/java/dev/sonarcli/daemon/PluginRuntime.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/PluginRuntime.java rename to src/main/java/dev/sonarcli/daemon/PluginRuntime.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/PluginsDir.java b/src/main/java/dev/sonarcli/daemon/PluginsDir.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/PluginsDir.java rename to src/main/java/dev/sonarcli/daemon/PluginsDir.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/QualityProfile.java b/src/main/java/dev/sonarcli/daemon/QualityProfile.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/QualityProfile.java rename to src/main/java/dev/sonarcli/daemon/QualityProfile.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/QualityProfileException.java b/src/main/java/dev/sonarcli/daemon/QualityProfileException.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/QualityProfileException.java rename to src/main/java/dev/sonarcli/daemon/QualityProfileException.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/RequestDispatcher.java b/src/main/java/dev/sonarcli/daemon/RequestDispatcher.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/RequestDispatcher.java rename to src/main/java/dev/sonarcli/daemon/RequestDispatcher.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/RuleCatalog.java b/src/main/java/dev/sonarcli/daemon/RuleCatalog.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/RuleCatalog.java rename to src/main/java/dev/sonarcli/daemon/RuleCatalog.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/RuleParameterDefaults.java b/src/main/java/dev/sonarcli/daemon/RuleParameterDefaults.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/RuleParameterDefaults.java rename to src/main/java/dev/sonarcli/daemon/RuleParameterDefaults.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/SonarWayProfiles.java b/src/main/java/dev/sonarcli/daemon/SonarWayProfiles.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/SonarWayProfiles.java rename to src/main/java/dev/sonarcli/daemon/SonarWayProfiles.java diff --git a/daemon/src/main/java/dev/sonarcli/daemon/TestPathDetector.java b/src/main/java/dev/sonarcli/daemon/TestPathDetector.java similarity index 100% rename from daemon/src/main/java/dev/sonarcli/daemon/TestPathDetector.java rename to src/main/java/dev/sonarcli/daemon/TestPathDetector.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/Json.java b/src/main/java/dev/sonarcli/protocol/Json.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/Json.java rename to src/main/java/dev/sonarcli/protocol/Json.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/MessageCodec.java b/src/main/java/dev/sonarcli/protocol/MessageCodec.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/MessageCodec.java rename to src/main/java/dev/sonarcli/protocol/MessageCodec.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/Method.java b/src/main/java/dev/sonarcli/protocol/Method.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/Method.java rename to src/main/java/dev/sonarcli/protocol/Method.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/ProtocolException.java b/src/main/java/dev/sonarcli/protocol/ProtocolException.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/ProtocolException.java rename to src/main/java/dev/sonarcli/protocol/ProtocolException.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/SocketPaths.java b/src/main/java/dev/sonarcli/protocol/SocketPaths.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/SocketPaths.java rename to src/main/java/dev/sonarcli/protocol/SocketPaths.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/WireMessage.java b/src/main/java/dev/sonarcli/protocol/WireMessage.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/WireMessage.java rename to src/main/java/dev/sonarcli/protocol/WireMessage.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/dto/AnalysisWarning.java b/src/main/java/dev/sonarcli/protocol/dto/AnalysisWarning.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/dto/AnalysisWarning.java rename to src/main/java/dev/sonarcli/protocol/dto/AnalysisWarning.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/dto/AnalyzeRequest.java b/src/main/java/dev/sonarcli/protocol/dto/AnalyzeRequest.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/dto/AnalyzeRequest.java rename to src/main/java/dev/sonarcli/protocol/dto/AnalyzeRequest.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/dto/AnalyzeResponse.java b/src/main/java/dev/sonarcli/protocol/dto/AnalyzeResponse.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/dto/AnalyzeResponse.java rename to src/main/java/dev/sonarcli/protocol/dto/AnalyzeResponse.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/dto/Issue.java b/src/main/java/dev/sonarcli/protocol/dto/Issue.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/dto/Issue.java rename to src/main/java/dev/sonarcli/protocol/dto/Issue.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/dto/PingResponse.java b/src/main/java/dev/sonarcli/protocol/dto/PingResponse.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/dto/PingResponse.java rename to src/main/java/dev/sonarcli/protocol/dto/PingResponse.java diff --git a/protocol/src/main/java/dev/sonarcli/protocol/dto/RuleMetadata.java b/src/main/java/dev/sonarcli/protocol/dto/RuleMetadata.java similarity index 100% rename from protocol/src/main/java/dev/sonarcli/protocol/dto/RuleMetadata.java rename to src/main/java/dev/sonarcli/protocol/dto/RuleMetadata.java diff --git a/cli/src/main/resources/manifest.json b/src/main/resources/manifest.json similarity index 100% rename from cli/src/main/resources/manifest.json rename to src/main/resources/manifest.json diff --git a/dist/src/main/scripts/sonar b/src/main/staging/bin/sonar similarity index 95% rename from dist/src/main/scripts/sonar rename to src/main/staging/bin/sonar index 3ec7166..bb95d95 100644 --- a/dist/src/main/scripts/sonar +++ b/src/main/staging/bin/sonar @@ -1,5 +1,5 @@ #!/bin/sh -# sonar-predictor launcher — self-contained agent skill entry point. +# sonar-predictor launcher — self-contained distribution entry point. # # Auto-discovers a Java 17+ runtime so neither the agent nor the user has to # set JAVA_HOME or put a compatible java on PATH. Then runs the bundled CLI, @@ -29,7 +29,7 @@ DAEMON_JAR="$BUNDLE_DIR/lib/sonar-predictor-daemon.jar" PLUGINS_DIR="$BUNDLE_DIR/plugins" if [ ! -f "$CLI_JAR" ]; then - echo "sonar-predictor: missing $CLI_JAR — the skill bundle is incomplete." >&2 + echo "sonar-predictor: missing $CLI_JAR — the distribution bundle is incomplete." >&2 exit 2 fi diff --git a/dist/src/main/scripts/sonar.bat b/src/main/staging/bin/sonar.bat similarity index 91% rename from dist/src/main/scripts/sonar.bat rename to src/main/staging/bin/sonar.bat index ab2485d..0341797 100644 --- a/dist/src/main/scripts/sonar.bat +++ b/src/main/staging/bin/sonar.bat @@ -1,6 +1,6 @@ @echo off setlocal EnableDelayedExpansion -rem sonar-predictor launcher (Windows) — self-contained agent skill entry point. +rem sonar-predictor launcher (Windows) — self-contained distribution entry point. rem rem Auto-discovers a Java 17+ runtime so no JAVA_HOME / PATH setup is required, rem then runs the bundled CLI with the bundle's jar/plugin locations passed in. @@ -8,7 +8,7 @@ rem rem TODO(windows): the daemon's IPC uses a Unix domain socket path; full rem Windows support needs a named-pipe / AF_UNIX-on-Windows transport in the rem protocol + daemon modules. This launcher is provided best-effort so the -rem skill bundle is shape-complete; daemon-backed analysis on Windows is not +rem distribution bundle is shape-complete; daemon-backed analysis on Windows is not rem yet verified. set "SCRIPT_DIR=%~dp0" @@ -19,7 +19,7 @@ set "DAEMON_JAR=%BUNDLE_DIR%\lib\sonar-predictor-daemon.jar" set "PLUGINS_DIR=%BUNDLE_DIR%\plugins" if not exist "%CLI_JAR%" ( - echo sonar-predictor: missing %CLI_JAR% - the skill bundle is incomplete. 1>&2 + echo sonar-predictor: missing %CLI_JAR% - the distribution bundle is incomplete. 1>&2 exit /b 2 ) diff --git a/cli/src/test/java/dev/sonarcli/cli/CliIntegrationTest.java b/src/test/java/dev/sonarcli/cli/CliIntegrationTest.java similarity index 99% rename from cli/src/test/java/dev/sonarcli/cli/CliIntegrationTest.java rename to src/test/java/dev/sonarcli/cli/CliIntegrationTest.java index c13b5d3..cd229bb 100644 --- a/cli/src/test/java/dev/sonarcli/cli/CliIntegrationTest.java +++ b/src/test/java/dev/sonarcli/cli/CliIntegrationTest.java @@ -33,7 +33,7 @@ class CliIntegrationTest { private static final Path FIXTURES = - Path.of("src/test/resources/fixtures").toAbsolutePath(); + Path.of("src/test/resources/cli/fixtures").toAbsolutePath(); private SocketPaths paths; private DaemonLauncher launcher; diff --git a/cli/src/test/java/dev/sonarcli/cli/CommandTest.java b/src/test/java/dev/sonarcli/cli/CommandTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/CommandTest.java rename to src/test/java/dev/sonarcli/cli/CommandTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/CoverageCliTest.java b/src/test/java/dev/sonarcli/cli/CoverageCliTest.java similarity index 99% rename from cli/src/test/java/dev/sonarcli/cli/CoverageCliTest.java rename to src/test/java/dev/sonarcli/cli/CoverageCliTest.java index 939b22a..7fe9e1d 100644 --- a/cli/src/test/java/dev/sonarcli/cli/CoverageCliTest.java +++ b/src/test/java/dev/sonarcli/cli/CoverageCliTest.java @@ -33,7 +33,7 @@ class CoverageCliTest { private static final Path COVERAGE_FIXTURES = - Path.of("src/test/resources/fixtures/coverage").toAbsolutePath(); + Path.of("src/test/resources/cli/fixtures/coverage").toAbsolutePath(); /** A stub daemon returning a fixed analyze result. */ private static final class StubRpc implements DaemonRpc { diff --git a/cli/src/test/java/dev/sonarcli/cli/DaemonClientTest.java b/src/test/java/dev/sonarcli/cli/DaemonClientTest.java similarity index 98% rename from cli/src/test/java/dev/sonarcli/cli/DaemonClientTest.java rename to src/test/java/dev/sonarcli/cli/DaemonClientTest.java index 21f44fe..9bfcfbc 100644 --- a/cli/src/test/java/dev/sonarcli/cli/DaemonClientTest.java +++ b/src/test/java/dev/sonarcli/cli/DaemonClientTest.java @@ -36,7 +36,7 @@ class DaemonClientTest { private static final Path FIXTURES = - Path.of("src/test/resources/fixtures").toAbsolutePath(); + Path.of("src/test/resources/cli/fixtures").toAbsolutePath(); @Test @DisplayName("ping() returns a PingResponse from a running daemon") diff --git a/cli/src/test/java/dev/sonarcli/cli/DaemonLauncherTest.java b/src/test/java/dev/sonarcli/cli/DaemonLauncherTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/DaemonLauncherTest.java rename to src/test/java/dev/sonarcli/cli/DaemonLauncherTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/FileResolverTest.java b/src/test/java/dev/sonarcli/cli/FileResolverTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/FileResolverTest.java rename to src/test/java/dev/sonarcli/cli/FileResolverTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/HelpTest.java b/src/test/java/dev/sonarcli/cli/HelpTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/HelpTest.java rename to src/test/java/dev/sonarcli/cli/HelpTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/InstallHookCommandTest.java b/src/test/java/dev/sonarcli/cli/InstallHookCommandTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/InstallHookCommandTest.java rename to src/test/java/dev/sonarcli/cli/InstallHookCommandTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/IssueGroupingTest.java b/src/test/java/dev/sonarcli/cli/IssueGroupingTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/IssueGroupingTest.java rename to src/test/java/dev/sonarcli/cli/IssueGroupingTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/ReportersTest.java b/src/test/java/dev/sonarcli/cli/ReportersTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/ReportersTest.java rename to src/test/java/dev/sonarcli/cli/ReportersTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/RuleMetadataIndexTest.java b/src/test/java/dev/sonarcli/cli/RuleMetadataIndexTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/RuleMetadataIndexTest.java rename to src/test/java/dev/sonarcli/cli/RuleMetadataIndexTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/RulesCommandTest.java b/src/test/java/dev/sonarcli/cli/RulesCommandTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/RulesCommandTest.java rename to src/test/java/dev/sonarcli/cli/RulesCommandTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/SarifReporterTest.java b/src/test/java/dev/sonarcli/cli/SarifReporterTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/SarifReporterTest.java rename to src/test/java/dev/sonarcli/cli/SarifReporterTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/coverage/CloverSimplecovParsersTest.java b/src/test/java/dev/sonarcli/cli/coverage/CloverSimplecovParsersTest.java similarity index 98% rename from cli/src/test/java/dev/sonarcli/cli/coverage/CloverSimplecovParsersTest.java rename to src/test/java/dev/sonarcli/cli/coverage/CloverSimplecovParsersTest.java index 8985b9f..2e82022 100644 --- a/cli/src/test/java/dev/sonarcli/cli/coverage/CloverSimplecovParsersTest.java +++ b/src/test/java/dev/sonarcli/cli/coverage/CloverSimplecovParsersTest.java @@ -18,7 +18,7 @@ class CloverSimplecovParsersTest { private static final Path FIXTURES = - Path.of("src/test/resources/fixtures/coverage").toAbsolutePath(); + Path.of("src/test/resources/cli/fixtures/coverage").toAbsolutePath(); @Test @DisplayName("Clover parser counts only type=stmt lines; covered when count > 0") diff --git a/cli/src/test/java/dev/sonarcli/cli/coverage/CoverageFormatTest.java b/src/test/java/dev/sonarcli/cli/coverage/CoverageFormatTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/coverage/CoverageFormatTest.java rename to src/test/java/dev/sonarcli/cli/coverage/CoverageFormatTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/coverage/CoverageImporterTest.java b/src/test/java/dev/sonarcli/cli/coverage/CoverageImporterTest.java similarity index 98% rename from cli/src/test/java/dev/sonarcli/cli/coverage/CoverageImporterTest.java rename to src/test/java/dev/sonarcli/cli/coverage/CoverageImporterTest.java index 3910225..65b94a0 100644 --- a/cli/src/test/java/dev/sonarcli/cli/coverage/CoverageImporterTest.java +++ b/src/test/java/dev/sonarcli/cli/coverage/CoverageImporterTest.java @@ -21,7 +21,7 @@ class CoverageImporterTest { private static final Path FIXTURES = - Path.of("src/test/resources/fixtures/coverage").toAbsolutePath(); + Path.of("src/test/resources/cli/fixtures/coverage").toAbsolutePath(); @Test @DisplayName("imports a single report by detecting and dispatching to its parser") diff --git a/cli/src/test/java/dev/sonarcli/cli/coverage/TextCoverageParsersTest.java b/src/test/java/dev/sonarcli/cli/coverage/TextCoverageParsersTest.java similarity index 98% rename from cli/src/test/java/dev/sonarcli/cli/coverage/TextCoverageParsersTest.java rename to src/test/java/dev/sonarcli/cli/coverage/TextCoverageParsersTest.java index 91ca571..7ec5897 100644 --- a/cli/src/test/java/dev/sonarcli/cli/coverage/TextCoverageParsersTest.java +++ b/src/test/java/dev/sonarcli/cli/coverage/TextCoverageParsersTest.java @@ -18,7 +18,7 @@ class TextCoverageParsersTest { private static final Path FIXTURES = - Path.of("src/test/resources/fixtures/coverage").toAbsolutePath(); + Path.of("src/test/resources/cli/fixtures/coverage").toAbsolutePath(); @Test @DisplayName("LCOV parser counts DA records: coverable = all, covered = hits > 0") diff --git a/cli/src/test/java/dev/sonarcli/cli/coverage/XmlCoverageParsersTest.java b/src/test/java/dev/sonarcli/cli/coverage/XmlCoverageParsersTest.java similarity index 97% rename from cli/src/test/java/dev/sonarcli/cli/coverage/XmlCoverageParsersTest.java rename to src/test/java/dev/sonarcli/cli/coverage/XmlCoverageParsersTest.java index d228ea2..2102dff 100644 --- a/cli/src/test/java/dev/sonarcli/cli/coverage/XmlCoverageParsersTest.java +++ b/src/test/java/dev/sonarcli/cli/coverage/XmlCoverageParsersTest.java @@ -17,7 +17,7 @@ class XmlCoverageParsersTest { private static final Path FIXTURES = - Path.of("src/test/resources/fixtures/coverage").toAbsolutePath(); + Path.of("src/test/resources/cli/fixtures/coverage").toAbsolutePath(); @Test @DisplayName("JaCoCo parser reads per-file LINE counters into covered/coverable counts") diff --git a/cli/src/test/java/dev/sonarcli/cli/setup/DownloaderTest.java b/src/test/java/dev/sonarcli/cli/setup/DownloaderTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/setup/DownloaderTest.java rename to src/test/java/dev/sonarcli/cli/setup/DownloaderTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/setup/ManifestTest.java b/src/test/java/dev/sonarcli/cli/setup/ManifestTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/setup/ManifestTest.java rename to src/test/java/dev/sonarcli/cli/setup/ManifestTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/setup/PluginProvisionerTest.java b/src/test/java/dev/sonarcli/cli/setup/PluginProvisionerTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/setup/PluginProvisionerTest.java rename to src/test/java/dev/sonarcli/cli/setup/PluginProvisionerTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/setup/RuntimeLayoutTest.java b/src/test/java/dev/sonarcli/cli/setup/RuntimeLayoutTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/setup/RuntimeLayoutTest.java rename to src/test/java/dev/sonarcli/cli/setup/RuntimeLayoutTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/setup/SetupCommandTest.java b/src/test/java/dev/sonarcli/cli/setup/SetupCommandTest.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/setup/SetupCommandTest.java rename to src/test/java/dev/sonarcli/cli/setup/SetupCommandTest.java diff --git a/cli/src/test/java/dev/sonarcli/cli/setup/TarWriter.java b/src/test/java/dev/sonarcli/cli/setup/TarWriter.java similarity index 100% rename from cli/src/test/java/dev/sonarcli/cli/setup/TarWriter.java rename to src/test/java/dev/sonarcli/cli/setup/TarWriter.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/AnalysisServiceTest.java b/src/test/java/dev/sonarcli/daemon/AnalysisServiceTest.java similarity index 99% rename from daemon/src/test/java/dev/sonarcli/daemon/AnalysisServiceTest.java rename to src/test/java/dev/sonarcli/daemon/AnalysisServiceTest.java index 40ae64f..deda033 100644 --- a/daemon/src/test/java/dev/sonarcli/daemon/AnalysisServiceTest.java +++ b/src/test/java/dev/sonarcli/daemon/AnalysisServiceTest.java @@ -18,7 +18,7 @@ class AnalysisServiceTest { /** Fixture root, relative to the daemon module root. */ - private static final Path FIXTURES = Paths.get("src/test/resources/fixtures"); + private static final Path FIXTURES = Paths.get("src/test/resources/daemon/fixtures"); private static final Set VALID_SEVERITIES = Set.of("BLOCKER", "CRITICAL", "MAJOR", "MINOR", "INFO"); diff --git a/daemon/src/test/java/dev/sonarcli/daemon/DaemonIntegrationTest.java b/src/test/java/dev/sonarcli/daemon/DaemonIntegrationTest.java similarity index 99% rename from daemon/src/test/java/dev/sonarcli/daemon/DaemonIntegrationTest.java rename to src/test/java/dev/sonarcli/daemon/DaemonIntegrationTest.java index 1334303..8cea623 100644 --- a/daemon/src/test/java/dev/sonarcli/daemon/DaemonIntegrationTest.java +++ b/src/test/java/dev/sonarcli/daemon/DaemonIntegrationTest.java @@ -41,7 +41,7 @@ */ class DaemonIntegrationTest { - private static final Path FIXTURES = Path.of("src/test/resources/fixtures"); + private static final Path FIXTURES = Path.of("src/test/resources/daemon/fixtures"); @Test @DisplayName("ping, analyze, rule-metadata, shutdown over one Unix-socket connection") diff --git a/daemon/src/test/java/dev/sonarcli/daemon/DaemonMainTest.java b/src/test/java/dev/sonarcli/daemon/DaemonMainTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/DaemonMainTest.java rename to src/test/java/dev/sonarcli/daemon/DaemonMainTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/DaemonServerTest.java b/src/test/java/dev/sonarcli/daemon/DaemonServerTest.java similarity index 99% rename from daemon/src/test/java/dev/sonarcli/daemon/DaemonServerTest.java rename to src/test/java/dev/sonarcli/daemon/DaemonServerTest.java index 6bb7a48..d6324f9 100644 --- a/daemon/src/test/java/dev/sonarcli/daemon/DaemonServerTest.java +++ b/src/test/java/dev/sonarcli/daemon/DaemonServerTest.java @@ -36,7 +36,7 @@ class DaemonServerTest { /** Generous idle timeout: long enough that no test trips it accidentally. */ private static final Duration LONG_IDLE = Duration.ofMinutes(10); - private static final Path FIXTURES = Path.of("src/test/resources/fixtures"); + private static final Path FIXTURES = Path.of("src/test/resources/daemon/fixtures"); private static AnalysisService service; diff --git a/daemon/src/test/java/dev/sonarcli/daemon/EngineLogTest.java b/src/test/java/dev/sonarcli/daemon/EngineLogTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/EngineLogTest.java rename to src/test/java/dev/sonarcli/daemon/EngineLogTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/FileInputFileTest.java b/src/test/java/dev/sonarcli/daemon/FileInputFileTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/FileInputFileTest.java rename to src/test/java/dev/sonarcli/daemon/FileInputFileTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/IssueMapperTest.java b/src/test/java/dev/sonarcli/daemon/IssueMapperTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/IssueMapperTest.java rename to src/test/java/dev/sonarcli/daemon/IssueMapperTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/LanguageDetectorTest.java b/src/test/java/dev/sonarcli/daemon/LanguageDetectorTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/LanguageDetectorTest.java rename to src/test/java/dev/sonarcli/daemon/LanguageDetectorTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/PluginRuntimeTest.java b/src/test/java/dev/sonarcli/daemon/PluginRuntimeTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/PluginRuntimeTest.java rename to src/test/java/dev/sonarcli/daemon/PluginRuntimeTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/PluginsDirTest.java b/src/test/java/dev/sonarcli/daemon/PluginsDirTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/PluginsDirTest.java rename to src/test/java/dev/sonarcli/daemon/PluginsDirTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/QualityProfileTest.java b/src/test/java/dev/sonarcli/daemon/QualityProfileTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/QualityProfileTest.java rename to src/test/java/dev/sonarcli/daemon/QualityProfileTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/RequestDispatcherTest.java b/src/test/java/dev/sonarcli/daemon/RequestDispatcherTest.java similarity index 99% rename from daemon/src/test/java/dev/sonarcli/daemon/RequestDispatcherTest.java rename to src/test/java/dev/sonarcli/daemon/RequestDispatcherTest.java index 72952ef..ad7352d 100644 --- a/daemon/src/test/java/dev/sonarcli/daemon/RequestDispatcherTest.java +++ b/src/test/java/dev/sonarcli/daemon/RequestDispatcherTest.java @@ -27,7 +27,7 @@ class RequestDispatcherTest { - private static final Path FIXTURES = Paths.get("src/test/resources/fixtures"); + private static final Path FIXTURES = Paths.get("src/test/resources/daemon/fixtures"); private static AnalysisService service; diff --git a/daemon/src/test/java/dev/sonarcli/daemon/RuleCatalogTest.java b/src/test/java/dev/sonarcli/daemon/RuleCatalogTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/RuleCatalogTest.java rename to src/test/java/dev/sonarcli/daemon/RuleCatalogTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/RuleParameterDefaultsTest.java b/src/test/java/dev/sonarcli/daemon/RuleParameterDefaultsTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/RuleParameterDefaultsTest.java rename to src/test/java/dev/sonarcli/daemon/RuleParameterDefaultsTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/SonarWayProfilesTest.java b/src/test/java/dev/sonarcli/daemon/SonarWayProfilesTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/SonarWayProfilesTest.java rename to src/test/java/dev/sonarcli/daemon/SonarWayProfilesTest.java diff --git a/daemon/src/test/java/dev/sonarcli/daemon/TestPathDetectorTest.java b/src/test/java/dev/sonarcli/daemon/TestPathDetectorTest.java similarity index 100% rename from daemon/src/test/java/dev/sonarcli/daemon/TestPathDetectorTest.java rename to src/test/java/dev/sonarcli/daemon/TestPathDetectorTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/JsonTest.java b/src/test/java/dev/sonarcli/protocol/JsonTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/JsonTest.java rename to src/test/java/dev/sonarcli/protocol/JsonTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/MessageCodecEdgeCasesTest.java b/src/test/java/dev/sonarcli/protocol/MessageCodecEdgeCasesTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/MessageCodecEdgeCasesTest.java rename to src/test/java/dev/sonarcli/protocol/MessageCodecEdgeCasesTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/MessageCodecTest.java b/src/test/java/dev/sonarcli/protocol/MessageCodecTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/MessageCodecTest.java rename to src/test/java/dev/sonarcli/protocol/MessageCodecTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/MethodTest.java b/src/test/java/dev/sonarcli/protocol/MethodTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/MethodTest.java rename to src/test/java/dev/sonarcli/protocol/MethodTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/SocketPathsTest.java b/src/test/java/dev/sonarcli/protocol/SocketPathsTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/SocketPathsTest.java rename to src/test/java/dev/sonarcli/protocol/SocketPathsTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/WireMessageTest.java b/src/test/java/dev/sonarcli/protocol/WireMessageTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/WireMessageTest.java rename to src/test/java/dev/sonarcli/protocol/WireMessageTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/dto/AnalysisWarningTest.java b/src/test/java/dev/sonarcli/protocol/dto/AnalysisWarningTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/dto/AnalysisWarningTest.java rename to src/test/java/dev/sonarcli/protocol/dto/AnalysisWarningTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/dto/AnalyzeRequestTest.java b/src/test/java/dev/sonarcli/protocol/dto/AnalyzeRequestTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/dto/AnalyzeRequestTest.java rename to src/test/java/dev/sonarcli/protocol/dto/AnalyzeRequestTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/dto/AnalyzeResponseTest.java b/src/test/java/dev/sonarcli/protocol/dto/AnalyzeResponseTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/dto/AnalyzeResponseTest.java rename to src/test/java/dev/sonarcli/protocol/dto/AnalyzeResponseTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/dto/IssueTest.java b/src/test/java/dev/sonarcli/protocol/dto/IssueTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/dto/IssueTest.java rename to src/test/java/dev/sonarcli/protocol/dto/IssueTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/dto/PingResponseTest.java b/src/test/java/dev/sonarcli/protocol/dto/PingResponseTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/dto/PingResponseTest.java rename to src/test/java/dev/sonarcli/protocol/dto/PingResponseTest.java diff --git a/protocol/src/test/java/dev/sonarcli/protocol/dto/RuleMetadataTest.java b/src/test/java/dev/sonarcli/protocol/dto/RuleMetadataTest.java similarity index 100% rename from protocol/src/test/java/dev/sonarcli/protocol/dto/RuleMetadataTest.java rename to src/test/java/dev/sonarcli/protocol/dto/RuleMetadataTest.java diff --git a/cli/src/test/resources/fixtures/coverage/.resultset.json b/src/test/resources/cli/fixtures/coverage/.resultset.json similarity index 100% rename from cli/src/test/resources/fixtures/coverage/.resultset.json rename to src/test/resources/cli/fixtures/coverage/.resultset.json diff --git a/cli/src/test/resources/fixtures/coverage/clover.xml b/src/test/resources/cli/fixtures/coverage/clover.xml similarity index 100% rename from cli/src/test/resources/fixtures/coverage/clover.xml rename to src/test/resources/cli/fixtures/coverage/clover.xml diff --git a/cli/src/test/resources/fixtures/coverage/cobertura.xml b/src/test/resources/cli/fixtures/coverage/cobertura.xml similarity index 100% rename from cli/src/test/resources/fixtures/coverage/cobertura.xml rename to src/test/resources/cli/fixtures/coverage/cobertura.xml diff --git a/cli/src/test/resources/fixtures/coverage/go-cover.out b/src/test/resources/cli/fixtures/coverage/go-cover.out similarity index 100% rename from cli/src/test/resources/fixtures/coverage/go-cover.out rename to src/test/resources/cli/fixtures/coverage/go-cover.out diff --git a/cli/src/test/resources/fixtures/coverage/jacoco.xml b/src/test/resources/cli/fixtures/coverage/jacoco.xml similarity index 100% rename from cli/src/test/resources/fixtures/coverage/jacoco.xml rename to src/test/resources/cli/fixtures/coverage/jacoco.xml diff --git a/cli/src/test/resources/fixtures/coverage/lcov.info b/src/test/resources/cli/fixtures/coverage/lcov.info similarity index 100% rename from cli/src/test/resources/fixtures/coverage/lcov.info rename to src/test/resources/cli/fixtures/coverage/lcov.info diff --git a/cli/src/test/resources/fixtures/java/Clean.java b/src/test/resources/cli/fixtures/java/Clean.java similarity index 100% rename from cli/src/test/resources/fixtures/java/Clean.java rename to src/test/resources/cli/fixtures/java/Clean.java diff --git a/cli/src/test/resources/fixtures/java/ConsolePrinter.java b/src/test/resources/cli/fixtures/java/ConsolePrinter.java similarity index 100% rename from cli/src/test/resources/fixtures/java/ConsolePrinter.java rename to src/test/resources/cli/fixtures/java/ConsolePrinter.java diff --git a/cli/src/test/resources/fixtures/java/UtilityClass.java b/src/test/resources/cli/fixtures/java/UtilityClass.java similarity index 100% rename from cli/src/test/resources/fixtures/java/UtilityClass.java rename to src/test/resources/cli/fixtures/java/UtilityClass.java diff --git a/cli/src/test/resources/fixtures/profiles/only-s1118.xml b/src/test/resources/cli/fixtures/profiles/only-s1118.xml similarity index 100% rename from cli/src/test/resources/fixtures/profiles/only-s1118.xml rename to src/test/resources/cli/fixtures/profiles/only-s1118.xml diff --git a/daemon/src/test/resources/fixtures/go/bad.go b/src/test/resources/daemon/fixtures/go/bad.go similarity index 100% rename from daemon/src/test/resources/fixtures/go/bad.go rename to src/test/resources/daemon/fixtures/go/bad.go diff --git a/daemon/src/test/resources/fixtures/go/idiomatic.go b/src/test/resources/daemon/fixtures/go/idiomatic.go similarity index 100% rename from daemon/src/test/resources/fixtures/go/idiomatic.go rename to src/test/resources/daemon/fixtures/go/idiomatic.go diff --git a/daemon/src/test/resources/fixtures/java/Clean.java b/src/test/resources/daemon/fixtures/java/Clean.java similarity index 100% rename from daemon/src/test/resources/fixtures/java/Clean.java rename to src/test/resources/daemon/fixtures/java/Clean.java diff --git a/daemon/src/test/resources/fixtures/java/ConsolePrinter.java b/src/test/resources/daemon/fixtures/java/ConsolePrinter.java similarity index 100% rename from daemon/src/test/resources/fixtures/java/ConsolePrinter.java rename to src/test/resources/daemon/fixtures/java/ConsolePrinter.java diff --git a/daemon/src/test/resources/fixtures/java/UtilityClass.java b/src/test/resources/daemon/fixtures/java/UtilityClass.java similarity index 100% rename from daemon/src/test/resources/fixtures/java/UtilityClass.java rename to src/test/resources/daemon/fixtures/java/UtilityClass.java diff --git a/daemon/src/test/resources/fixtures/js/bad.js b/src/test/resources/daemon/fixtures/js/bad.js similarity index 100% rename from daemon/src/test/resources/fixtures/js/bad.js rename to src/test/resources/daemon/fixtures/js/bad.js diff --git a/daemon/src/test/resources/fixtures/python/bad.py b/src/test/resources/daemon/fixtures/python/bad.py similarity index 100% rename from daemon/src/test/resources/fixtures/python/bad.py rename to src/test/resources/daemon/fixtures/python/bad.py diff --git a/daemon/src/test/resources/fixtures/ts/bad.ts b/src/test/resources/daemon/fixtures/ts/bad.ts similarity index 100% rename from daemon/src/test/resources/fixtures/ts/bad.ts rename to src/test/resources/daemon/fixtures/ts/bad.ts From 2c792c2a7e88c16eb5840b1b8ee030b461b53316 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sun, 24 May 2026 04:51:00 +0000 Subject: [PATCH 2/4] fix(build): run jar+shade before test so DaemonLauncher tests find a real jar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI broke on PR #6 with 11 failures + 8 errors all variants of "could not locate the daemon jar". In the old multi-module reactor, daemon-module's package phase produced its jar BEFORE cli-module's test phase ran, so DaemonLauncherTest / DaemonClientTest / CliIntegrationTest could spawn the daemon. Collapsing to a single module broke that ordering: shade ran in `package`, AFTER `test`, so the jar was missing when tests that exec the launcher's resolveDaemonJar() ran. Three coordinated changes restore the invariant: 1. pom.xml — bind maven-jar-plugin's default-jar execution to process-classes, and move both shade executions (shade-cli, shade-daemon) from package to process-test-classes. Result lifecycle: compile → process-classes (primary jar) → test-compile → process-test-classes (shade × 2) → test → … → package Both shaded fat jars exist when DaemonLauncher tests fire. 2. pom.xml — change shade finalName to include the version (sonar-predictor-{cli,daemon}-${project.version}). The output filename matches DAEMON_JAR_PREFIX="sonar-predictor-daemon-" in DaemonLauncher, which test devDefaultResolvesShadedJar already asserts on. The launcher scripts glob the version away so they stay version-agnostic. 3. DaemonLauncher.findDevDefaultJar — search both target/ (single-module layout) and daemon/target/ (legacy multi-module) for the shaded jar. No behaviour change for an old checkout; a new checkout finds the jar at root target/. Adjacent updates: - src/main/assembly/dist.xml: glob `sonar-predictor-{cli,daemon}-*.jar` (versioned names), exclude `original-*.jar` (the unshaded artifact shade also leaves behind). - src/main/staging/bin/sonar: replace hardcoded CLI_JAR/DAEMON_JAR paths with POSIX for-loop globs against lib/sonar-predictor-{cli,daemon}-*.jar. - src/main/staging/bin/sonar.bat: same for Windows (cmd FOR loops). Verify mvn -B -ntp clean verify -Dsurefire.failIfNoSpecifiedTests=false BUILD SUCCESS — 323/323 tests pass target/sonar-predictor-dist-0.2.0-SNAPSHOT.zip contains lib/sonar-predictor-cli-0.2.0-SNAPSHOT.jar lib/sonar-predictor-daemon-0.2.0-SNAPSHOT.jar ./bin/sonar --help → exit 0 --- pom.xml | 28 ++++++++++++++++--- src/main/assembly/dist.xml | 15 ++++++---- .../java/dev/sonarcli/cli/DaemonLauncher.java | 16 +++++++---- src/main/staging/bin/sonar | 16 ++++++++--- src/main/staging/bin/sonar.bat | 16 +++++++++-- 5 files changed, 71 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index df1311f..ce34abf 100644 --- a/pom.xml +++ b/pom.xml @@ -161,6 +161,26 @@ maven-compiler-plugin + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.1 + + + default-jar + process-classes + jar + + + + - sonar-predictor-cli + sonar-predictor-cli-${project.version} true cli @@ -298,10 +318,10 @@ shade-daemon - package + process-test-classes shade - sonar-predictor-daemon + sonar-predictor-daemon-${project.version} true daemon diff --git a/src/main/assembly/dist.xml b/src/main/assembly/dist.xml index 7e17ec3..b156c27 100644 --- a/src/main/assembly/dist.xml +++ b/src/main/assembly/dist.xml @@ -51,16 +51,21 @@ + shade-cli + shade-daemon executions. Their on-disk names are + sonar-predictor-{cli,daemon}-.jar; the launcher + scripts (bin/sonar, bin/sonar.bat) glob lib/sonar-predictor-cli-*.jar + and lib/sonar-predictor-daemon-*.jar to find them. Exclude the + unshaded original-*.jar shade also leaves behind. --> ${project.build.directory} lib - sonar-predictor-cli.jar - sonar-predictor-daemon.jar + sonar-predictor-cli-*.jar + sonar-predictor-daemon-*.jar + + original-*.jar + diff --git a/src/main/java/dev/sonarcli/cli/DaemonLauncher.java b/src/main/java/dev/sonarcli/cli/DaemonLauncher.java index 5917ffa..dac3a43 100644 --- a/src/main/java/dev/sonarcli/cli/DaemonLauncher.java +++ b/src/main/java/dev/sonarcli/cli/DaemonLauncher.java @@ -312,11 +312,17 @@ private static String javaExecutable() { private static Path findDevDefaultJar() { Path dir = Path.of("").toAbsolutePath(); while (dir != null) { - Path target = dir.resolve("daemon").resolve("target"); - if (Files.isDirectory(target)) { - Path jar = newestDaemonJar(target); - if (jar != null) { - return jar; + // Single-module layout: target/sonar-predictor-daemon-*.jar at the + // project root. Legacy multi-module: daemon/target/... — try both + // so a checkout of either generation still resolves. + for (Path candidate : new Path[] { + dir.resolve("target"), + dir.resolve("daemon").resolve("target") }) { + if (Files.isDirectory(candidate)) { + Path jar = newestDaemonJar(candidate); + if (jar != null) { + return jar; + } } } dir = dir.getParent(); diff --git a/src/main/staging/bin/sonar b/src/main/staging/bin/sonar index bb95d95..63d5c7b 100644 --- a/src/main/staging/bin/sonar +++ b/src/main/staging/bin/sonar @@ -24,12 +24,20 @@ done BIN_DIR=$(cd "$(dirname "$SCRIPT")" && pwd) BUNDLE_DIR=$(cd "$BIN_DIR/.." && pwd) -CLI_JAR="$BUNDLE_DIR/lib/sonar-predictor-cli.jar" -DAEMON_JAR="$BUNDLE_DIR/lib/sonar-predictor-daemon.jar" +# The shaded jars carry a version suffix (sonar-predictor-cli-X.Y.Z.jar). +# Glob and pick the first match so the launcher stays version-agnostic. +CLI_JAR="" +for _f in "$BUNDLE_DIR"/lib/sonar-predictor-cli-*.jar; do + [ -f "$_f" ] && { CLI_JAR="$_f"; break; } +done +DAEMON_JAR="" +for _f in "$BUNDLE_DIR"/lib/sonar-predictor-daemon-*.jar; do + [ -f "$_f" ] && { DAEMON_JAR="$_f"; break; } +done PLUGINS_DIR="$BUNDLE_DIR/plugins" -if [ ! -f "$CLI_JAR" ]; then - echo "sonar-predictor: missing $CLI_JAR — the distribution bundle is incomplete." >&2 +if [ -z "$CLI_JAR" ] || [ ! -f "$CLI_JAR" ]; then + echo "sonar-predictor: no sonar-predictor-cli-*.jar found in $BUNDLE_DIR/lib — the distribution bundle is incomplete." >&2 exit 2 fi diff --git a/src/main/staging/bin/sonar.bat b/src/main/staging/bin/sonar.bat index 0341797..7b804c4 100644 --- a/src/main/staging/bin/sonar.bat +++ b/src/main/staging/bin/sonar.bat @@ -14,10 +14,22 @@ rem yet verified. set "SCRIPT_DIR=%~dp0" for %%I in ("%SCRIPT_DIR%..") do set "BUNDLE_DIR=%%~fI" -set "CLI_JAR=%BUNDLE_DIR%\lib\sonar-predictor-cli.jar" -set "DAEMON_JAR=%BUNDLE_DIR%\lib\sonar-predictor-daemon.jar" +rem The shaded jars carry a version suffix (sonar-predictor-cli-X.Y.Z.jar). +rem Glob and pick the first match so the launcher stays version-agnostic. +set "CLI_JAR=" +for %%F in ("%BUNDLE_DIR%\lib\sonar-predictor-cli-*.jar") do ( + if not defined CLI_JAR set "CLI_JAR=%%~fF" +) +set "DAEMON_JAR=" +for %%F in ("%BUNDLE_DIR%\lib\sonar-predictor-daemon-*.jar") do ( + if not defined DAEMON_JAR set "DAEMON_JAR=%%~fF" +) set "PLUGINS_DIR=%BUNDLE_DIR%\plugins" +if not defined CLI_JAR ( + echo sonar-predictor: no sonar-predictor-cli-*.jar found in %BUNDLE_DIR%\lib - the distribution bundle is incomplete. 1>&2 + exit /b 2 +) if not exist "%CLI_JAR%" ( echo sonar-predictor: missing %CLI_JAR% - the distribution bundle is incomplete. 1>&2 exit /b 2 From 557f558bc3c2f258b5def0204515ff7e3344a458 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sun, 24 May 2026 05:15:22 +0000 Subject: [PATCH 3/4] fix(ci): use 'sonar analyze --save' directly; agent-scan was a deleted skill-shell wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The self-scan + parity workflows invoked '$SONAR_PREDICTOR_HOME/bin/sonar agent-scan analyze .', but 'agent-scan' was never a CLI subcommand — it was a shell function defined inside the OLD plugin/skills/sonar-predictor/bin/sonar wrapper that this branch deletes. The new distribution's bin/sonar is a thin pass-through to the Java CLI, so the call now errors: Unmatched argument at index 0: 'agent-scan' Did you mean: sonar analyze? Replace with the equivalent direct invocation: sonar --format json --save .sonar-predictor/scan.json analyze . --coverage --save was already a global option on the CLI (visible in sonar --help) — it captures the same JSON the old wrapper redirected to scan.json. The downstream Render scan summary / Quality gate / Upload artifact steps in both workflows already read .sonar-predictor/scan.json, so no change needed there. --- .github/workflows/parity.yml | 6 ++++-- .github/workflows/sonar.yml | 18 +++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.github/workflows/parity.yml b/.github/workflows/parity.yml index f3fed7e..94ce447 100644 --- a/.github/workflows/parity.yml +++ b/.github/workflows/parity.yml @@ -114,8 +114,10 @@ jobs: run: | set +e export SONAR_PREDICTOR_HOME="$(pwd)/target/sonar-predictor-dist-${{ steps.version.outputs.version }}/sonar-predictor" - "$SONAR_PREDICTOR_HOME/bin/sonar" agent-scan analyze . \ - --coverage target/site/jacoco/jacoco.xml + mkdir -p .sonar-predictor + "$SONAR_PREDICTOR_HOME/bin/sonar" \ + --format json --save .sonar-predictor/scan.json \ + analyze . --coverage target/site/jacoco/jacoco.xml rc=$? set -e echo "Self-scan exit code: $rc (0=clean, 1=issues found, 2+=tool error)" diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 2173489..06e092a 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -84,13 +84,11 @@ jobs: echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "Project version: ${VERSION}" - # The actual self-scan. We override SONAR_PREDICTOR_HOME so the wrapper - # script picks up THIS branch's freshly-built daemon jar and analyzer - # plugins from the assembly's exploded staging directory, not whatever - # happens to be installed globally. One JaCoCo XML is passed in as - # coverage evidence (single module = one report). agent-scan writes - # JSON to .sonar-predictor/scan.json and prints a human summary on - # stdout; we want both. + # The actual self-scan. We point bin/sonar at THIS branch's + # freshly-built distribution under target/ (not whatever happens to + # be installed globally), and capture the scan as JSON to + # .sonar-predictor/scan.json via --save. One JaCoCo XML is passed + # in as coverage evidence (single module = one report). # # IMPORTANT: the CLI uses three-state exit codes # 0 = clean (no findings at the floor) @@ -104,8 +102,10 @@ jobs: run: | set +e export SONAR_PREDICTOR_HOME="$(pwd)/target/sonar-predictor-dist-${{ steps.version.outputs.version }}/sonar-predictor" - "$SONAR_PREDICTOR_HOME/bin/sonar" agent-scan analyze . \ - --coverage target/site/jacoco/jacoco.xml + mkdir -p .sonar-predictor + "$SONAR_PREDICTOR_HOME/bin/sonar" \ + --format json --save .sonar-predictor/scan.json \ + analyze . --coverage target/site/jacoco/jacoco.xml rc=$? set -e echo "Self-scan exit code: $rc (0=clean, 1=issues found, 2+=tool error)" From 6679768c4c445910a6928518089176b5156b8887 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Sun, 24 May 2026 06:28:17 +0000 Subject: [PATCH 4/4] fix(daemon-client): wrap Channels stream wrappers in try-with-resources (S2095) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SonarCloud quality gate flagged java:S2095 BLOCKER on DaemonClient.roundTrip: the OutputStream and InputStream returned by Channels.newOutputStream/newInputStream weren't explicitly closed. In practice they delegate to the SocketChannel which IS in try-with-resources, so the underlying resource closes correctly, but the static analyzer can't prove that — and the wrappers' close() may flush state we relied on implicit-close for. Move both into the try-with-resources head; resources close in reverse declaration order (in → out → channel), which is the order we want. Verify mvn -B -ntp test -Dtest=DaemonClientTest → 4/4 pass --- src/main/java/dev/sonarcli/cli/DaemonClient.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/dev/sonarcli/cli/DaemonClient.java b/src/main/java/dev/sonarcli/cli/DaemonClient.java index bf58bde..56e07f4 100644 --- a/src/main/java/dev/sonarcli/cli/DaemonClient.java +++ b/src/main/java/dev/sonarcli/cli/DaemonClient.java @@ -157,9 +157,9 @@ private WireMessage exchange(WireMessage request) { private WireMessage roundTrip(WireMessage request) throws IOException { try (SocketChannel channel = - SocketChannel.open(UnixDomainSocketAddress.of(paths.socket()))) { - OutputStream out = Channels.newOutputStream(channel); - InputStream in = Channels.newInputStream(channel); + SocketChannel.open(UnixDomainSocketAddress.of(paths.socket())); + OutputStream out = Channels.newOutputStream(channel); + InputStream in = Channels.newInputStream(channel)) { MessageCodec.writeMessage(out, request); WireMessage response = MessageCodec.readMessage(in); if (!request.id().equals(response.id())) {