Skip to content

build: check binary compatibility against published releases - #465

Merged
maxlambrecht merged 3 commits into
spiffe:mainfrom
jainruchir:build/binary-compatibility-check
Oct 5, 2026
Merged

maxlambrecht merged 3 commits into
spiffe:mainfrom
jainruchir:build/binary-compatibility-check

Conversation

@jainruchir

@jainruchir jainruchir commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closes #463.

Add a japicmp binary compatibility gate for java-spiffe-core and java-spiffe-provider, wired into check and therefore the existing CI builds. This catches changes that still compile from source but break previously compiled consumers, such as the builder return-type change in #377.

  • Resolve the latest stable major.minor.patch release from Maven Central automatically, with -PbaselineVersion=... for maintenance branches.
  • Use detached configurations so Gradle cannot substitute the current project for its published baseline. Compare regular module JARs only, with separate dependency classpaths for resolving referenced types.
  • Check public/protected APIs and synthetic bridge methods, matching Javadoc's exclusions for generated and internal packages. Fail on binary breaks, not compatible additions or source-only incompatibilities.
  • Produce text and HTML reports under each module's build/reports/japicmp/.
  • Document signature-level exclusions and the requirement for a breaking-change changelog entry. Missing artifacts or resolution errors fail rather than silently bypassing the gate; -PbaselineVersion=none explicitly opts out for a first-ever release.

Compatibility issue caught and restored

The check caught an unreleased binary-incompatible change to RetryHandler.scheduleRetry(Runnable) from void to boolean. This signature change was reverted in #469: the original void scheduleRetry(Runnable) API was restored, and the boolean-returning implementation moved to tryScheduleRetry(Runnable). The temporary method exclusion and breaking-change changelog entry have therefore been removed from this PR.

The compatibility gate now checks this method without an exclusion.

Testing

On macOS arm64:

  • The initial implementation passed ./gradlew build on JDK 25, including 608 existing unit tests and nine new Gradle TestKit tests. Its TestKit suite and both module compatibility tasks also passed on JDK 17 and JDK 21 with Gradle 9.6.1.
  • After fix(workloadapi): restore void RetryHandler.scheduleRetry signature #469 and removal of the temporary exclusion, reran all nine TestKit tests and both module compatibility tasks with --rerun-tasks on JDK 25 using the updated Gradle 9.8.0 wrapper; all passed.
  • Fixtures exercise additions, removed public/protected methods, builder return-type changes, prerelease filtering, pinned and missing baselines, narrow exclusions, and invalidation when the current API or published baseline changes.
  • A regression test compares the actual Maven Central core JARs from 0.8.14 and 0.8.15 and verifies that the removed X509SourceOptionsBuilder and changed builder() signature fail the gate.

Local commands (no SPIRE agent required):

./gradlew :java-spiffe-core:japicmp :java-spiffe-provider:japicmp
./gradlew binaryCompatibilityTest
./gradlew binaryCompatibilityTest --tests '*detectsPublishedBuilderRegressionFrom0814To0815'

SPIRE integration tests were not run; this changes build verification only.

@maxlambrecht

Copy link
Copy Markdown
Member

Thanks for adding this! I'll review it.

@maxlambrecht
maxlambrecht force-pushed the build/binary-compatibility-check branch from dcae21e to 702d8fb Compare October 1, 2026 19:31

@maxlambrecht maxlambrecht left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this! Looks good to me.

@rturner3, could you take a look as well?

@maxlambrecht

Copy link
Copy Markdown
Member

Existing unreleased change

The check found that RetryHandler.scheduleRetry(Runnable) already changed from void to boolean on main in 8cef441. This PR records that exact method as an exclusion and documents its ABI impact in the changelog; it does not modify the retry implementation.

Please review whether to accept that existing break or restore compatibility separately. More generally, does the proposed method/field exclusion plus changelog policy match how you would like to handle intentional ABI changes?

I’ll restore the original void scheduleRetry(Runnable) signature in a separate PR and move the boolean implementation to tryScheduleRetry(Runnable). Since this hasn’t been released, we can preserve compatibility before the next release and remove the exclusion once the fix lands.

Compare core and provider APIs with the latest stable Maven Central release during check. Add TestKit coverage, including the published 0.8.14 to 0.8.15 builder regression, and document baseline overrides and intentional changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Ruchir Jain <122954065+jainruchir@users.noreply.github.com>
@maxlambrecht
maxlambrecht force-pushed the build/binary-compatibility-check branch from 702d8fb to dbf9f4e Compare October 2, 2026 23:06
Comment thread CHANGELOG.md Outdated
jainruchir and others added 2 commits October 5, 2026 11:22
The original scheduleRetry signature was restored in spiffe#469. Remove its temporary exclusion and outdated breaking-change changelog entry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Ruchir Jain <122954065+jainruchir@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Ruchir Jain <122954065+jainruchir@users.noreply.github.com>
@maxlambrecht
maxlambrecht merged commit fc7feb7 into spiffe:main Oct 5, 2026
8 checks passed
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.

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

2 participants