Installation¶
How to add serialkompat to a project: the Gradle plugin, the GitHub Action, or the standalone CLI. Most projects start with the Gradle plugin and add the Action in CI.
The check compares your schema against a baseline in both directions: backward (new code reads old data) and forward (old code reads new data).
Gradle plugin¶
The plugin is on the
Gradle Plugin Portal,
so gradlePluginPortal() (Gradle's default plugin repository) is all you need. Apply
it by id and version, and configure it:
import com.chrisjenx.serialkompat.core.CompatibilityDirection
plugins {
kotlin("jvm")
kotlin("plugin.serialization")
id("com.chrisjenx.serialkompat") version "0.3.1"
}
serialkompat {
types.set(listOf("com.example.wire.OrderEvent", "com.example.wire.Payment"))
jsonInstance.set("com.example.wire.WireJson.instance")
// baselineRef is optional. Unset, it auto-detects your default branch.
direction.set(CompatibilityDirection.FULL)
failOnBreaking.set(true)
failOnEmptyBaseline.set(true)
}
The baseline isn't read from a checked-in file. serialkompat
checks out baselineRef in a temporary git worktree and runs serialkompatExtract
there, so the baseline can't go stale. The plugin must therefore be applied on
baselineRef too; see Quick start → Your first PR.
Extraction runs on your project's own runtime classpath, so your models are read with the same kotlinx-serialization version they were compiled against.
-
Every option
Configuration lists the full
serialkompat { }DSL, includinghistory { }andreports { }. -
Every task
Tasks & CLI lists what each Gradle task does and when it runs.
GitHub Action¶
The Action runs serialkompatCheckAgainst and posts a sticky comment on the pull
request, with annotations on the workflow run. A minimal workflow:
name: serialkompat
on: [pull_request, push]
jobs:
serialkompat:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v7
with: { fetch-depth: 0 }
- uses: actions/setup-java@v6
with: { distribution: temurin, java-version: "17" }
- uses: chrisjenx/serialkompat@v0
with:
ref: origin/main
Keep fetch-depth: 0 and pull-requests: write: the baseline needs full git history,
and the sticky comment needs the permission. CI setup has the inputs, the
sticky comment, versioning (@v0) and other CI systems such as GitLab.
Multi-module builds¶
Apply the plugin in each module that holds @Serializable wire models, and configure
types (or discovery) per module. There is no repo-wide config: each module has its own
types, baselineRef and scope. Modules that hold no wire models can leave the plugin
off. Monorepos covers scoping and --parallel.
Two things to know:
- Gradle stops at the first failing module unless you pass
--continue. See Troubleshooting. - The GitHub Action's sticky comment covers one module's report. See the Action in a multi-module build and the sticky comment.
Kotlin Multiplatform & Android¶
Extraction reads compiled JVM descriptors on a JVM runtime classpath, so the module must produce JVM classes.
- Kotlin/JVM modules: supported. The plugin reads the module's
runtimeClasspath. - Kotlin Multiplatform with a
jvm()target: supported. The plugin readsjvmRuntimeClasspathand thejvm()target's compiled classes. Models incommonMainare checked because they are compiled into that target. A functional test coversOPT_OUTdiscovery ofcommonMainmodels in such a module. - KMP with no
jvm()target (for example JS-only): not supported. With no serialkompat configuration the plugin is a no-op and doesn't breakcheck(a functional test covers a JS-only module). If you configure it there, there are no JVM classes to extract. Add ajvm()target, or move the wire models to a module that has one. - Android modules (
com.android.library,com.android.application): not supported directly. The plugin has no Android-specific handling: it looks up onlyruntimeClasspathandjvmRuntimeClasspath, and it isn't tested on Android. Put the wire models in a JVM or KMP-jvm()module and apply the plugin there; the Android module can depend on that module like any other.
CLI¶
The CLI diffs two snapshot files without a Gradle build in the loop. Use it for non-Gradle or cross-repo checks, such as comparing a producer and a consumer that live in different repositories.
The CLI isn't published as a download yet. Build it from a checkout of this repository:
$ ./gradlew :serialkompat-cli:installDist
$ serialkompat-cli/build/install/serialkompat-cli/bin/serialkompat-cli --help
The docs call that launcher serialkompat; alias or rename it as you like.
Producing snapshots¶
The CLI only diffs. Extraction needs a compiled classpath, so produce each .snapshot
file with the Gradle plugin's serialkompatExtract task: once at your baseline, and
once at the current commit.
$ ./gradlew serialkompatExtract # writes build/serialkompat/current.snapshot
$ serialkompat diff baseline.snapshot current.snapshot
For flags and exit codes, see Tasks & CLI. For a worked producer/consumer example, see Cross-repo with the CLI.