Skip to content

Prepare for 1.0.0: JS/Native cross-build, MiMa, declaration-order eval, publishing hygiene - #3

Merged
stivens merged 4 commits into
mainfrom
prepare-the-1-0-release
Oct 1, 2026
Merged

stivens merged 4 commits into
mainfrom
prepare-the-1-0-release

Conversation

@stivens

@stivens stivens commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Motivation

Preparation for the 1.0.0 release. A 1.0 freezes both the API semantics and the binary
interface, so this PR settles the one arbitrary runtime semantic (eval ordering), cleans up
what the published artifact exposes to users (dependencies, resolvers), puts the machinery in
place to keep the 1.x line binary-compatible (MiMa + early SemVer), and widens the audience
with Scala.js and Scala Native artifacts — nearly free for a compile-time-only library.

Changes

eval now runs handlers in field declaration order

Previously handlers ran in alphabetical order of field name — an arbitrary choice that would
have been frozen by 1.0. Handlers now run in the declaration order of the source type's
primary-constructor fields; handled non-constructor fields (body vals) come last, in
registration order. The contract is documented on CaseComplete.eval and in the README, and
pinned by tests that distinguish declaration, alphabetical, and registration order.

Internally, compileImpl already knows the field order at expansion time, so the emitted code
now passes a single pre-ordered List[SOURCE_TYPE => TARGET_TYPE] to CaseCompleteImpl,
replacing the name-keyed Map + runtime sort. getHandledFields preserves registration order
to support this.

⚠️ Behaviorally breaking vs 0.3.0 for anyone relying on the alphabetical order — intentional,
and the reason this lands in 1.0.0 rather than after it.

Cross-build for Scala.js and Scala Native

The build is now an sbt-crossproject (CrossType.Pure at the repo root) targeting JVM,
Scala.js 1.x, and Scala Native 0.5
. Sources are shared; the full test suite runs on all
three platforms. Artifacts: casecomplete_3, casecomplete_sjs1_3, casecomplete_native0.5_3.

Test-only adjustments this surfaced: java.time.Year replaced with Int (no java.time in
the JS/Native javalibs) and a Double fixture value replaced with Int (Scala.js renders
7.0 as "7").

Binary-compatibility guardrail (MiMa)

  • sbt-mima-plugin wired into CI via the existing test invocation (sbt 'test; mimaReportBinaryIssues').
  • mimaPreviousArtifacts is intentionally empty until 1.0.0 ships (it is a new baseline);
    the exact expression to flip afterwards is spelled out in build.sbt.
  • versionScheme := Some("early-semver") declared in the POM, and a compatibility-policy
    section added to the README.

Publishing hygiene

  • Dependency leak fixed: scalactic was a compile-scoped dependency in the published POM;
    scalatest is now % Test, so the library has zero runtime dependencies beyond the Scala
    standard library (verified in the generated POM).
  • Removed stray resolvers (shibboleth-releases, Sonatype snapshots) — everything resolves
    from Maven Central.
  • Build settings consolidated into inThisBuild + per-project blocks.

Docs & CI

  • README: cross-platform install snippet (%%%), documented eval ordering, compatibility
    policy, platform requirements, typo fix (equivalant → equivalent).
  • CI: job timeout raised 15 → 30 minutes to accommodate JS/Native linking.

@stivens

stivens commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner Author

The build was on sbt 1.11.3, with several plugins behind their latest releases. sbt 2.x is now stable (2.0.9), and the plugins this build depends on publish sbt 2 versions. Moving now means 1.0.0 is built and published with the current toolchain, so the first post-1.0 release doesn't need a build migration.

Changes

sbt 1.11.3 → 2.0.9

  • project/build.properties: sbt.version=2.0.9
  • %%% → %% in build.sbt. sbt 2's %% picks the right JVM, JS or Native artifact itself, and %%% no longer compiles.
  • addDependencyTreePlugin removed: dependencyTree is built into sbt 2, and the old line is now a deprecated no-op.

Publishing: sbt-sonatype → sbt's built-in Sonatype Central support

sbt-sonatype has no sbt 2 build. sbt 2 publishes to Sonatype Central itself, so:

  • publishTo := localStaging.value replaces sonatypePublishToBundle.value
  • sonatypeCredentialHost / the xerial.sbt.Sonatype import are gone

The release command changes to sbt publishSigned sonaRelease, replacing sonatypeBundleRelease.

sbt-dependency-check removed

It has no sbt 2 build. If we want CVE scanning, it should move into a CI step.

Scala Native test-interface version scheme

Under sbt 2, the Native test update failed:

org.scala-native:test-interface_native0.5_3:0.5.12 (strict) is selected over 0.5.10

The sbt-scala-native plugin brings in 0.5.12, while scalatest 3.2.20 depends on 0.5.10. test-interface marks its versions as strict, so sbt 2 treats that patch-level difference as a fatal error. Scala Native keeps 0.5.x binary compatible, so .nativeSettings sets VersionScheme.Always for that one module.

The module name is built from ScalaNativePlatform and scalaBinaryVersion instead of a hardcoded string, so it still matches after future Native or Scala version bumps. An org.scala-native % "*" wildcard would also work, but I didn't use it because it would hide real breaking conflicts in other modules.

Version bumps

Before After
sbt 1.11.3 2.0.9
scalatest 3.2.19 3.2.20
sbt-scalafmt / scalafmt 2.5.5 / 3.9.3 2.6.2 / 3.11.5
sbt-scalafix 0.14.3 0.14.9
sbt-updates 0.6.4 0.7.0
sbt-pgp 2.3.1 2.3.2
sbt-scalajs 1.19.0 1.22.0
sbt-scalajs-crossproject / sbt-scala-native-crossproject 1.3.2 1.4.0
sbt-mima-plugin 1.1.4 1.2.1
actions/checkout / actions/setup-java v4 / v4 v7 / v6

build.sbt was reformatted by the new scalafmt; the changes are alignment only.

@stivens
stivens merged commit 51e1caa into main Oct 1, 2026
1 check passed
@stivens
stivens deleted the prepare-the-1-0-release branch October 1, 2026 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant