POC: an sbt 1.x plugin built with scala-cli, with scripted tests driven by just + a small scala-cli script.
plugin/— the sbt plugin source (Scala 2.12, scala-cli). Publishes to Maven Central asorg.polyvariant:scala-cli-sbt-plugin-poc_2.12_1.0.plugin/resources/sbt/sbt.autoplugins— required so sbt 1.x discovers the AutoPlugin (this file is normally generated by sbt's compiler plugin).sbt-test/<group>/<name>/— sbt scripted tests.build/scripted.scala— minimal driver that callssbt.scriptedtest.ScriptedRunnerfromorg.scala-sbt::scripted-sbt-redux. All the surrounding plumbing (publishing locally, fetchingsbt-launch, writingrepo.config) lives injustfile.justfile—scripted,scripted-released,publishtargets.
just # alias for `just scripted`
just scripted simple/basic
PLUGIN_VERSION=1.2.3 just scripted
just scripted-released # uses PLUGIN_VERSION; expects artifact on Central
just scripted publishes the plugin via scala-cli publish --ivy2-local-like into a scratch staging dir, then post-processes the result into a scratch ivy home (<work>/ivy/local/<org>/<name>/scala_2.12/sbt_1.0/<rev>/) — the sbt-plugin Ivy layout. ivy.xml gets patched to add the e:scalaVersion/e:sbtVersion cross-attributes (which scala-cli doesn't emit), and checksums are regenerated. The spawned sbt picks the plugin up through its default local resolver against the scratch ivy home — no repo.config involved.
For just scripted-released, sbt-test/.../project/plugins.sbt reads plugin.snapshots=true to register the Central snapshots resolver when verifying a -SNAPSHOT version.
just publish --signer gpg --gpg-key <KEY_ID>
Plugin.scala uses //> using publish.computeVersion git:dynver:
- On a
v*tag → the tag (e.g.v0.1.0→0.1.0). - On any other commit →
<lastTag>+<n>-<sha>-SNAPSHOT(e.g.0.1.0+3-abc1234-SNAPSHOT).
scala-cli routes -SNAPSHOT versions to the Central snapshots host automatically. The publish target passes --workspace . so git:dynver finds the repo (the plugin/ subdirectory has no .git).
Three jobs, chained via needs::
test— runs on every push and PR.just scripted.publish— runs onmainpushes andv*tags, aftertestpasses. Imports the GPG key fromPGP_SECRET, configures Sonatype credentials, and runsjust publish --signer gpg --gpg-key DB33C5B9DA1A245B. Onmainthis produces a-SNAPSHOTartifact; on av*tag, a release.verify-release— runs afterpublishon bothmainandv*tags. Reads the version from apublishjob output (computed via a dummyscala-cli publish --dummy), polls the appropriate Central host (snapshots vs releases) until the artifact is reachable (up to ~15 minutes), thenjust scripted-releasedresolves it from Central rather than the scratch repo.
Required secrets: PGP_SECRET, SONATYPE_USERNAME, SONATYPE_PASSWORD.