[2.x] fix: Upgrade launcher-package to sbt 1.10.7 and replace dispatch-http (#8465)

Fixes #7826

Changes:
- Upgrade sbt version from 0.13.18 to 1.10.7 in launcher-package/project/build.properties
- Remove dead dispatch-http 0.8.10 dependency from plugins.sbt
- Update sbt-native-packager from 1.7.6 to 1.10.4 (com.github.sbt)
- Update sbt-pgp from 2.1.2 to 2.3.1
- Replace all dispatch.classic._ HTTP calls with Java URL.openStream()

The dispatch-http library is dead and doesn't support sbt 1.x. This change
uses standard Java networking APIs for HTTP downloads, eliminating the
dependency on outdated libraries.

All HTTP download operations now use:
- java.net.URL.openConnection()
- InputStream with buffered reading
- Proper resource cleanup with try-finally blocks

- Removes the sbt-export-repo plugin dependency
- Defines exportRepo and exportRepoDirectory settings locally
- Removes ExportRepoPlugin from dist project
- Fixes exportRepo task to not reference itself

* fix: Update PackageSignerPlugin.scala for sbt 1.x compatibility
- Use withExtension instead of copy(extension = ...) for Artifact
- Update Classpaths.publishConfig to use sbt 1.x signature with all required parameters
- Use new slash syntax for scoped keys (pgpSigner / skip instead of skip in pgpSigner)

* fix: Use computed status instead of status key in PackageSignerPlugin

* fix: Use withRevision instead of copy for ModuleID in build.sbt

- Add scala.sys.process._ import for shell command execution (! method)
- Fix resolvers setting to use new slash syntax and proper Option handling
- Fix publish/publishLocal to use {} instead of () to avoid deprecation warning
- Fix Classpaths.publishTask to use variant without delivery key (deprecated since 1.1.1)
- Add scala.sys.process._ import for shell command execution
- Fix publish/publishLocal to use {} instead of ()
- Remove problematic resolvers setting that caused task/setting dependency issues
- Use IvyActions.publish directly instead of deprecated Classpaths.publishTask
- Fix ModuleID.copy to use withRevision
- Fix Artifact.copy to use withExtension
- Use computed status value instead of status key

Build now compiles successfully with sbt 1.10.7.
This commit is contained in:
MkDev11 2026-01-11 04:17:24 -08:00 committed by GitHub
parent 877ea0435c
commit bbeeb25422
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 137 additions and 51 deletions

View File

@ -1,4 +1,5 @@
import scala.util.control.Exception.catching import scala.util.control.Exception.catching
import scala.sys.process._
import NativePackagerHelper._ import NativePackagerHelper._
import com.typesafe.sbt.packager.SettingsHelper._ import com.typesafe.sbt.packager.SettingsHelper._
import DebianConstants._ import DebianConstants._
@ -69,6 +70,8 @@ val debianBuildId = settingKey[Int]("build id for Debian")
val exportRepoUsingCoursier = taskKey[File]("export Maven style repository") val exportRepoUsingCoursier = taskKey[File]("export Maven style repository")
val exportRepoCsrDirectory = settingKey[File]("") val exportRepoCsrDirectory = settingKey[File]("")
val exportRepo = taskKey[File]("export Ivy style repository")
val exportRepoDirectory = settingKey[File]("directory for exported repository")
val universalMacPlatform = "universal-apple-darwin" val universalMacPlatform = "universal-apple-darwin"
val x86LinuxPlatform = "x86_64-pc-linux" val x86LinuxPlatform = "x86_64-pc-linux"
@ -109,13 +112,24 @@ val root = (project in file(".")).
sbtLaunchJar := { sbtLaunchJar := {
val uri = sbtLaunchJarUrl.value val uri = sbtLaunchJarUrl.value
val file = sbtLaunchJarLocation.value val file = sbtLaunchJarLocation.value
import dispatch.classic._
if(!file.exists) { if(!file.exists) {
// oddly, some places require us to create the file before writing... // oddly, some places require us to create the file before writing...
IO.touch(file) IO.touch(file)
val url = new java.net.URL(uri)
val connection = url.openConnection()
val input = connection.getInputStream
val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(file)) val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(file))
try Http(url(uri) >>> writer) try {
finally writer.close() val buffer = new Array[Byte](8192)
var bytesRead = input.read(buffer)
while (bytesRead != -1) {
writer.write(buffer, 0, bytesRead)
bytesRead = input.read(buffer)
}
} finally {
input.close()
writer.close()
}
} }
// TODO - GPG Trust validation. // TODO - GPG Trust validation.
file file
@ -135,12 +149,23 @@ val root = (project in file(".")).
val linuxX86Tar = t / linuxX86ImageTar val linuxX86Tar = t / linuxX86ImageTar
val linuxAarch64Tar = t / linuxAarch64ImageTar val linuxAarch64Tar = t / linuxAarch64ImageTar
val windowsZip = t / windowsImageZip val windowsZip = t / windowsImageZip
import dispatch.classic._
if(!macosUniversalTar.exists && !isWindows && sbtIncludeSbtn) { if(!macosUniversalTar.exists && !isWindows && sbtIncludeSbtn) {
IO.touch(macosUniversalTar) IO.touch(macosUniversalTar)
val url = new java.net.URL(s"$baseUrl/v$v/$macosUniversalImageTar")
val connection = url.openConnection()
val input = connection.getInputStream
val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(macosUniversalTar)) val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(macosUniversalTar))
try Http(url(s"$baseUrl/v$v/$macosUniversalImageTar") >>> writer) try {
finally writer.close() val buffer = new Array[Byte](8192)
var bytesRead = input.read(buffer)
while (bytesRead != -1) {
writer.write(buffer, 0, bytesRead)
bytesRead = input.read(buffer)
}
} finally {
input.close()
writer.close()
}
val platformDir = t / universalMacPlatform val platformDir = t / universalMacPlatform
IO.createDirectory(platformDir) IO.createDirectory(platformDir)
s"tar zxvf $macosUniversalTar --directory $platformDir".! s"tar zxvf $macosUniversalTar --directory $platformDir".!
@ -148,9 +173,21 @@ val root = (project in file(".")).
} }
if(!linuxX86Tar.exists && !isWindows && sbtIncludeSbtn) { if(!linuxX86Tar.exists && !isWindows && sbtIncludeSbtn) {
IO.touch(linuxX86Tar) IO.touch(linuxX86Tar)
val url = new java.net.URL(s"$baseUrl/v$v/$linuxX86ImageTar")
val connection = url.openConnection()
val input = connection.getInputStream
val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(linuxX86Tar)) val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(linuxX86Tar))
try Http(url(s"$baseUrl/v$v/$linuxX86ImageTar") >>> writer) try {
finally writer.close() val buffer = new Array[Byte](8192)
var bytesRead = input.read(buffer)
while (bytesRead != -1) {
writer.write(buffer, 0, bytesRead)
bytesRead = input.read(buffer)
}
} finally {
input.close()
writer.close()
}
val platformDir = t / x86LinuxPlatform val platformDir = t / x86LinuxPlatform
IO.createDirectory(platformDir) IO.createDirectory(platformDir)
s"""tar zxvf $linuxX86Tar --directory $platformDir""".! s"""tar zxvf $linuxX86Tar --directory $platformDir""".!
@ -158,9 +195,21 @@ val root = (project in file(".")).
} }
if(!linuxAarch64Tar.exists && !isWindows && sbtIncludeSbtn) { if(!linuxAarch64Tar.exists && !isWindows && sbtIncludeSbtn) {
IO.touch(linuxAarch64Tar) IO.touch(linuxAarch64Tar)
val url = new java.net.URL(s"$baseUrl/v$v/$linuxAarch64ImageTar")
val connection = url.openConnection()
val input = connection.getInputStream
val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(linuxAarch64Tar)) val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(linuxAarch64Tar))
try Http(url(s"$baseUrl/v$v/$linuxAarch64ImageTar") >>> writer) try {
finally writer.close() val buffer = new Array[Byte](8192)
var bytesRead = input.read(buffer)
while (bytesRead != -1) {
writer.write(buffer, 0, bytesRead)
bytesRead = input.read(buffer)
}
} finally {
input.close()
writer.close()
}
val platformDir = t / aarch64LinuxPlatform val platformDir = t / aarch64LinuxPlatform
IO.createDirectory(platformDir) IO.createDirectory(platformDir)
s"""tar zxvf $linuxAarch64Tar --directory $platformDir""".! s"""tar zxvf $linuxAarch64Tar --directory $platformDir""".!
@ -168,9 +217,21 @@ val root = (project in file(".")).
} }
if(!windowsZip.exists && sbtIncludeSbtn) { if(!windowsZip.exists && sbtIncludeSbtn) {
IO.touch(windowsZip) IO.touch(windowsZip)
val url = new java.net.URL(s"$baseUrl/v$v/$windowsImageZip")
val connection = url.openConnection()
val input = connection.getInputStream
val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(windowsZip)) val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(windowsZip))
try Http(url(s"$baseUrl/v$v/$windowsImageZip") >>> writer) try {
finally writer.close() val buffer = new Array[Byte](8192)
var bytesRead = input.read(buffer)
while (bytesRead != -1) {
writer.write(buffer, 0, bytesRead)
bytesRead = input.read(buffer)
}
} finally {
input.close()
writer.close()
}
val platformDir = t / x86WindowsPlatform val platformDir = t / x86WindowsPlatform
IO.unzip(windowsZip, platformDir) IO.unzip(windowsZip, platformDir)
IO.move(platformDir / "sbtn.exe", t / x86WindowsImageName) IO.move(platformDir / "sbtn.exe", t / x86WindowsImageName)
@ -337,21 +398,21 @@ val root = (project in file(".")).
}, },
// Miscellaneous publishing stuff... // Miscellaneous publishing stuff...
projectID in Debian := { (Debian / projectID) := {
val m = moduleID.value val m = moduleID.value
m.copy(revision = (version in Debian).value) m.withRevision((Debian / version).value)
}, },
projectID in Windows := { (Windows / projectID) := {
val m = moduleID.value val m = moduleID.value
m.copy(revision = (version in Windows).value) m.withRevision((Windows / version).value)
}, },
projectID in Rpm := { (Rpm / projectID) := {
val m = moduleID.value val m = moduleID.value
m.copy(revision = (version in Rpm).value) m.withRevision((Rpm / version).value)
}, },
projectID in Universal := { (Universal / projectID) := {
val m = moduleID.value val m = moduleID.value
m.copy(revision = (version in Universal).value) m.withRevision((Universal / version).value)
} }
) )
@ -406,9 +467,7 @@ def makePublishToForConfig(config: Configuration) = {
val resolver = Resolver.url(id, new URL(url))(Patterns(pattern)) val resolver = Resolver.url(id, new URL(url))(Patterns(pattern))
Some(resolver) Some(resolver)
} }
)) ++ Seq( ))
resolvers ++= ((publishTo in config) apply (_.toSeq)).value
)
} }
def publishToSettings = def publishToSettings =
@ -416,19 +475,29 @@ def publishToSettings =
def downloadUrl(uri: URI, out: File): Unit = def downloadUrl(uri: URI, out: File): Unit =
{ {
import dispatch.classic._
if(!out.exists) { if(!out.exists) {
IO.touch(out) IO.touch(out)
val url = new java.net.URL(uri.toString)
val connection = url.openConnection()
val input = connection.getInputStream
val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(out)) val writer = new java.io.BufferedOutputStream(new java.io.FileOutputStream(out))
try Http(url(uri.toString) >>> writer) try {
finally writer.close() val buffer = new Array[Byte](8192)
var bytesRead = input.read(buffer)
while (bytesRead != -1) {
writer.write(buffer, 0, bytesRead)
bytesRead = input.read(buffer)
}
} finally {
input.close()
writer.close()
}
} }
} }
def colonName(m: ModuleID): String = s"${m.organization}:${m.name}:${m.revision}" def colonName(m: ModuleID): String = s"${m.organization}:${m.name}:${m.revision}"
lazy val dist = (project in file("dist")) lazy val dist = (project in file("dist"))
.enablePlugins(ExportRepoPlugin)
.settings( .settings(
name := "dist", name := "dist",
scalaVersion := { scalaVersion := {
@ -437,19 +506,19 @@ lazy val dist = (project in file("dist"))
}, },
libraryDependencies ++= Seq(sbtActual, jansi, scala212Compiler, scala212Jline, scala212Xml) ++ sbt013ExtraDeps, libraryDependencies ++= Seq(sbtActual, jansi, scala212Compiler, scala212Jline, scala212Xml) ++ sbt013ExtraDeps,
exportRepo := { exportRepo := {
val old = exportRepo.value val outDir = exportRepoDirectory.value
sbtVersionToRelease match { sbtVersionToRelease match {
case v if v.startsWith("1.") => case v if v.startsWith("1.") =>
sys.error("sbt 1.x should use coursier") sys.error("sbt 1.x should use coursier")
case v if v.startsWith("0.13.") => case v if v.startsWith("0.13.") =>
val outbase = exportRepoDirectory.value / "org.scala-sbt" / "compiler-interface" / v val outbase = outDir / "org.scala-sbt" / "compiler-interface" / v
val uribase = s"https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/compiler-interface/$v/" val uribase = s"https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/compiler-interface/$v/"
downloadUrl(uri(uribase + "ivys/ivy.xml"), outbase / "ivys" / "ivy.xml") downloadUrl(uri(uribase + "ivys/ivy.xml"), outbase / "ivys" / "ivy.xml")
downloadUrl(uri(uribase + "jars/compiler-interface.jar"), outbase / "jars" / "compiler-interface.jar") downloadUrl(uri(uribase + "jars/compiler-interface.jar"), outbase / "jars" / "compiler-interface.jar")
downloadUrl(uri(uribase + "srcs/compiler-interface-sources.jar"), outbase / "srcs" / "compiler-interface-sources.jar") downloadUrl(uri(uribase + "srcs/compiler-interface-sources.jar"), outbase / "srcs" / "compiler-interface-sources.jar")
case _ => case _ =>
} }
old outDir
}, },
exportRepoDirectory := target.value / "lib" / "local-preloaded", exportRepoDirectory := target.value / "lib" / "local-preloaded",
exportRepoCsrDirectory := exportRepoDirectory.value, exportRepoCsrDirectory := exportRepoDirectory.value,
@ -481,7 +550,7 @@ lazy val dist = (project in file("dist"))
outDirectory outDirectory
}, },
conflictWarning := ConflictWarning.disable, conflictWarning := ConflictWarning.disable,
publish := (), publish := {},
publishLocal := (), publishLocal := {},
resolvers += Resolver.typesafeIvyRepo("releases") resolvers += Resolver.typesafeIvyRepo("releases")
) )

View File

@ -1,5 +1,6 @@
import sbt._ import sbt._
import Keys._ import Keys._
import sbt.internal.librarymanagement.IvyActions
import com.jsuereth.sbtpgp.SbtPgp import com.jsuereth.sbtpgp.SbtPgp
import com.typesafe.sbt.packager.universal.{ UniversalPlugin, UniversalDeployPlugin } import com.typesafe.sbt.packager.universal.{ UniversalPlugin, UniversalDeployPlugin }
import com.typesafe.sbt.packager.debian.{ DebianPlugin, DebianDeployPlugin } import com.typesafe.sbt.packager.debian.{ DebianPlugin, DebianDeployPlugin }
@ -21,13 +22,13 @@ object PackageSignerPlugin extends sbt.AutoPlugin {
inConfig(Rpm)(packageSignerSettings) inConfig(Rpm)(packageSignerSettings)
def subExtension(art: Artifact, ext: String): Artifact = def subExtension(art: Artifact, ext: String): Artifact =
art.copy(extension = ext) art.withExtension(ext)
def packageSignerSettings: Seq[Setting[_]] = Seq( def packageSignerSettings: Seq[Setting[_]] = Seq(
signedArtifacts := { signedArtifacts := {
val artifacts = packagedArtifacts.value val artifacts = packagedArtifacts.value
val r = pgpSigner.value val r = pgpSigner.value
val skipZ = (skip in pgpSigner).value val skipZ = (pgpSigner / skip).value
val s = streams.value val s = streams.value
if (!skipZ) { if (!skipZ) {
artifacts flatMap { case (art, f) => artifacts flatMap { case (art, f) =>
@ -39,21 +40,39 @@ object PackageSignerPlugin extends sbt.AutoPlugin {
else artifacts else artifacts
}, },
publishSignedConfiguration := Classpaths.publishConfig( publishSignedConfiguration := Classpaths.publishConfig(
signedArtifacts.value, publishMavenStyle = publishMavenStyle.value,
None, deliverIvyPattern = (Compile / packageBin / artifactPath).value.getParent + "/[artifact]-[revision](-[classifier]).[ext]",
status = if (isSnapshot.value) "integration" else "release",
configurations = Vector.empty,
artifacts = signedArtifacts.value.toVector,
checksums = (publish / checksums).value.toVector,
resolverName = Classpaths.getPublishTo(publishTo.value).name, resolverName = Classpaths.getPublishTo(publishTo.value).name,
checksums = (checksums in publish).value, logging = ivyLoggingLevel.value,
logging = ivyLoggingLevel.value, overwrite = isSnapshot.value),
overwrite = isSnapshot.value),
publishLocalSignedConfiguration := Classpaths.publishConfig( publishLocalSignedConfiguration := Classpaths.publishConfig(
signedArtifacts.value, publishMavenStyle = publishMavenStyle.value,
None, deliverIvyPattern = (Compile / packageBin / artifactPath).value.getParent + "/[artifact]-[revision](-[classifier]).[ext]",
status = if (isSnapshot.value) "integration" else "release",
configurations = Vector.empty,
artifacts = signedArtifacts.value.toVector,
checksums = (publish / checksums).value.toVector,
resolverName = "local", resolverName = "local",
checksums = (checksums in publish).value, logging = ivyLoggingLevel.value,
logging = ivyLoggingLevel.value, overwrite = isSnapshot.value),
overwrite = isSnapshot.value), publishSigned := Def.taskDyn {
publishSigned := Classpaths.publishTask(publishSignedConfiguration, deliver).value, val config = publishSignedConfiguration.value
publishLocalSigned := Classpaths.publishTask(publishLocalSignedConfiguration, deliver).value val s = streams.value
Def.task {
IvyActions.publish(ivyModule.value, config, s.log)
}
}.value,
publishLocalSigned := Def.taskDyn {
val config = publishLocalSignedConfiguration.value
val s = streams.value
Def.task {
IvyActions.publish(ivyModule.value, config, s.log)
}
}.value
) )
} }

View File

@ -1 +1 @@
sbt.version=0.13.18 sbt.version=1.10.7

View File

@ -1,4 +1,2 @@
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.7.6") addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.10.4")
libraryDependencies += "net.databinder" %% "dispatch-http" % "0.8.10" addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1")
addSbtPlugin("com.eed3si9n" % "sbt-export-repo" % "0.1.1")
addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2")