Skip to content

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:

build.gradle.kts
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, including history { } and reports { }.

  • 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:

.github/workflows/serialkompat.yml
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:

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 reads jvmRuntimeClasspath and the jvm() target's compiled classes. Models in commonMain are checked because they are compiled into that target. A functional test covers OPT_OUT discovery of commonMain models 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 break check (a functional test covers a JS-only module). If you configure it there, there are no JVM classes to extract. Add a jvm() 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 only runtimeClasspath and jvmRuntimeClasspath, 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.