From 9e0a728c58ee127daccea2f6800f300d0afe2730 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Wed, 5 Apr 2023 13:18:28 +0200 Subject: [PATCH] Add sbtPluginPublishLegacyMavenStyle to publish to Artifactory Artifactory rejects the legacy artifacts of sbt plugin. It is now possible to publish to Artifactory by turning `sbtPluginPublishLegacyMavenStyle` off. --- main/src/main/scala/sbt/Defaults.scala | 22 ++- main/src/main/scala/sbt/Keys.scala | 1 + .../sbt-plugin-publish/build.sbt | 133 +++++++++++------- .../sbt-plugin-publish/test | 26 ++-- 4 files changed, 114 insertions(+), 68 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 92add3fb5..ef66ce012 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -2822,17 +2822,20 @@ object Classpaths { Defaults.globalDefaults( Seq( publishMavenStyle :== true, + sbtPluginPublishLegacyMavenStyle := true, publishArtifact :== true, (Test / publishArtifact) :== false ) ) + private val publishSbtPluginMavenStyle = Def.task { + sbtPlugin.value && publishMavenStyle.value + } val jvmPublishSettings: Seq[Setting[_]] = Seq( artifacts := artifactDefs(defaultArtifactTasks).value, - packagedArtifacts := packaged(defaultArtifactTasks).value ++ - Def - .ifS(sbtPlugin.toTask)(mavenArtifactsOfSbtPlugin)(Def.task(Map.empty[Artifact, File])) - .value + packagedArtifacts := Def + .ifS(publishSbtPluginMavenStyle)(mavenArtifactsOfSbtPlugin)(packaged(defaultArtifactTasks)) + .value, ) ++ RemoteCache.projectSettings /** @@ -2841,7 +2844,7 @@ object Classpaths { * valid POM file, that is a POM file that Maven can resolve. */ private def mavenArtifactsOfSbtPlugin: Def.Initialize[Task[Map[Artifact, File]]] = - Def.ifS(publishMavenStyle.toTask)(Def.task { + Def.task { val crossVersion = sbtCrossVersion.value val legacyArtifact = (makePom / artifact).value val pom = makeMavenPomOfSbtPlugin.value @@ -2849,8 +2852,13 @@ object Classpaths { def addSuffix(a: Artifact): Artifact = a.withName(crossVersion(a.name)) val packages = legacyPackages.map { case (artifact, file) => addSuffix(artifact) -> file } - packages + (addSuffix(legacyArtifact) -> pom) - })(Def.task(Map.empty)) + val legacyPackagedArtifacts = Def + .ifS(sbtPluginPublishLegacyMavenStyle.toTask)(packaged(defaultArtifactTasks))( + Def.task(Map.empty[Artifact, File]) + ) + .value + packages + (addSuffix(legacyArtifact) -> pom) ++ legacyPackagedArtifacts + } private def sbtCrossVersion: Def.Initialize[String => String] = Def.setting { val sbtV = sbtBinaryVersion.value diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index cd5b520c0..82d778c2f 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -491,6 +491,7 @@ object Keys { val makeIvyXmlLocalConfiguration = taskKey[PublishConfiguration]("Configuration for generating ivy.xml.").withRank(DSetting) val packagedArtifacts = taskKey[Map[Artifact, File]]("Packages all artifacts for publishing and maps the Artifact definition to the generated file.").withRank(CTask) val publishMavenStyle = settingKey[Boolean]("Configures whether to generate and publish a pom (true) or Ivy file (false).").withRank(BSetting) + val sbtPluginPublishLegacyMavenStyle = settingKey[Boolean]("Configuration for generating the legacy pom of sbt plugins, to publish to Maven").withRank(CSetting) val credentials = taskKey[Seq[Credentials]]("The credentials to use for updating and publishing.").withRank(BMinusTask) val allCredentials = taskKey[Seq[Credentials]]("Aggregated credentials across current and root subprojects. Do not rewire this task.").withRank(DTask) diff --git a/sbt-app/src/sbt-test/dependency-management/sbt-plugin-publish/build.sbt b/sbt-app/src/sbt-test/dependency-management/sbt-plugin-publish/build.sbt index bc05305f8..27cb09743 100644 --- a/sbt-app/src/sbt-test/dependency-management/sbt-plugin-publish/build.sbt +++ b/sbt-app/src/sbt-test/dependency-management/sbt-plugin-publish/build.sbt @@ -3,26 +3,27 @@ import scala.util.matching.Regex lazy val repo = file("test-repo") lazy val resolver = Resolver.file("test-repo", repo) -lazy val example = project.in(file("example")) +lazy val sbtPlugin1 = project.in(file("sbt-plugin-1")) .enablePlugins(SbtPlugin) .settings( organization := "org.example", + name := "sbt-plugin-1", addSbtPlugin("ch.epfl.scala" % "sbt-plugin-example-diamond" % "0.5.0"), publishTo := Some(resolver), - checkPackagedArtifacts := checkPackagedArtifactsDef.value, - checkPublish := checkPublishDef.value + checkPackagedArtifacts := checkPackagedArtifactsDef("sbt-plugin-1", true).value, + checkPublish := checkPublishDef("sbt-plugin-1", true).value ) -lazy val testMaven = project.in(file("test-maven")) +lazy val testMaven1 = project.in(file("test-maven-1")) .settings( - addSbtPlugin("org.example" % "example" % "0.1.0-SNAPSHOT"), + addSbtPlugin("org.example" % "sbt-plugin-1" % "0.1.0-SNAPSHOT"), externalResolvers -= Resolver.defaultLocal, resolvers += { val base = (ThisBuild / baseDirectory).value MavenRepository("test-repo", s"file://$base/test-repo") }, checkUpdate := checkUpdateDef( - "example_2.12_1.0-0.1.0-SNAPSHOT.jar", + "sbt-plugin-1_2.12_1.0-0.1.0-SNAPSHOT.jar", "sbt-plugin-example-diamond_2.12_1.0-0.5.0.jar", "sbt-plugin-example-left_2.12_1.0-0.3.0.jar", "sbt-plugin-example-right_2.12_1.0-0.3.0.jar", @@ -30,11 +31,41 @@ lazy val testMaven = project.in(file("test-maven")) ).value ) -lazy val testLocal = project.in(file("test-local")) +lazy val testLocal1 = project.in(file("test-local-1")) .settings( - addSbtPlugin("org.example" % "example" % "0.1.0-SNAPSHOT"), + addSbtPlugin("org.example" % "sbt-plugin-1" % "0.1.0-SNAPSHOT"), checkUpdate := checkUpdateDef( - "example.jar", // resolved from local repository + "sbt-plugin-1.jar", // resolved from local repository + "sbt-plugin-example-diamond_2.12_1.0-0.5.0.jar", + "sbt-plugin-example-left_2.12_1.0-0.3.0.jar", + "sbt-plugin-example-right_2.12_1.0-0.3.0.jar", + "sbt-plugin-example-bottom_2.12_1.0-0.3.0.jar", + ).value + ) + +// test publish without legacy Maven artifacts +lazy val sbtPlugin2 = project.in(file("sbt-plugin-2")) + .enablePlugins(SbtPlugin) + .settings( + organization := "org.example", + name := "sbt-plugin-2", + addSbtPlugin("ch.epfl.scala" % "sbt-plugin-example-diamond" % "0.5.0"), + sbtPluginPublishLegacyMavenStyle := false, + publishTo := Some(resolver), + checkPackagedArtifacts := checkPackagedArtifactsDef("sbt-plugin-2", false).value, + checkPublish := checkPublishDef("sbt-plugin-2", false).value, + ) + +lazy val testMaven2 = project.in(file("test-maven-2")) + .settings( + addSbtPlugin("org.example" % "sbt-plugin-2" % "0.1.0-SNAPSHOT"), + externalResolvers -= Resolver.defaultLocal, + resolvers += { + val base = (ThisBuild / baseDirectory).value + MavenRepository("test-repo", s"file://$base/test-repo") + }, + checkUpdate := checkUpdateDef( + "sbt-plugin-2_2.12_1.0-0.1.0-SNAPSHOT.jar", "sbt-plugin-example-diamond_2.12_1.0-0.5.0.jar", "sbt-plugin-example-left_2.12_1.0-0.3.0.jar", "sbt-plugin-example-right_2.12_1.0-0.3.0.jar", @@ -46,65 +77,63 @@ lazy val checkPackagedArtifacts = taskKey[Unit]("check the packaged artifacts") lazy val checkPublish = taskKey[Unit]("check publish") lazy val checkUpdate = taskKey[Unit]("check update") -def checkPackagedArtifactsDef: Def.Initialize[Task[Unit]] = Def.task { +def checkPackagedArtifactsDef(artifactName: String, withLegacy: Boolean): Def.Initialize[Task[Unit]] = Def.task { val packagedArtifacts = Keys.packagedArtifacts.value - val deprecatedArtifacts = packagedArtifacts.keys.filter(a => a.name == "example") - assert(deprecatedArtifacts.size == 4) - val artifactsWithCrossVersion = packagedArtifacts.keys.filter(a => a.name == "example_2.12_1.0") + val legacyArtifacts = packagedArtifacts.keys.filter(a => a.name == artifactName) + if (withLegacy) { + assert(legacyArtifacts.size == 4) + val legacyPom = legacyArtifacts.find(_.`type` == "pom") + assert(legacyPom.isDefined) + val legacyPomContent = IO.read(packagedArtifacts(legacyPom.get)) + assert(legacyPomContent.contains(s"$artifactName")) + assert(legacyPomContent.contains(s"sbt-plugin-example-diamond")) + } else { + assert(legacyArtifacts.size == 0) + } + + val artifactsWithCrossVersion = + packagedArtifacts.keys.filter(a => a.name == s"${artifactName}_2.12_1.0") assert(artifactsWithCrossVersion.size == 4) - - val deprecatedPom = deprecatedArtifacts.find(_.`type` == "pom") - assert(deprecatedPom.isDefined) - val deprecatedPomContent = IO.read(packagedArtifacts(deprecatedPom.get)) - assert(deprecatedPomContent.contains(s"example")) - assert(deprecatedPomContent.contains(s"sbt-plugin-example-diamond")) - val pomWithCrossVersion = artifactsWithCrossVersion.find(_.`type` == "pom") assert(pomWithCrossVersion.isDefined) val pomContent = IO.read(packagedArtifacts(pomWithCrossVersion.get)) - assert(pomContent.contains(s"example_2.12_1.0")) + assert(pomContent.contains(s"${artifactName}_2.12_1.0")) assert(pomContent.contains(s"sbt-plugin-example-diamond_2.12_1.0")) } -def checkPublishDef: Def.Initialize[Task[Unit]] = Def.task { +def checkPublishDef(artifactName: String, withLegacy: Boolean): Def.Initialize[Task[Unit]] = Def.task { val _ = publish.value val org = organization.value - val files = IO.listFiles(repo / org.replace('.', '/') / "example_2.12_1.0" / "0.1.0-SNAPSHOT") - + val files = IO.listFiles(repo / org.replace('.', '/') / s"${artifactName}_2.12_1.0" / "0.1.0-SNAPSHOT") + val logger = streams.value.log + assert(files.nonEmpty) - val Deprecated = s"example-${Regex.quote("0.1.0-SNAPSHOT")}(-javadoc|-sources)?(\\.jar|\\.pom)".r - val WithCrossVersion = s"example${Regex.quote("_2.12_1.0")}-${Regex.quote("0.1.0-SNAPSHOT")}(-javadoc|-sources)?(\\.jar|\\.pom)".r + val legacyRegex = + s"$artifactName-${Regex.quote("0.1.0-SNAPSHOT")}(-javadoc|-sources)?(\\.jar|\\.pom)".r + val legacyArtifacts = files.filter(f => legacyRegex.unapplySeq(f.name).isDefined) + if (withLegacy) { + val legacyJars = legacyArtifacts.map(_.name).filter(_.endsWith(".jar")) + assert(legacyJars.size == 3, legacyJars.mkString(", ")) // bin, sources and javadoc + val legacyPom = legacyArtifacts.find(_.name.endsWith(".pom")) + assert(legacyPom.isDefined, "missing legacy pom") + val legacyPomContent = IO.read(legacyPom.get) + assert(legacyPomContent.contains(s"$artifactName")) + assert(legacyPomContent.contains(s"sbt-plugin-example-diamond")) + } else { + assert(legacyArtifacts.size == 0) + } - val deprecatedJars = files.map(_.name).collect { case jar @ Deprecated(_, ".jar") => jar } - assert(deprecatedJars.size == 3, deprecatedJars.mkString(", ")) // bin, sources and javadoc - - val jarsWithCrossVersion = files.map(_.name).collect { case jar @ WithCrossVersion(_, ".jar") => jar } + val withCrossVersionRegex = + s"$artifactName${Regex.quote("_2.12_1.0")}-${Regex.quote("0.1.0-SNAPSHOT")}(-javadoc|-sources)?(\\.jar|\\.pom)".r + val artifactWithCrossVersion = files.filter(f => withCrossVersionRegex.unapplySeq(f.name).isDefined) + val jarsWithCrossVersion = artifactWithCrossVersion.map(_.name).filter(_.endsWith(".jar")) assert(jarsWithCrossVersion.size == 3, jarsWithCrossVersion.mkString(", ")) // bin, sources and javadoc - - val deprecatedPom = files - .find { file => - file.name match { - case pom @ Deprecated(_, ".pom") => true - case _ => false - } - } - assert(deprecatedPom.isDefined, "missing deprecated pom") - val deprecatedPomContent = IO.read(deprecatedPom.get) - assert(deprecatedPomContent.contains(s"example")) - assert(deprecatedPomContent.contains(s"sbt-plugin-example-diamond")) - - val pomWithCrossVersion = files - .find { file => - file.name match { - case pom @ WithCrossVersion(_, ".pom") => true - case _ => false - } - } + val pomWithCrossVersion = artifactWithCrossVersion.find(_.name.endsWith(".pom")) assert(pomWithCrossVersion.isDefined, "missing pom with sbt cross-version _2.12_1.0") val pomContent = IO.read(pomWithCrossVersion.get) - assert(pomContent.contains(s"example_2.12_1.0")) + assert(pomContent.contains(s"${artifactName}_2.12_1.0")) assert(pomContent.contains(s"sbt-plugin-example-diamond_2.12_1.0")) } @@ -118,5 +147,5 @@ def checkUpdateDef(expected: String*): Def.Initialize[Task[Unit]] = Def.task { .map(_._2) val obtainedSet = obtainedFiles.map(_.getName).toSet val expectedSet = expected.toSet + "scala-library.jar" - assert(obtainedSet == expectedSet, obtainedFiles) + assert(obtainedSet == expectedSet, obtainedSet) } diff --git a/sbt-app/src/sbt-test/dependency-management/sbt-plugin-publish/test b/sbt-app/src/sbt-test/dependency-management/sbt-plugin-publish/test index ec720452b..e5e7096dd 100644 --- a/sbt-app/src/sbt-test/dependency-management/sbt-plugin-publish/test +++ b/sbt-app/src/sbt-test/dependency-management/sbt-plugin-publish/test @@ -1,11 +1,19 @@ -> example / checkPackagedArtifacts +> sbtPlugin1 / checkPackagedArtifacts -> example / checkPublish -> testMaven / checkUpdate -> set testMaven / useCoursier := false -> testMaven / checkUpdate +> sbtPlugin1 / checkPublish +> testMaven1 / checkUpdate +> set testMaven1 / useCoursier := false +> testMaven1 / checkUpdate -> example / publishLocal -> testLocal / checkUpdate -> set testLocal / useCoursier := false -> testLocal / checkUpdate +> sbtPlugin1 / publishLocal +> testLocal1 / checkUpdate +> set testLocal1 / useCoursier := false +> testLocal1 / checkUpdate + +> sbtPlugin2 / checkPackagedArtifacts + +# test publish without legacy artifacts and resolve +> sbtPlugin2 / checkPublish +> testMaven2 / checkUpdate +> set testMaven2 / useCoursier := false +> testMaven2 / checkUpdate