diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index 86bb19c..e7422a4 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -9,7 +9,15 @@ on: jobs: build: - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + jobtype: 1 + - os: ubuntu-latest + jobtype: 2 + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v5 @@ -21,5 +29,11 @@ jobs: cache: sbt - name: Install sbt uses: sbt/setup-sbt@v1 - - name: Run tests - run: sbt "^ scripted" + - name: Build and test + if: ${{ matrix.jobtype == 1 }} + shell: bash + run: sbt -v '++ 2.12.x' scripted + - name: Scala 3 + if: ${{ matrix.jobtype == 2 }} + shell: bash + run: sbt -v '++ 3.x' 'scripted agent/*' diff --git a/build.sbt b/build.sbt index 17d717b..0053822 100644 --- a/build.sbt +++ b/build.sbt @@ -2,13 +2,13 @@ * Copyright © 2016-2017 Lightbend, Inc. */ -// sbt cross build -crossSbtVersions := Seq("1.11.4") - // dependencies val packagerVersion = "1.11.3" val packager19xVersion = "1.9.16" +val scala212 = "2.12.20" +val scala3 = "3.7.2" + addSbtPlugin( "com.github.sbt" % "sbt-native-packager" % packagerVersion % "provided" ) @@ -42,6 +42,13 @@ lazy val `sbt-javaagent` = (project.in(file("."))) .settings( name := "sbt-javaagent", organization := "com.github.sbt", + crossScalaVersions := Seq(scala212, scala3), + scalacOptions ++= { + scalaBinaryVersion.value match { + case "2.12" => Seq("-Xsource:3") + case _ => Nil + } + }, scriptedBufferLog := false, scriptedLaunchOpts ++= Seq( "-Dproject.version=" + version.value, @@ -51,6 +58,18 @@ lazy val `sbt-javaagent` = (project.in(file("."))) scriptedDependencies := { (maxwell / publishLocal).value publishLocal.value + }, + (pluginCrossBuild / sbtVersion) := { + scalaBinaryVersion.value match { + case "2.12" => "1.11.6" + case _ => "2.0.0-RC4" + } + }, + scriptedSbt := { + scalaBinaryVersion.value match { + case "2.12" => "1.11.6" + case _ => (pluginCrossBuild / sbtVersion).value + } } ) diff --git a/src/main/scala-2.12/AgentModule.scala b/src/main/scala-2.12/AgentModule.scala new file mode 100644 index 0000000..0002868 --- /dev/null +++ b/src/main/scala-2.12/AgentModule.scala @@ -0,0 +1,14 @@ +package com.lightbend.sbt.javaagent + +import sbt.* +import scala.language.implicitConversions + +case class AgentScope(compile: Boolean = false, test: Boolean = false, run: Boolean = false, dist: Boolean = true) + +case class AgentModule(name: String, module: ModuleID, scope: AgentScope, arguments: String) + +case class ResolvedAgent(agent: AgentModule, artifact: File) + +object AgentModule { + implicit def moduleToAgentModule(module: ModuleID): AgentModule = JavaAgent(module) +} diff --git a/src/main/scala-2.12/PluginCompat.scala b/src/main/scala-2.12/PluginCompat.scala new file mode 100644 index 0000000..0a11a25 --- /dev/null +++ b/src/main/scala-2.12/PluginCompat.scala @@ -0,0 +1,25 @@ +package com.lightbend.sbt.javaagent + +import sbt.* +import java.nio.file.{ Path => NioPath } +import xsbti.FileConverter + +private[javaagent] object PluginCompat { + type FileRef = java.io.File + type Out = java.io.File + + def toNioPath(a: Attributed[File])(implicit conv: FileConverter): NioPath = + a.data.toPath() + def toFile(a: Attributed[File])(implicit conv: FileConverter): File = + a.data + def toNioPaths(cp: Seq[Attributed[File]])(implicit conv: FileConverter): Vector[NioPath] = + cp.map(_.data.toPath()).toVector + def toFiles(cp: Seq[Attributed[File]])(implicit conv: FileConverter): Vector[File] = + cp.map(_.data).toVector + def toFileRef(a: File)(implicit conv: FileConverter): File = a + + // This adds `Def.uncached(...)` + implicit class DefOp(singleton: Def.type) { + def uncached[A1](a: A1): A1 = a + } +} diff --git a/src/main/scala-3/AgentModule.scala b/src/main/scala-3/AgentModule.scala new file mode 100644 index 0000000..d326e87 --- /dev/null +++ b/src/main/scala-3/AgentModule.scala @@ -0,0 +1,15 @@ +package com.lightbend.sbt.javaagent + +import sbt.* +import scala.language.implicitConversions + +case class AgentScope(compile: Boolean = false, test: Boolean = false, run: Boolean = false, dist: Boolean = true) + +case class AgentModule(name: String, module: ModuleID, scope: AgentScope, arguments: String) + +case class ResolvedAgent(agent: AgentModule, artifact: File) + +object AgentModule { + given Conversion[ModuleID, AgentModule] with + def apply(module: ModuleID): AgentModule = JavaAgent(module) +} diff --git a/src/main/scala-3/PluginCompat.scala b/src/main/scala-3/PluginCompat.scala new file mode 100644 index 0000000..1f245ea --- /dev/null +++ b/src/main/scala-3/PluginCompat.scala @@ -0,0 +1,21 @@ +package com.lightbend.sbt.javaagent + +import java.nio.file.{ Path => NioPath } +import sbt.* +import xsbti.{ FileConverter, HashedVirtualFileRef, VirtualFile } + +private[javaagent] object PluginCompat: + type FileRef = HashedVirtualFileRef + type Out = VirtualFile + + def toNioPath(a: Attributed[HashedVirtualFileRef])(using conv: FileConverter): NioPath = + conv.toPath(a.data) + inline def toFile(a: Attributed[HashedVirtualFileRef])(using conv: FileConverter): File = + toNioPath(a).toFile() + def toNioPaths(cp: Seq[Attributed[HashedVirtualFileRef]])(using conv: FileConverter): Vector[NioPath] = + cp.map(toNioPath).toVector + inline def toFiles(cp: Seq[Attributed[HashedVirtualFileRef]])(using conv: FileConverter): Vector[File] = + toNioPaths(cp).map(_.toFile()) + def toFileRef(a: File)(using conv: FileConverter): HashedVirtualFileRef = + conv.toVirtualFile(a.toPath()) +end PluginCompat diff --git a/src/main/scala/com/lightbend/sbt/javaagent/JavaAgent.scala b/src/main/scala/com/lightbend/sbt/javaagent/JavaAgent.scala index 2b70611..35a05f6 100644 --- a/src/main/scala/com/lightbend/sbt/javaagent/JavaAgent.scala +++ b/src/main/scala/com/lightbend/sbt/javaagent/JavaAgent.scala @@ -4,8 +4,10 @@ package com.lightbend.sbt.javaagent -import sbt._ -import sbt.Keys._ +import sbt.* +import sbt.Keys.* +import xsbti.FileConverter +import PluginCompat.{ *, given } /** * Plugin for adding Java agents to projects in a general way. @@ -17,22 +19,13 @@ object JavaAgent extends JavaAgent { object JavaAgentKeys { val javaAgents = settingKey[Seq[AgentModule]]("Java agent modules enabled for this project.") + + @transient val resolvedJavaAgents = taskKey[Seq[ResolvedAgent]]("Java agent modules with resolved artifacts.") } val AgentConfig = config("javaagent").hide - case class AgentScope(compile: Boolean = false, test: Boolean = false, run: Boolean = false, dist: Boolean = true) - - case class AgentModule(name: String, module: ModuleID, scope: AgentScope, arguments: String) - - case class ResolvedAgent(agent: AgentModule, artifact: File) - - object AgentModule { - import scala.language.implicitConversions - implicit def moduleToAgentModule(module: ModuleID): AgentModule = JavaAgent(module) - } - /** * Create an agent module from a module dependency. * Scope is also derived from the given module configuration. @@ -69,7 +62,11 @@ class JavaAgent extends AutoPlugin { Test/fork := enableFork(Test/fork, _.scope.test).value, run/javaOptions ++= agentOptions(_.agent.scope.run).value, Test/javaOptions ++= agentOptions(_.agent.scope.test).value, - Test/fullClasspath := filterAgents((Test/fullClasspath).value, resolvedJavaAgents.value) + Test/fullClasspath := Def.uncached { + val conv = fileConverter.value + implicit val conv0: xsbti.FileConverter = conv + filterAgents((Test/fullClasspath).value, resolvedJavaAgents.value) + } ) private def resolveAgents = Def.task[Seq[ResolvedAgent]] { @@ -102,8 +99,9 @@ class JavaAgent extends AutoPlugin { } } - def filterAgents(classpath: Classpath, resolvedAgents: Seq[ResolvedAgent]): Classpath = { + def filterAgents(classpath: Classpath, resolvedAgents: Seq[ResolvedAgent])(implicit conv: FileConverter): Classpath = { val agents = resolvedAgents.map(resolved => resolved.artifact.absolutePath) - classpath.filter(aFile => !agents.contains(aFile.data.getAbsolutePath)) + classpath + .filter(entry => !agents.contains(PluginCompat.toFile(entry).getAbsolutePath)) } } diff --git a/src/main/scala/com/lightbend/sbt/javaagent/JavaAgentPackaging.scala b/src/main/scala/com/lightbend/sbt/javaagent/JavaAgentPackaging.scala index 63ad770..8f42cb5 100644 --- a/src/main/scala/com/lightbend/sbt/javaagent/JavaAgentPackaging.scala +++ b/src/main/scala/com/lightbend/sbt/javaagent/JavaAgentPackaging.scala @@ -4,8 +4,8 @@ package com.lightbend.sbt.javaagent -import sbt._ -import sbt.Keys._ +import sbt.* +import sbt.Keys.* import com.typesafe.sbt.packager.universal.UniversalPlugin.autoImport.Universal import java.io.File @@ -24,7 +24,11 @@ object JavaAgentPackaging extends AutoPlugin { override def projectSettings = { import com.typesafe.sbt.packager.{ Keys => PackagerKeys } Seq( - Universal / mappings ++= agentMappings.value.map(m => m._1 -> m._2), + Universal / mappings ++= { + val conv = fileConverter.value + implicit val conv0: xsbti.FileConverter = conv + agentMappings.value.map(m => PluginCompat.toFileRef(m._1) -> m._2) + }, PackagerKeys.bashScriptExtraDefines ++= agentBashScriptOptions.value, PackagerKeys.batScriptExtraDefines ++= agentBatScriptOptions.value ) diff --git a/src/sbt-test/agent/confs/build.sbt b/src/sbt-test/agent-1/confs/build.sbt similarity index 100% rename from src/sbt-test/agent/confs/build.sbt rename to src/sbt-test/agent-1/confs/build.sbt diff --git a/src/sbt-test/agent/confs/project/plugins.sbt b/src/sbt-test/agent-1/confs/project/plugins.sbt similarity index 100% rename from src/sbt-test/agent/confs/project/plugins.sbt rename to src/sbt-test/agent-1/confs/project/plugins.sbt diff --git a/src/sbt-test/agent/confs/src/main/scala/Main.scala b/src/sbt-test/agent-1/confs/src/main/scala/Main.scala similarity index 100% rename from src/sbt-test/agent/confs/src/main/scala/Main.scala rename to src/sbt-test/agent-1/confs/src/main/scala/Main.scala diff --git a/src/sbt-test/agent/confs/src/test/scala/Test.scala b/src/sbt-test/agent-1/confs/src/test/scala/Test.scala similarity index 100% rename from src/sbt-test/agent/confs/src/test/scala/Test.scala rename to src/sbt-test/agent-1/confs/src/test/scala/Test.scala diff --git a/src/sbt-test/agent/confs/test b/src/sbt-test/agent-1/confs/test similarity index 100% rename from src/sbt-test/agent/confs/test rename to src/sbt-test/agent-1/confs/test diff --git a/src/sbt-test/agent/confs/test.sbt b/src/sbt-test/agent-1/confs/test.sbt similarity index 100% rename from src/sbt-test/agent/confs/test.sbt rename to src/sbt-test/agent-1/confs/test.sbt diff --git a/src/sbt-test/agent/dist_1.9.x/build.sbt b/src/sbt-test/agent-1/dist_1.9.x/build.sbt similarity index 100% rename from src/sbt-test/agent/dist_1.9.x/build.sbt rename to src/sbt-test/agent-1/dist_1.9.x/build.sbt diff --git a/src/sbt-test/agent/dist_1.9.x/project/plugins.sbt b/src/sbt-test/agent-1/dist_1.9.x/project/plugins.sbt similarity index 100% rename from src/sbt-test/agent/dist_1.9.x/project/plugins.sbt rename to src/sbt-test/agent-1/dist_1.9.x/project/plugins.sbt diff --git a/src/sbt-test/agent/dist_1.9.x/src/main/scala/Main.scala b/src/sbt-test/agent-1/dist_1.9.x/src/main/scala/Main.scala similarity index 100% rename from src/sbt-test/agent/dist_1.9.x/src/main/scala/Main.scala rename to src/sbt-test/agent-1/dist_1.9.x/src/main/scala/Main.scala diff --git a/src/sbt-test/agent/dist_1.9.x/test b/src/sbt-test/agent-1/dist_1.9.x/test similarity index 100% rename from src/sbt-test/agent/dist_1.9.x/test rename to src/sbt-test/agent-1/dist_1.9.x/test diff --git a/src/sbt-test/agent/dist_1.9.x/test.sbt b/src/sbt-test/agent-1/dist_1.9.x/test.sbt similarity index 100% rename from src/sbt-test/agent/dist_1.9.x/test.sbt rename to src/sbt-test/agent-1/dist_1.9.x/test.sbt diff --git a/src/sbt-test/agent/test/build.sbt b/src/sbt-test/agent-1/test/build.sbt similarity index 100% rename from src/sbt-test/agent/test/build.sbt rename to src/sbt-test/agent-1/test/build.sbt diff --git a/src/sbt-test/agent/test/project/plugins.sbt b/src/sbt-test/agent-1/test/project/plugins.sbt similarity index 100% rename from src/sbt-test/agent/test/project/plugins.sbt rename to src/sbt-test/agent-1/test/project/plugins.sbt diff --git a/src/sbt-test/agent/test/src/test/scala/Test.scala b/src/sbt-test/agent-1/test/src/test/scala/Test.scala similarity index 100% rename from src/sbt-test/agent/test/src/test/scala/Test.scala rename to src/sbt-test/agent-1/test/src/test/scala/Test.scala diff --git a/src/sbt-test/agent/test/test b/src/sbt-test/agent-1/test/test similarity index 100% rename from src/sbt-test/agent/test/test rename to src/sbt-test/agent-1/test/test diff --git a/src/sbt-test/agent/test/test.sbt b/src/sbt-test/agent-1/test/test.sbt similarity index 100% rename from src/sbt-test/agent/test/test.sbt rename to src/sbt-test/agent-1/test/test.sbt diff --git a/src/sbt-test/agent/compile/build.sbt b/src/sbt-test/agent/compile/build.sbt index 71c47b0..42be0e5 100644 --- a/src/sbt-test/agent/compile/build.sbt +++ b/src/sbt-test/agent/compile/build.sbt @@ -3,4 +3,4 @@ lazy val agentCompile = javaAgents += "sbt.javaagent.test" % "maxwell" % sys.props( "project.version" -) % "compile" +) % Compile