Skip to content

Commit 9dbd7ff

Browse files
committed
Downgrade the runner module dependency when it's added to the classpath for Scala >= 3.0.0 and < current Scala 3 LTS version
1 parent 3a1907e commit 9dbd7ff

File tree

6 files changed

+80
-7
lines changed

6 files changed

+80
-7
lines changed

build.sc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import $ivy.`com.lihaoyi::mill-contrib-bloop:$MILL_VERSION`
22
import $ivy.`io.get-coursier::coursier-launcher:2.1.24`
33
import $ivy.`io.github.alexarchambault.mill::mill-native-image-upload:0.1.29`
4-
import $file.project.deps, deps.{Deps, Docker, InternalDeps, Java, Scala, TestDeps}
4+
import $file.project.deps, deps.{Cli, Deps, Docker, InternalDeps, Java, Scala, TestDeps}
55
import $file.project.publish, publish.{ghOrg, ghName, ScalaCliPublishModule, organization}
66
import $file.project.settings, settings.{
77
CliLaunchers,
@@ -454,6 +454,7 @@ trait Core extends ScalaCliCrossSbtModule
454454
| def runnerOrganization = "${runner(Scala.runnerScala3).pomSettings().organization}"
455455
| def runnerModuleName = "${runner(Scala.runnerScala3).artifactName()}"
456456
| def runnerVersion = "${runner(Scala.runnerScala3).publishVersion()}"
457+
| def runnerLegacyVersion = "${Cli.runnerLegacyVersion}"
457458
| def runnerMainClass = "$runnerMainClass"
458459
|
459460
| def semanticDbPluginOrganization = "${Deps.semanticDbScalac.dep.module.organization
@@ -1060,6 +1061,9 @@ trait CliIntegration extends SbtModule with ScalaCliPublishModule with HasTests
10601061
| def maxAmmoniteScala213Version = "${Scala.maxAmmoniteScala213Version}"
10611062
| def maxAmmoniteScala3Version = "${Scala.maxAmmoniteScala3Version}"
10621063
| def maxAmmoniteScala3LtsVersion = "${Scala.maxAmmoniteScala3LtsVersion}"
1064+
| def legacyScala3Versions = Seq(${Scala.legacyScala3Versions.map(p =>
1065+
s"\"$p\""
1066+
).mkString(", ")})
10631067
| def scalaJsVersion = "${Scala.scalaJs}"
10641068
| def scalaJsCliVersion = "${Scala.scalaJsCli}"
10651069
| def scalaNativeVersion = "${Deps.Versions.scalaNative}"
@@ -1069,6 +1073,7 @@ trait CliIntegration extends SbtModule with ScalaCliPublishModule with HasTests
10691073
| def ammoniteVersion = "${Deps.ammonite.dep.version}"
10701074
| def defaultGraalVMJavaVersion = "${deps.graalVmJavaVersion}"
10711075
| def defaultGraalVMVersion = "${deps.graalVmVersion}"
1076+
| def runnerLegacyVersion = "${Cli.runnerLegacyVersion}"
10721077
| def scalaPyVersion = "${Deps.scalaPy.dep.version}"
10731078
| def scalaPyMaxScalaNative = "${Deps.Versions.maxScalaNativeForScalaPy}"
10741079
| def bloopVersion = "${Deps.bloopRifle.dep.version}"

modules/cli/src/main/scala/scala/cli/commands/run/Run.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import scala.build.errors.{BuildException, CompositeBuildException}
1616
import scala.build.input.{Inputs, ScalaCliInvokeData, SubCommand}
1717
import scala.build.internal.{Constants, Runner, ScalaJsLinkerConfig}
1818
import scala.build.internals.ConsoleUtils.ScalaCliConsole
19+
import scala.build.internals.ConsoleUtils.ScalaCliConsole.warnPrefix
1920
import scala.build.internals.EnvVar
2021
import scala.build.options.{BuildOptions, JavaOpt, PackageType, Platform, ScalacOpt, Scope}
2122
import scala.cli.CurrentParams
@@ -103,6 +104,7 @@ object Run extends ScalaCommand[RunOptions] with BuildCommandHelpers {
103104
addRunnerDependencyOpt = baseOptions.notForBloopOptions.addRunnerDependencyOpt.orElse {
104105
runMode(options) match {
105106
case _: RunMode.Spark | RunMode.HadoopJar =>
107+
logger.debug(s"$warnPrefix Skipping the runner dependency when running Spark/Hadoop.")
106108
Some(false)
107109
case RunMode.Default => None
108110
}

modules/integration/src/test/scala/scala/cli/integration/RunTestDefinitions.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,4 +2400,18 @@ abstract class RunTestDefinitions
24002400
expect(res.out.trim() == expectedOutput)
24012401
}
24022402
}
2403+
2404+
test(
2405+
s"run a simple hello world with the runner module on the classpath and Scala $actualScalaVersion"
2406+
) {
2407+
val expectedMessage = "Hello, world!"
2408+
val legacyRunnerWarning = "Defaulting to a legacy runner module version"
2409+
TestInputs(os.rel / "script.sc" -> s"""println("$expectedMessage")""")
2410+
.fromRoot { root =>
2411+
val res = os.proc(TestUtil.cli, "run", ".", "--runner", extraOptions)
2412+
.call(cwd = root, stderr = os.Pipe)
2413+
expect(res.out.trim() == expectedMessage)
2414+
expect(!res.err.trim().contains(legacyRunnerWarning))
2415+
}
2416+
}
24032417
}

modules/integration/src/test/scala/scala/cli/integration/RunTestsDefault.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,23 @@ class RunTestsDefault extends RunTestDefinitions
187187
}
188188
}
189189
}
190+
191+
for {
192+
scalaVersion <-
193+
Constants.legacyScala3Versions.sorted.reverse.distinctBy(_.split('.').take(2).mkString("."))
194+
expectedMessage = "Hello, world!"
195+
expectedWarning =
196+
s"Defaulting to a legacy runner module version: ${Constants.runnerLegacyVersion}"
197+
}
198+
test(
199+
s"run a simple hello world with the runner module on the classpath and Scala $scalaVersion (legacy)"
200+
) {
201+
TestInputs(os.rel / "script.sc" -> s"""println("$expectedMessage")""").fromRoot { root =>
202+
val res =
203+
os.proc(TestUtil.cli, "run", ".", "-S", scalaVersion, TestUtil.extraOptions, "--runner")
204+
.call(cwd = root, stderr = os.Pipe)
205+
expect(res.out.trim() == expectedMessage)
206+
expect(res.err.trim().contains(expectedWarning))
207+
}
208+
}
190209
}

modules/options/src/main/scala/scala/build/Artifacts.scala

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import scala.build.internal.Constants
2323
import scala.build.internal.Constants.*
2424
import scala.build.internal.CsLoggerUtil.*
2525
import scala.build.internal.Util.{PositionedScalaDependencyOps, ScalaModuleOps}
26+
import scala.build.internals.ConsoleUtils.ScalaCliConsole.warnPrefix
2627
import scala.collection.mutable
2728

2829
final case class Artifacts(
@@ -399,18 +400,36 @@ object Artifacts {
399400
}
400401

401402
val (hasRunner, extraRunnerJars) =
402-
if (scalaOpt.nonEmpty) {
403+
if scalaOpt.nonEmpty then {
403404
val addJvmRunner0 = addJvmRunner.getOrElse(false)
404405
val runnerJars =
405-
if (addJvmRunner0) {
406+
if addJvmRunner0 then {
406407
val maybeSnapshotRepo =
407-
if (runnerVersion.endsWith("SNAPSHOT"))
408+
if runnerVersion.endsWith("SNAPSHOT") then
408409
Seq(coursier.Repositories.sonatype("snapshots"))
409410
else Nil
411+
val scalaVersion = (for {
412+
scalaArtifactsParams <- scalaArtifactsParamsOpt
413+
scalaParams = scalaArtifactsParams.params
414+
scalaVersion = scalaParams.scalaVersion
415+
} yield scalaVersion).getOrElse(defaultScalaVersion)
416+
val runnerVersion0 =
417+
if scalaVersion.startsWith("3") &&
418+
scalaVersion.coursierVersion < s"$scala3LtsPrefix.0".coursierVersion
419+
then {
420+
logger.message(
421+
s"""$warnPrefix Scala $scalaVersion is no longer supported by the runner module.
422+
|$warnPrefix Defaulting to a legacy runner module version: $runnerLegacyVersion.
423+
|$warnPrefix To use the latest runner, upgrade Scala to at least $scala3LtsPrefix."""
424+
.stripMargin
425+
)
426+
runnerLegacyVersion
427+
}
428+
else runnerVersion
410429
value {
411430
artifacts(
412431
Seq(Positioned.none(
413-
dep"$runnerOrganization::$runnerModuleName:$runnerVersion,intransitive"
432+
dep"$runnerOrganization::$runnerModuleName:$runnerVersion0,intransitive"
414433
)),
415434
extraRepositories ++ maybeSnapshotRepo,
416435
scalaArtifactsParamsOpt.map(_.params),

project/deps.sc

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import Deps.Versions
22
import mill._
33
import scalalib._
44

5+
object Cli {
6+
def runnerLegacyVersion = "1.7.1" // last runner version to support pre-LTS Scala 3 versions
7+
}
8+
59
object Scala {
610
def scala212 = "2.12.20"
711
def scala213 = "2.13.16"
@@ -32,9 +36,13 @@ object Scala {
3236
def scalaJs = "1.19.0"
3337
def scalaJsCli = scalaJs // this must be compatible with the Scala.js version
3438

39+
private def patchVer(sv: String): Int =
40+
sv.split('.').drop(2).head.takeWhile(_.isDigit).toInt
41+
42+
private def minorVer(sv: String): Int =
43+
sv.split('.').drop(1).head.takeWhile(_.isDigit).toInt
44+
3545
def listAll: Seq[String] = {
36-
def patchVer(sv: String): Int =
37-
sv.split('.').drop(2).head.takeWhile(_.isDigit).toInt
3846
val max212 = patchVer(scala212)
3947
val max213 = patchVer(scala213)
4048
val max30 = 2
@@ -57,6 +65,12 @@ object Scala {
5765
(0 until max37).map(i => s"3.7.$i") ++ Seq(scala3Next)
5866
}
5967

68+
def legacyScala3Versions =
69+
listAll
70+
.filter(_.startsWith("3"))
71+
.distinct
72+
.filter(minorVer(_) < minorVer(scala3Lts))
73+
6074
def maxAmmoniteScala212Version = scala212
6175
def maxAmmoniteScala213Version = scala213
6276
def maxAmmoniteScala3Version = "3.6.3"

0 commit comments

Comments
 (0)