ci: fail when an ABI split ships fewer native libraries than its siblings - #7013
Merged
jamesarich merged 1 commit intoSep 2, 2026
Merged
Conversation
…ings A dependency published for only some of our ABIs builds and installs cleanly on the rest and dies with UnsatisfiedLinkError the first time it is touched. Nothing at build time says a word. That is #7001: maplibre-native-ffi 0.202608.3 ships arm64-v8a and x86_64 only, so the F-Droid armeabi-v7a split had no map engine and opening the map took the app down. Compare the split APKs in android-check, where every PR already builds them. The reference set is the union across splits — a library any ABI ships is one the app expects to load — and each split must carry all of it unless a known-gap line in scripts/lib/abi-parity.sh says otherwise. Known gaps are checked both ways. The library must be absent, and the check fails once it turns up, so an entry cannot outlive its reason: the maplibre-compose bump that closes this one goes red until its two lines are deleted with it. Without that, Renovate would land the bump and nothing would mark #7001 closed. The two lines recorded now are the MapLibre gap on fdroid/armeabi-v7a. The 32-bit build upstream merged on 2026-08-24 (maplibre-native-ffi #658, #659, #660) has no release yet; on those devices the app shows a message instead of a map meanwhile. A fixture self-test runs in lint-check, mirroring verify-rb-selftest.sh: the real check only ever sees what the current dependencies happen to ship, so both failure modes would otherwise go unexercised until they bit.
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Sep 2, 2026
Collaborator
Author
|
Rolled into #7005 rather than stacked: pull-request.yml only triggers for PRs targeting main or release/**, so a PR based on a feature branch gets no CI here, and the parity check has to run in android-check to prove itself. GitHub marked this merged when the fast-forward put its commit into the base branch. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A dependency published for only some of our ABIs builds and installs cleanly on the rest, then dies with
UnsatisfiedLinkErrorthe first time it is touched — and nothing at build time says a word. That is #7001:maplibre-native-ffi 0.202608.3ships arm64-v8a and x86_64 only, so the F-Droidarmeabi-v7asplit had no map engine and opening the map took the app down. The two shippedv2.8.2-closed.1splits were 32.5 MB and 18.2 MB and CI was green.Stacked on #7005, which makes the crash a message. This makes the gap visible, and makes closing it verified.
Relates to #7001.
🧹 Chores
scripts/lib/abi-parity.sh— the classifier. The reference set is the union of native libs across a flavor's split APKs; every split must carry all of it unless a known-gap line says otherwise.scripts/verify-abi-parity.sh— runs inandroid-checkright after the debug assemble, where every PR already builds the splits. Fails on a missing lib with the three ways out (fix the dependency, drop the ABI, record a known gap with its reason).scripts/verify-abi-parity-selftest.sh— fixture self-test inlint-check, mirroringverify-rb-selftest.sh. The real check only ever sees what the current dependencies happen to ship, so both failure modes would otherwise go unexercised until they bit.The part that matters for review: known gaps are checked both ways
The two lines recorded now are the MapLibre gap on
fdroid/armeabi-v7a. An entry must be absent from its split — and the check fails once the library turns up, so an entry cannot outlive its reason.That closes the hole in the obvious alternative. Renovate tracks the 8
org.maplibre.composeartifacts in the catalog and will bumpmaplibre-composewhen a release with the 32-bit build lands (upstream merged it 2026-08-24: maplibre-native-ffi #658, #659, #660; no release yet). Without this, that bump lands green and nothing marks #7001 closed. With it, the bump PR goes red with "the gap has closed, delete those lines", and deleting them is the proof the v7a APK really has an engine.Why not the snapshot pin (#7003)
Closed in favour of this. Verified against it directly:
0.1.0-SNAPSHOTwas re-published overnight — yesterday's bytes were20260825.201433-1, today's are20260902.064417-1. Same version string, different engine.-androidis064417-1,-runtime-opengl-androidis064601-1), and Central's snapshot retention is 90 days, so a merged pin would 404 for any rebuild of that tag after late November.rb-checkwould not have caught any of that: it assembles the APK once and never compares two builds.Testing Performed
Run against three real APK sets, not just fixtures:
v2.8.2-closed.1fdroid splits + google splitsshellcheck -xoverscripts/(the lint-check invocation) clean;actionlinton both workflows clean.🤖 Generated with Claude Code