Skip to content

Add a binary-compatibility check to catch unintended ABI breaks between releases #463

Description

@jainruchir

Some releases change the public binary API without it being flagged as a breaking change, which surfaces for consumers as a runtime NoSuchMethodError/NoClassDefFoundError (from a jar compiled against the previous version) rather than a compile error that would be caught early.

The clearest recent example is 0.8.15: #377 removed Lombok and hand-wrote the builders, which renamed the generated builder class DefaultX509Source.X509SourceOptions.X509SourceOptionsBuilderBuilder. Code compiled against <= 0.8.14 then fails at runtime against >= 0.8.15:

java.lang.NoSuchMethodError: 'io.spiffe.workloadapi.DefaultX509Source$X509SourceOptions$X509SourceOptionsBuilder io.spiffe.workloadapi.DefaultX509Source$X509SourceOptions.builder()'

It was listed under "Dependency updates" in the 0.8.15 notes, so the ABI impact appears to have been unintentional.

Proposal

Add a binary-compatibility gate to the build that diffs each build's public API against the last published release and fails on binary-incompatible changes, applied to the consumer-facing modules (java-spiffe-core, java-spiffe-provider).

For this repo specifically (Groovy Gradle, pure Java, multi-module, published to Maven Central via com.vanniktech.maven.publish), the japicmp Gradle plugin looks like the best fit: it applies per subproject and can resolve the previous release from Maven Central as the baseline automatically, so there's no per-release config to maintain. revapi is a more powerful alternative if richer rules are ever needed, though it is likely heavier than this project requires.

This wouldn't block intentional breaking changes; it would make them explicit (an allowlist entry plus a changelog note) instead of silent, so consumers can plan for them.

We're happy to open a PR to wire this up.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions