From e2601b7ca62b68d17d07ddb3fd41970fc8c4bc3e Mon Sep 17 00:00:00 2001 From: Ali Rashid Date: Tue, 2 Jun 2026 05:58:31 +0300 Subject: [PATCH] [2.x] test: Round-trip platform-suffix publishing/consumption --- .../platform-publish/build.sbt | 81 ++++++++++--------- .../platform-publish/test | 15 ++-- 2 files changed, 50 insertions(+), 46 deletions(-) diff --git a/sbt-app/src/sbt-test/dependency-management/platform-publish/build.sbt b/sbt-app/src/sbt-test/dependency-management/platform-publish/build.sbt index daad5f6fb..379a3fe74 100644 --- a/sbt-app/src/sbt-test/dependency-management/platform-publish/build.sbt +++ b/sbt-app/src/sbt-test/dependency-management/platform-publish/build.sbt @@ -1,51 +1,52 @@ -// sbt/sbt#9117: published artifact filenames must carry the platform suffix -// (e.g. _native0.5), matching the module coordinate / directory. +// sbt/sbt#9117: published artifact names must carry the platform suffix, matching the +// coordinate, on both publish backends. `platform` is set directly, as sbt-scala-native does. ThisBuild / organization := "com.example" -ThisBuild / version := "0.1.0-SNAPSHOT" +ThisBuild / version := "0.1.0" ThisBuild / scalaVersion := "3.8.3" ThisBuild / csrCacheDirectory := (ThisBuild / baseDirectory).value / "coursier-cache" -ThisBuild / platform := "native0.5" -ThisBuild / crossVersion := CrossVersion.binary -// expected cross+platform base name, identical to the coordinate directory +lazy val mavenRepo = settingKey[File]("shared local Maven repo for the consume round-trip") +ThisBuild / mavenRepo := (ThisBuild / baseDirectory).value / "maven-repo" + def expected(name: String) = s"${name}_native0.5_3" -// ivyless backend: the published filenames come from the coursier publication names, -// and the POM artifactId from PomGenerator. -lazy val ivyless = (project in file("ivyless")) - .settings( - useIvy := false, - ivyPaths := IvyPaths(baseDirectory.value.toString, Some((target.value / "ivy2").toString)), - TaskKey[Unit]("check") := { - val nm = expected(moduleName.value) - val dir = target.value / "ivy2" / "local" / organization.value / nm / version.value - def req(f: File): Unit = assert(f.exists, s"expected $f to exist") - req(dir / "jars" / s"$nm.jar") - req(dir / "srcs" / s"$nm-sources.jar") - val pom = dir / "poms" / s"$nm.pom" - req(pom) - assert(IO.read(pom).contains(s"$nm"), s"POM artifactId must be $nm: ${IO.read(pom)}") - } - ) +def producer(useIvyFlag: Boolean): Seq[Setting[?]] = Seq( + platform := "native0.5", + crossVersion := CrossVersion.binary, + useIvy := useIvyFlag, + publishMavenStyle := true, + ivyPaths := IvyPaths(baseDirectory.value.toString, Some((target.value / "ivy2").toString)), + publishTo := Some(MavenCache("platform-publish-local", (ThisBuild / mavenRepo).value)) +) + +// checkPomArtifactId only for ivyless: there the artifactId comes from PomGenerator (and +// resolution does not validate POM content); the Ivy backend's is correct regardless. +def ivyLayoutCheck(base: String, checkPomArtifactId: Boolean): Setting[?] = + TaskKey[Unit]("check") := { + val nm = expected(base) + val dir = target.value / "ivy2" / "local" / organization.value / nm / version.value + def req(f: File): Unit = assert(f.exists, s"expected $f to exist") + req(dir / "jars" / s"$nm.jar") + req(dir / "srcs" / s"$nm-sources.jar") + val pom = dir / "poms" / s"$nm.pom" + req(pom) + if (checkPomArtifactId) + assert(IO.read(pom).contains(s"$nm"), s"POM artifactId must be $nm: ${IO.read(pom)}") + } + +lazy val ivyless = (project in file("ivyless")) + .settings(name := "libivyless", producer(false), ivyLayoutCheck("libivyless", checkPomArtifactId = true)) -// Ivy backend (sbt-ivy): the published filenames come from CrossVersion.substituteCross. lazy val ivyfull = (project in file("ivyfull")) + .settings(name := "libivyfull", producer(true), ivyLayoutCheck("libivyfull", checkPomArtifactId = false)) + +// Must not dependsOn the producers, so the coordinates resolve from the Maven repo rather +// than inter-project - otherwise a suffix-dropped published name would not be caught. +lazy val consumer = (project in file("consumer")) .settings( - useIvy := true, - publishMavenStyle := true, - ivyPaths := IvyPaths(baseDirectory.value.toString, Some((target.value / "ivy2").toString)), - publishTo := Some(MavenCache("test-maven", target.value / "maven-repo")), - TaskKey[Unit]("check") := { - val nm = expected(moduleName.value) - val ver = version.value - def req(f: File): Unit = assert(f.exists, s"expected $f to exist") - val ivyDir = target.value / "ivy2" / "local" / organization.value / nm / ver - req(ivyDir / "jars" / s"$nm.jar") - req(ivyDir / "srcs" / s"$nm-sources.jar") - req(ivyDir / "poms" / s"$nm.pom") - val mvnDir = target.value / "maven-repo" / organization.value.replace('.', '/') / nm / ver - req(mvnDir / s"$nm-$ver.jar") - req(mvnDir / s"$nm-$ver.pom") - } + publish / skip := true, + resolvers += MavenCache("platform-publish-local", (ThisBuild / mavenRepo).value), + libraryDependencies += organization.value % expected("libivyless") % version.value, + libraryDependencies += organization.value % expected("libivyfull") % version.value ) diff --git a/sbt-app/src/sbt-test/dependency-management/platform-publish/test b/sbt-app/src/sbt-test/dependency-management/platform-publish/test index 835426e8d..bd3213bee 100644 --- a/sbt-app/src/sbt-test/dependency-management/platform-publish/test +++ b/sbt-app/src/sbt-test/dependency-management/platform-publish/test @@ -1,11 +1,14 @@ -# sbt/sbt#9117: published artifact filenames must carry the platform suffix -# (_native0.5), matching the coordinate, on both the ivyless and Ivy backends. +# sbt/sbt#9117: published artifact names must carry the platform suffix (_native0.5), +# matching the coordinate, on both the ivyless and Ivy backends. -# ivyless backend: publication names + POM artifactId +# publishLocal (ivy layout): filenames + POM artifactId > ivyless/publishLocal > ivyless/check - -# Ivy backend (useIvy := true): publishLocal (ivy layout) and publish (maven layout) > ivyfull/publishLocal -> ivyfull/publish > ivyfull/check + +# publish to a local Maven repo, then resolve the artifacts back under their platform +# coordinate +> ivyless/publish +> ivyfull/publish +> consumer/update