diff --git a/build.sbt b/build.sbt index f3745f3..04e0678 100644 --- a/build.sbt +++ b/build.sbt @@ -40,6 +40,7 @@ lazy val plugin = project case _ => "2.0.0-M2" } }, + libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test, addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.0"), addSbtPlugin("com.github.sbt" % "sbt-git" % "2.1.0"), addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.0"), diff --git a/plugin/src/main/scala/com/geirsson/CiReleasePlugin.scala b/plugin/src/main/scala/com/geirsson/CiReleasePlugin.scala index ad99c50..8286ffa 100644 --- a/plugin/src/main/scala/com/geirsson/CiReleasePlugin.scala +++ b/plugin/src/main/scala/com/geirsson/CiReleasePlugin.scala @@ -106,6 +106,8 @@ object CiReleasePlugin extends AutoPlugin { Some(s"scm:git:git@github.com:$user/$repo.git") ) + lazy val cireleasePublishCommand = settingKey[String]("") + override lazy val buildSettings: Seq[Def.Setting[_]] = List( dynverSonatypeSnapshots := true, scmInfo ~= { @@ -128,7 +130,20 @@ object CiReleasePlugin extends AutoPlugin { } catch { case NonFatal(_) => None } - } + }, + cireleasePublishCommand := { + val gitDescribe = dynverGitDescribeOutput.value + val v = gitDescribe.getVersion( + dynverCurrentDate.value, + dynverSeparator.value, + dynverSonatypeSnapshots.value + ) + sys.env.get("CI_RELEASE") match { + case Some(cmd) => cmd + case None => backPubVersionToCommand(v) + } + }, + version ~= dropBackPubCommand, ) override lazy val globalSettings: Seq[Def.Setting[_]] = List( @@ -136,7 +151,8 @@ object CiReleasePlugin extends AutoPlugin { publishMavenStyle := true, commands += Command.command("ci-release") { currentState => val shouldDeployToSonatypeCentral = isDeploySetToSonatypeCentral(currentState) - val isSnapshot = isSnapshotVersion(currentState) + val version = getVersion(currentState) + val isSnapshot = isSnapshotVersion(version) if (!isSecure) { println("No access to secret variables, doing nothing") currentState @@ -150,6 +166,8 @@ object CiReleasePlugin extends AutoPlugin { val reloadKeyFiles = "; set pgpSecretRing := pgpSecretRing.value; set pgpPublicRing := pgpPublicRing.value" + val publishCommand = getPublishCommand(currentState) + if (shouldDeployToSonatypeCentral) { if (isSnapshot) { println(s"Sonatype Central does not accept snapshots, only official releases. Aborting release.") @@ -161,7 +179,7 @@ object CiReleasePlugin extends AutoPlugin { println("Tag push detected, publishing a stable release") reloadKeyFiles :: sys.env.getOrElse("CI_CLEAN", "; clean ; sonatypeBundleClean") :: - sys.env.getOrElse("CI_RELEASE", "+publishSigned") :: + publishCommand :: sys.env.getOrElse("CI_SONATYPE_RELEASE", "sonatypeCentralRelease") :: currentState } @@ -184,7 +202,7 @@ object CiReleasePlugin extends AutoPlugin { println("Tag push detected, publishing a stable release") reloadKeyFiles :: sys.env.getOrElse("CI_CLEAN", "; clean ; sonatypeBundleClean") :: - sys.env.getOrElse("CI_RELEASE", "+publishSigned") :: + publishCommand :: sys.env.getOrElse("CI_SONATYPE_RELEASE", "sonatypeBundleRelease") :: currentState } @@ -210,10 +228,39 @@ object CiReleasePlugin extends AutoPlugin { } } - def isSnapshotVersion(state: State): Boolean = { + def getVersion(state: State): String = (ThisBuild / version).get(Project.extract(state).structure.data) match { - case Some(v) => v.endsWith("-SNAPSHOT") + case Some(v) => v case None => throw new NoSuchFieldError("version") } + + def getPublishCommand(state: State): String = + (ThisBuild / cireleasePublishCommand).get(Project.extract(state).structure.data) match { + case Some(v) => v + case None => throw new NoSuchFieldError("cireleasePublishCommand") + } + + def isSnapshotVersion(v: String): Boolean = v.endsWith("-SNAPSHOT") + + def backPubVersionToCommand(ver: String): String = + if (ver.contains("@")) { + val afterAt = ver.split("@").drop(1).mkString("@") + val cmd = + if (afterAt.contains("#")) afterAt.split("#").head + else afterAt + if (cmd.isEmpty) sys.error(s"Invalid back-publish version: $ver") + else { + if (!cmd.head.isDigit) cmd + else if (cmd.contains(".x")) s";++${cmd};publishSigned" + else s";++${cmd}!;publishSigned" + } + } else "+publishSigned" + + def dropBackPubCommand(ver: String): String = { + val nonComment = + if (ver.contains("#")) ver.split("#").head + else ver + if (nonComment.contains("@")) nonComment.split("@").head + else nonComment } } diff --git a/plugin/src/test/scala/com/geirsson/CiReleaseTest.scala b/plugin/src/test/scala/com/geirsson/CiReleaseTest.scala new file mode 100644 index 0000000..4cdd39f --- /dev/null +++ b/plugin/src/test/scala/com/geirsson/CiReleaseTest.scala @@ -0,0 +1,39 @@ +package com.geirsson + +import CiReleasePlugin.{ backPubVersionToCommand, dropBackPubCommand } + +class CiReleaseTest extends munit.FunSuite { + val expectedVer = "1.1.0" + + test("Normal version default") { + assertEquals(backPubVersionToCommand("1.1.0"), "+publishSigned") + assertEquals(dropBackPubCommand("1.1.0"), expectedVer) + } + + test("Command starting with number is assumed to be a cross version") { + assertEquals(backPubVersionToCommand("1.1.0@2.12.20"), ";++2.12.20!;publishSigned") + assertEquals(dropBackPubCommand("1.1.0@2.12.20"), expectedVer) + + assertEquals(backPubVersionToCommand("1.1.0@3.x"), ";++3.x;publishSigned") + assertEquals(dropBackPubCommand("1.1.0@3.x"), expectedVer) + } + + test("Non-number is treated as an alternative publish command") { + assertEquals(backPubVersionToCommand("1.1.0@foo/publishSigned"), "foo/publishSigned") + assertEquals(dropBackPubCommand("1.1.0@foo/publishSigned"), expectedVer) + + assertEquals(backPubVersionToCommand("1.1.0@+foo/publishSigned"), "+foo/publishSigned") + assertEquals(dropBackPubCommand("1.1.0@+foo/publishSigned"), expectedVer) + } + + test("Treat # as comments") { + assertEquals(backPubVersionToCommand("1.1.0#comment"), "+publishSigned") + assertEquals(dropBackPubCommand("1.1.0#comment"), expectedVer) + + assertEquals(backPubVersionToCommand("1.1.0@2.12.20#comment"), ";++2.12.20!;publishSigned") + assertEquals(dropBackPubCommand("1.1.0@2.12.20#comment"), expectedVer) + + assertEquals(backPubVersionToCommand("1.1.0@3.x#comment"), ";++3.x;publishSigned") + assertEquals(dropBackPubCommand("1.1.0@3.x#comment"), expectedVer) + } +}