Skip to content

Commit feb87ef

Browse files
authored
Migrate to sbt 2 (#998)
- Bump sbt 1.12.13 -> 2.0.1, sbt-jcheckstyle 0.2.1 -> 0.3.0 (now sbt2 cross-built, the previous blocker), sbt-osgi 0.10.0 -> 0.11.0-RC1 (only version with an sbt2 cross-build so far) - Fix build.sbt for sbt 2's new task engine (Def.uncached for the checkstyle-dependsOn override, Scala 3.8 strictness warnings) - sbt 2 requires JDK 17+ to run, so decouple "JDK running sbt" from "JDK under test/compile": fork both compilation and tests onto a target JDK via javaHome/TEST_JAVA_HOME, with -release 8 added to scalacOptions since scalac compiles in-process and doesn't fork like javac - Update CI.yml/release.yml/snapshot.yml accordingly so the JDK 8/11/17/21/24 test matrix and publish workflows keep working - Fix an unrelated flaky MessageBufferInputTest (mkdirs() ordering) surfaced while validating the migration
1 parent ed9dd9c commit feb87ef

7 files changed

Lines changed: 65 additions & 12 deletions

File tree

.github/workflows/CI.yml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,16 @@ jobs:
4040
if: ${{ needs.changes.outputs.code == 'true' }}
4141
steps:
4242
- uses: actions/checkout@v6
43+
# sbt 2 requires JDK 17+ to run
44+
- uses: actions/setup-java@v5
45+
with:
46+
distribution: 'zulu'
47+
java-version: '21'
4348
- name: jcheckstyle
4449
run: ./sbt jcheckStyle
4550
- name: scalafmtCheckAll
4651
run: ./sbt scalafmtCheckAll
47-
52+
4853
test:
4954
name: Test JDK${{ matrix.java }}
5055
runs-on: ubuntu-latest
@@ -55,16 +60,29 @@ jobs:
5560
java: ['8', '11', '17', '21', '24']
5661
steps:
5762
- uses: actions/checkout@v6
63+
# The JDK under test: msgpack-core forks its tests onto this JDK (via
64+
# TEST_JAVA_HOME) so we still verify runtime behavior on each target JDK.
5865
- uses: actions/setup-java@v5
66+
id: target-jdk
5967
with:
6068
distribution: 'zulu'
6169
java-version: ${{ matrix.java }}
70+
# sbt 2 itself requires JDK 17+ to run, so install a fixed, newer JDK to
71+
# actually launch sbt. This becomes the default JDK on PATH/JAVA_HOME.
72+
- uses: actions/setup-java@v5
73+
with:
74+
distribution: 'zulu'
75+
java-version: '21'
6276
- uses: actions/cache@v5
6377
with:
6478
path: ~/.cache
6579
key: ${{ runner.os }}-jdk${{ matrix.java }}-${{ hashFiles('**/*.sbt') }}
6680
restore-keys: ${{ runner.os }}-jdk${{ matrix.java }}-
6781
- name: Test
82+
env:
83+
TEST_JAVA_HOME: ${{ steps.target-jdk.outputs.path }}
6884
run: ./sbt test
6985
- name: Universal Buffer Test
86+
env:
87+
TEST_JAVA_HOME: ${{ steps.target-jdk.outputs.path }}
7088
run: ./sbt test -J-Dmsgpack.universal-buffer=true

.github/workflows/release.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,27 @@ jobs:
1616
fetch-depth: 10000
1717
# Fetch all tags so that sbt-dynver can find the previous release version
1818
- run: git fetch --tags -f
19-
# Install OpenJDK 8
19+
# We need to compile with JDK8 for Android compatibility
20+
# https://github.com/msgpack/msgpack-java/issues/516
2021
- uses: actions/setup-java@v5
22+
id: jdk8
2123
with:
22-
# We need to use JDK8 for Android compatibility https://github.com/msgpack/msgpack-java/issues/516
2324
java-version: 8
2425
distribution: adopt
26+
# sbt 2 itself requires JDK 17+ to run; build.sbt forks the compiler (and tests)
27+
# onto JDK8 via TEST_JAVA_HOME, so this becomes the default JDK on PATH/JAVA_HOME.
28+
- uses: actions/setup-java@v5
29+
with:
30+
java-version: 21
31+
distribution: adopt
2532
- name: Setup GPG
2633
env:
2734
PGP_SECRET: ${{ secrets.PGP_SECRET }}
2835
run: echo $PGP_SECRET | base64 --decode | gpg --import --batch --yes
2936
- name: Build bundle
3037
env:
3138
PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
39+
TEST_JAVA_HOME: ${{ steps.jdk8.outputs.path }}
3240
run: |
3341
./sbt publishSigned
3442
- name: Release to Sonatype

.github/workflows/snapshot.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,19 @@ jobs:
2222
# Fetch all tags so that sbt-dynver can find the previous release version
2323
- run: git fetch --tags
2424
- uses: actions/setup-java@v5
25+
id: jdk11
2526
with:
2627
java-version: 11
2728
distribution: adopt
29+
# sbt 2 itself requires JDK 17+ to run; build.sbt forks the compiler onto JDK11
30+
# via TEST_JAVA_HOME, so this becomes the default JDK on PATH/JAVA_HOME.
31+
- uses: actions/setup-java@v5
32+
with:
33+
java-version: 21
34+
distribution: adopt
2835
- name: Publish snapshots
2936
env:
3037
SONATYPE_USERNAME: '${{ secrets.SONATYPE_USERNAME }}'
3138
SONATYPE_PASSWORD: '${{ secrets.SONATYPE_PASSWORD }}'
39+
TEST_JAVA_HOME: ${{ steps.jdk11.outputs.path }}
3240
run: ./sbt publish

build.sbt

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import scala.language.implicitConversions
2+
13
Global / onChangedBuildSource := ReloadOnSourceChanges
24

35
// For performance testing, ensure each test run one-by-one
@@ -67,8 +69,25 @@ val buildSettings = Seq[Setting[?]](
6769
crossPaths := false,
6870
publishMavenStyle := true,
6971
// JVM options for building
70-
scalacOptions ++= Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-feature"),
72+
// -release 8 pins scalac's resolution of JDK API calls to the JDK8 surface (e.g.
73+
// test code calling ByteBuffer.flip() resolves to the inherited Buffer.flip():Buffer
74+
// rather than JDK9's covariant ByteBuffer.flip():ByteBuffer override, which doesn't
75+
// exist on a real JDK8 at runtime -> NoSuchMethodError). Unlike javac's --release,
76+
// this doesn't need an ignore-symbol-file escape hatch since test code never touches
77+
// JDK-internal APIs the way the main sources' Unsafe usage does.
78+
scalacOptions ++=
79+
Seq("-encoding", "UTF-8", "-deprecation", "-unchecked", "-feature", "-release", "8"),
7180
Test / javaOptions ++= Seq("-ea"),
81+
// sbt 2 itself requires JDK 17+ to run, but each CI lane still needs to compile and
82+
// test against its own target JDK (e.g. 8) to faithfully reproduce runtime behavior:
83+
// javac resolves API calls against whichever JDK actually runs it (-source/-target
84+
// only constrain language level and bytecode version, not API resolution), so e.g.
85+
// compiling on JDK9+ can bind to covariant overloads like ByteBuffer.flip():
86+
// ByteBuffer that don't exist on a real JDK8 at runtime. When TEST_JAVA_HOME is set,
87+
// fork both compilation and test execution onto that JDK; otherwise use the JDK
88+
// running sbt, as before.
89+
javaHome := sys.env.get("TEST_JAVA_HOME").map(file),
90+
Test / fork := true,
7291
javacOptions ++= Seq("-source", "1.8", "-target", "1.8"),
7392
Compile / compile / javacOptions ++=
7493
Seq("-encoding", "UTF-8", "-Xlint:unchecked", "-Xlint:deprecation"),
@@ -92,8 +111,8 @@ val buildSettings = Seq[Setting[?]](
92111
// Style check config: (sbt-jchekcstyle)
93112
jcheckStyleConfig := "facebook",
94113
// Run jcheckstyle both for main and test codes
95-
Compile / compile := ((Compile / compile) dependsOn (Compile / jcheckStyle)).value,
96-
Test / compile := ((Test / compile) dependsOn (Test / jcheckStyle)).value
114+
Compile / compile := Def.uncached((Compile / compile).dependsOn(Compile / jcheckStyle).value),
115+
Test / compile := Def.uncached((Test / compile).dependsOn(Test / jcheckStyle).value)
97116
)
98117

99118
val junitJupiter = "org.junit.jupiter" % "junit-jupiter" % "5.14.4" % "test"
@@ -134,7 +153,6 @@ lazy val msgpackCore = Project(id = "msgpack-core", base = file("msgpack-core"))
134153
"--add-opens=java.base/java.nio=ALL-UNNAMED",
135154
"--add-opens=java.base/sun.nio.ch=ALL-UNNAMED"
136155
),
137-
Test / fork := true,
138156
libraryDependencies ++=
139157
Seq(
140158
// msgpack-core should have no external dependencies

msgpack-core/src/test/scala/org/msgpack/core/buffer/MessageBufferInputTest.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ class MessageBufferInputTest extends AirSpec:
5858
def toByteBuffer = ByteBuffer.wrap(b)
5959

6060
def saveToTmpFile: File =
61-
val tmp = File.createTempFile("testbuf", ".dat", new File("target"))
62-
tmp.getParentFile.mkdirs()
61+
val dir = new File("target")
62+
dir.mkdirs()
63+
val tmp = File.createTempFile("testbuf", ".dat", dir)
6364
tmp.deleteOnExit()
6465
withResource(new FileOutputStream(tmp)) { out =>
6566
out.write(b)

project/build.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
sbt.version=1.12.13
1+
sbt.version=2.0.1
22

project/plugins.sbt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1")
22
// TODO: Fixes jacoco error:
33
// java.lang.NoClassDefFoundError: Could not initialize class org.jacoco.core.internal.flow.ClassProbesAdapter
44
//addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.3.0")
5-
addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.2.1")
6-
addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.10.0")
5+
addSbtPlugin("org.xerial.sbt" % "sbt-jcheckstyle" % "0.3.0")
6+
addSbtPlugin("com.github.sbt" % "sbt-osgi" % "0.11.0-RC1")
77
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.6.1")
88
addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.1.1")
99

0 commit comments

Comments
 (0)