Skip to content

refactor!: collapse to single Maven module; drop skill+plugin concept (0.2.0-SNAPSHOT)#6

Merged
aksOps merged 4 commits into
mainfrom
chore/drop-skill-plugin
May 24, 2026
Merged

refactor!: collapse to single Maven module; drop skill+plugin concept (0.2.0-SNAPSHOT)#6
aksOps merged 4 commits into
mainfrom
chore/drop-skill-plugin

Conversation

@aksOps
Copy link
Copy Markdown
Contributor

@aksOps aksOps commented May 24, 2026

Summary

  • Collapse the 4-module Maven reactor (protocol + daemon + cli + dist) into one Maven project at root with src/{main,test}/{java,resources}.
  • Delete the Claude Code / Copilot CLI plugin marketplace path entirely — plugin/ and .claude-plugin/marketplace.json are gone.
  • Drop the "agent skill" concept (SKILL.md, config.env, SONAR_BUNDLE_VERSION lazy-fetch). Distribution is now a single sonar-predictor-dist-X.Y.Z.zip on GitHub Release + Maven Central.
  • Version bump 0.1.0-SNAPSHOT0.2.0-SNAPSHOT (breaking distribution change).

Why

The skill-bundle wrapper + 4-module reactor added a lot of moving parts for a ~15 KLOC project (8.4K prod / 7.2K test). With the marketplace install path retired and the distribution narrowed to "download a zip and run", a single Maven module is simpler to understand, build, test, and publish.

Verify locally

git checkout chore/drop-skill-plugin
mvn -B -ntp clean verify
# BUILD SUCCESS
# 323 tests pass, 0 failures, 0 errors
ls -la target/sonar-predictor-dist-0.2.0-SNAPSHOT.zip
# ~161 MB (bin/ + lib/sonar-predictor-{cli,daemon}.jar + plugins/*.jar × 10)
./target/sonar-predictor-dist-0.2.0-SNAPSHOT/sonar-predictor/bin/sonar --help
# exit 0, prints help

What ships on Maven Central per release

  • sonar-predictor-X.Y.Z.pom
  • sonar-predictor-X.Y.Z.jar (slim primary, ~200 KB)
  • sonar-predictor-X.Y.Z-cli.jar (shaded fat jar, runnable)
  • sonar-predictor-X.Y.Z-daemon.jar (shaded fat jar, runnable)
  • sonar-predictor-X.Y.Z-dist.zipthe bundle users actually run
  • sonar-predictor-X.Y.Z-src.zip (whole-repo source)
  • sonar-predictor-X.Y.Z-sources.jar + -javadoc.jar (Central requires these for jar packaging)

Breaking changes for downstream users

  • The /plugin marketplace add RandomCodeSpace/sonar-predict install path is gone.
  • The sonar-scanner-claude / sonar-scanner-copilot subagents that shipped inside the plugin are gone (they were thin wrappers — agents can call bin/sonar directly).
  • SONAR_BUNDLE_VERSION / config.env knobs are gone (no lazy-fetch any more — the zip is fully self-contained from extract).

Test plan

  • mvn -B -ntp clean verify is green locally (323/323 tests pass)
  • Dist zip layout is correct (bin/ + lib/ + plugins/, 18 entries, ~161 MB)
  • Launcher smoke test (bin/sonar --help) exits 0
  • CI sonar.yml self-scan stays green on this PR
  • CI parity.yml stays green on this PR
  • After merge: tag v0.2.0 to validate the rewritten publish.yml end-to-end (Maven Central + GitHub Release)

Notes

  • Both shaded fat jars are currently ~15.6 MB each (overlapping deps). Could be optimized later with shade <artifactSet> scoping; not blocking.
  • The release flow still requires the same GitHub secrets as today (OSS_NEXUS_USER, OSS_NEXUS_PASS, MAVEN_GPG_PRIVATE_KEY, MAVEN_GPG_PASSPHRASE).

aksOps added 4 commits May 24, 2026 04:31
…skill+plugin

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-<v>/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
…real jar

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
…d skill-shell wrapper

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 <jacoco.xml>

--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.
…es (S2095)

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
@sonarqubecloud
Copy link
Copy Markdown

@aksOps aksOps merged commit 501d0d1 into main May 24, 2026
12 checks passed
@aksOps aksOps deleted the chore/drop-skill-plugin branch May 24, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant