From e330b049edad6d0c1dbc877e62eb8eaa0ab91244 Mon Sep 17 00:00:00 2001 From: Vasil Vasilev Date: Wed, 29 Apr 2026 12:06:27 +0200 Subject: [PATCH 1/4] Add hidden sbt key for extra JUnit template library dependencies #SCL-25373 Introduce intellijExtraJUnitTemplateLibraryDependencies, a hidden settingKey[Seq[ModuleID]] whose modules are resolved through a dedicated hidden Ivy configuration and appended only to the JUnit Run Configuration template classpath. The sbt Test classpath is intentionally unaffected, so libraries needed at test runtime when launched from the IDE can be declared without polluting in-sbt test runs. Covered by a new integration test that asserts the resolved jar appears in the generated junit_template_argfile.txt and is absent from Test/fullClasspath. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../scala/org/jetbrains/sbtidea/Init.scala | 5 +++ .../scala/org/jetbrains/sbtidea/Keys.scala | 8 ++++ .../tasks/classpath/TestClasspathTasks.scala | 12 +++++- .../SbtIdeaPluginIntegrationTest.scala | 42 +++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/ideaSupport/src/main/scala/org/jetbrains/sbtidea/Init.scala b/ideaSupport/src/main/scala/org/jetbrains/sbtidea/Init.scala index 4757861c..0220a8c1 100644 --- a/ideaSupport/src/main/scala/org/jetbrains/sbtidea/Init.scala +++ b/ideaSupport/src/main/scala/org/jetbrains/sbtidea/Init.scala @@ -124,6 +124,11 @@ trait Init { this: Keys.type => intellijPlugins := Seq.empty, intellijExtraRuntimePluginsInTests := Seq.empty, + intellijExtraJUnitTemplateLibraryDependencies := Seq.empty, + + ivyConfigurations += intellijJUnitTemplateConfig, + libraryDependencies ++= intellijExtraJUnitTemplateLibraryDependencies.value + .map(_ % intellijJUnitTemplateConfig), intellijMainJarsClasspath := AttributedClasspathTasks.main.value, intellijTestJarsClasspath := AttributedClasspathTasks.test.value, diff --git a/ideaSupport/src/main/scala/org/jetbrains/sbtidea/Keys.scala b/ideaSupport/src/main/scala/org/jetbrains/sbtidea/Keys.scala index 28070458..93049935 100644 --- a/ideaSupport/src/main/scala/org/jetbrains/sbtidea/Keys.scala +++ b/ideaSupport/src/main/scala/org/jetbrains/sbtidea/Keys.scala @@ -27,6 +27,14 @@ object Keys extends Defns with Init with Utils with Quirks { lazy val intellijExtraRuntimePluginsInTests = settingKey[Seq[IntellijPlugin]]( "List of IntelliJ platform plugins to include in tests at runtime") + lazy val intellijExtraJUnitTemplateLibraryDependencies = settingKey[Seq[ModuleID]]( + "Extra library dependencies provided only on the JUnit test Run Configuration template classpath " + + "(generated during IDEA project import). These do not affect the sbt Test classpath." + ).withRank(sbt.KeyRanks.Invisible) + + private[sbtidea] lazy val intellijJUnitTemplateConfig: Configuration = + Configuration.of("IntellijJUnitTemplate", "intellij-junit-template").hide + @Deprecated(forRemoval = true) @deprecated("The setting is ignored and will be removed in future versions. The sources are always downloaded") lazy val intellijDownloadSources = settingKey[Boolean]( diff --git a/ideaSupport/src/main/scala/org/jetbrains/sbtidea/tasks/classpath/TestClasspathTasks.scala b/ideaSupport/src/main/scala/org/jetbrains/sbtidea/tasks/classpath/TestClasspathTasks.scala index b3d73a4b..687d7435 100644 --- a/ideaSupport/src/main/scala/org/jetbrains/sbtidea/tasks/classpath/TestClasspathTasks.scala +++ b/ideaSupport/src/main/scala/org/jetbrains/sbtidea/tasks/classpath/TestClasspathTasks.scala @@ -1,9 +1,10 @@ package org.jetbrains.sbtidea.tasks.classpath +import org.jetbrains.sbtidea.Keys.intellijJUnitTemplateConfig import org.jetbrains.sbtidea.packaging.PackagingKeys.packageOutputDir import sbt.* import sbt.Def.Classpath -import sbt.Keys.{exportedProductsNoTracking, externalDependencyClasspath} +import sbt.Keys.{classpathTypes, exportedProductsNoTracking, externalDependencyClasspath, update} import scala.collection.mutable @@ -36,7 +37,14 @@ object TestClasspathTasks { val outputDir = packageOutputDir.value val pluginPlaceholderPatterns = PluginClasspathUtils.pluginClasspathPattern(outputDir) val commonClasspath = commonTestClasspath.value - pluginPlaceholderPatterns ++ commonClasspath.map(_.data.getAbsolutePath) + val extraTemplateJars = Classpaths.managedJars( + intellijJUnitTemplateConfig, + classpathTypes.value, + update.value + ) + pluginPlaceholderPatterns ++ + commonClasspath.map(_.data.getAbsolutePath) ++ + extraTemplateJars.map(_.data.getAbsolutePath) } /** diff --git a/ideaSupport/src/test/scala/org/jetbrains/sbtidea/integrationTests/SbtIdeaPluginIntegrationTest.scala b/ideaSupport/src/test/scala/org/jetbrains/sbtidea/integrationTests/SbtIdeaPluginIntegrationTest.scala index a06f73b3..bfc32161 100644 --- a/ideaSupport/src/test/scala/org/jetbrains/sbtidea/integrationTests/SbtIdeaPluginIntegrationTest.scala +++ b/ideaSupport/src/test/scala/org/jetbrains/sbtidea/integrationTests/SbtIdeaPluginIntegrationTest.scala @@ -1,6 +1,7 @@ package org.jetbrains.sbtidea.integrationTests import org.jetbrains.sbtidea.download.api.IdeInstallationContext +import org.jetbrains.sbtidea.testUtils.SbtProjectFilesUtils import org.jetbrains.sbtidea.testUtils.SbtProjectFilesUtils.runSbtProcess import org.jetbrains.sbtidea.testUtils.IoUtils import org.scalatest.matchers.should.Matchers @@ -123,6 +124,47 @@ class SbtIdeaPluginIntegrationTest junitTemplateText should include("junit_template_argfile.txt") } + test("intellijExtraJUnitTemplateLibraryDependencies appears only on the JUnit template classpath") { + val projectDir = testProjectsDir / "simple-with-plugin" + + // Inject SDK paths/settings into the fixture; this rewrites extra.sbt from a clean state + // (runUpdateIntellijCommand calls cleanUntrackedVcsFiles -> git clean -fdx first). + runUpdateIntellijCommand(projectDir) + + // Configure one extra dep that should appear ONLY on the generated JUnit template classpath. + appendExtraJUnitTemplateLibDepToExtraSbt(projectDir) + + // 1) Generate the JUnit template — the jar must end up in the argfile. + runSbtProcess(Seq("createIDEARunConfiguration"), projectDir) + + val argFile = projectDir / ".idea" / "runConfigurations" / "junit_template_argfile.txt" + assertFileExists(argFile) + val argFileText = IoUtils.readLines(argFile).mkString(System.lineSeparator()) + argFileText should include("commons-io-2.16.1.jar") + + // 2) The same jar must NOT appear on the sbt Test / fullClasspath. + val result = runSbtProcess( + Seq("show Test/fullClasspath"), + projectDir, + ioMode = SbtProjectFilesUtils.IoMode.PrintAndCollectOutput, + ) + val fullClasspathOutput = result.outputLines.getOrElse(Seq.empty).mkString("\n") + fullClasspathOutput should not include "commons-io-2.16.1.jar" + } + + private def appendExtraJUnitTemplateLibDepToExtraSbt(projectDir: File): Unit = { + val extraSbt = projectDir / "extra.sbt" + assertFileExists(extraSbt) + val current = IoUtils.readLines(extraSbt).mkString(System.lineSeparator()) + //language=SBT + val additional = + """ + | + |intellijExtraJUnitTemplateLibraryDependencies += "commons-io" % "commons-io" % "2.16.1" + |""".stripMargin + IoUtils.writeStringToFile(extraSbt, current + additional) + } + private def dumpFileStructure(directory: File): String = { val IndentIncrement = " " From ddb62f13cc6a5096af6fb10468321c6a3e7791a6 Mon Sep 17 00:00:00 2001 From: Vasil Vasilev Date: Wed, 29 Apr 2026 13:56:01 +0200 Subject: [PATCH 2/4] Bump GitHub Actions to latest majors actions/checkout v4 -> v6 actions/setup-java v4 -> v5 coursier/cache-action v6 -> v8 sbt/setup-sbt is already at the latest major (v1). Existing inputs are unchanged across these majors, so no further configuration edits are needed. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/scala.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index 0ffbec41..d4a99ca9 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -11,13 +11,13 @@ jobs: name: sbt-idea-plugin plugin Build & Test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-java@v5 with: distribution: temurin java-version: 17 cache: sbt - uses: sbt/setup-sbt@v1 - - uses: coursier/cache-action@v6 + - uses: coursier/cache-action@v8 - name: Compile & Test run: sbt test From ba22d79159ad6e2d3933b50303d338af43977833 Mon Sep 17 00:00:00 2001 From: Vasil Vasilev Date: Wed, 29 Apr 2026 13:57:50 +0200 Subject: [PATCH 3/4] Bump sbt plugin versions sbt-ci-release 1.11.1 -> 1.11.2 sbt-ide-settings 1.1.2 -> 1.1.4 Verified via sbt reload. Co-Authored-By: Claude Opus 4.7 (1M context) --- project/plugins.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 8439a1af..494a1b96 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1,2 @@ -addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.11.1") -addSbtPlugin("org.jetbrains.scala" % "sbt-ide-settings" % "1.1.2") +addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.11.2") +addSbtPlugin("org.jetbrains.scala" % "sbt-ide-settings" % "1.1.4") From 8d8716fa25cac6ecd4d8f79765019bf2b62b8b07 Mon Sep 17 00:00:00 2001 From: Vasil Vasilev Date: Wed, 29 Apr 2026 14:03:47 +0200 Subject: [PATCH 4/4] Bump sbt to 1.12.10 1.11.5 -> 1.12.10. Verified via sbt reload. Co-Authored-By: Claude Opus 4.7 (1M context) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e480c675..6edd024b 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.11.5 +sbt.version=1.12.10