Close four paths that reported the wrong exit code, and fix red CI - #1
Merged
Merged
Conversation
An outside-in pass over the repo, following the README literally and then exercising the whole exit-code contract. Six things came back. The important one first: a 64-bit ABI directory holding no .so printed PASS and exited 0. lib/<abi>/ can legitimately hold files that are not libraries — wrap.sh, for one — and such a run measured nothing at all while returning a green result, without naming the ABI anywhere in the report. That is exactly the failure the tool exists to refuse. It exits 2 now, and an ABI directory with no library in it is reported as [none] rather than omitted. objdump exiting non-zero was reported as [FAIL] no LOAD segments readable, under "Play will reject this upload" — a measurement announced about a file the tool never managed to open. That case is 2. A library where objdump SUCCEEDS and prints nothing usable is still [FAIL], which is the distinction CONTRIBUTING already draws. --ndk "" and --bundletool "" were treated as if the flag had not been passed, so --ndk "$UNSET_VAR" fell through to auto-detection after being handed an explicit NDK — the silent fallback --ndk exists to prevent. The --ndk= form already errored; the two forms agree now. Auto-detection picked the wrong NDK. The versions were sorted as whole paths on '.', which puts the directory prefix in field 1, where a numeric compare reads it as 0 on both BSD and GNU sort — so the major version was never compared. With 26.3.x, 27.0.x and 28.2.x installed it chose 26.3.x. There is no portable sort spelling of this (sort -V is GNU-only), so version_gt does it in bash. CI on main is red, and has been since the first push. test/run.sh disables SC2329 for its indirectly-invoked test bodies, but ubuntu-latest still ships shellcheck 0.9, which reports that finding as SC2317. Clean on a current local shellcheck, red on CI. Both codes are disabled now, and CONTRIBUTING notes the version gap. Finally, the install command in the README failed as written: it writes to root-owned /usr/local/bin without sudo, so a non-root user gets curl: (56) on macOS and curl: (23) on Ubuntu. It has sudo now, plus a ~/.local/bin form for people who would rather not. Six tests, each failing before its fix. Verified on macOS with shellcheck 0.11 and in ubuntu:24.04 with the 0.9 that CI installs: 40 passed, 0 failed and a clean lint on both.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks 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 |
Two more call sites had the failure-to-measure/measured-failure conflation this branch already fixed for objdump. zipalign: any non-zero status was read as "not aligned". Build-tools older than 35 has no -P flag and exits 2 on the usage error, so a genuinely 16 KB-aligned APK came back as exit 1 under "Play will reject this upload" from a tool that had never checked it. Verified against a real build-tools;34.0.0: it prints "illegal option -- P" and exits 2, while 36.1.0 returns 1 for a real misalignment. 1 stays exit 1; anything else is now exit 2. unzip: its status was discarded with `|| true`, so an archive it could only partly extract was measured on whatever came out. An APK with two 64-bit .so, one of them stored with a compression method unzip cannot decode, extracted one library and reported PASS with exit 0 — reproduced identically on macOS and on ubuntu:24.04. 0, 1 and 11 (nothing matched the glob, which the missing-lib-root check reports properly) still pass through; anything else is exit 2. Two tests, both confirmed failing before the change: FAIL a zipalign that cannot run exits 2, not 1 expected exit 2, got 1 FAIL a partly-extractable archive exits 2 expected exit 2, got 0 No new path reaches 0, and no path that reached 0 legitimately stopped: a real aligned APK still exits 0 and a real unaligned one still exits 1 against NDK 28.2.13676358 and build-tools 36.1.0.
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.
What this changes
Four paths returned the wrong exit code, CI has been red on
mainsince thefirst push, and the README's install command fails as written. One of the four
reached
0.Why
I read the README as instructions and ran them literally, then walked the whole
exit-code contract from the outside. Six things came back.
1.
PASSand exit0on an artifact where nothing was measuredlib/<abi>/can hold files that are not libraries —wrap.shis the obviousone, and Android looks for it there. When the only 64-bit ABI directory held no
.so, the loop setfound64=1, the inner glob matched nothing, and the runfell through to
PASS. The ABI was not named anywhere in the report, so theoutput looked like a clean 32-bit-plus-64-bit app.
Same artifact, after:
found64counted directories; there is now a second counter for librariesactually read, and
[none]is printed rather than the ABI being omitted — samereasoning as the existing
[SKIP]line.2. objdump failing to run was reported as an alignment failure
A non-zero exit from objdump produced
[FAIL] no LOAD segments readableunderPlay will reject this upload— a measurement announced about a file the toolnever opened. Reproduced with the real NDK r28
llvm-objdumpagainst anlib/arm64-v8a/*.sothat is not an ELF (objdump exits1):The status is now read on its own, before parsing. A library where objdump
succeeds and prints nothing usable is still
[FAIL]— that is thedistinction CONTRIBUTING already draws, and
t_unreadable_elf_fails_with_onestill asserts
1. Worth knowing: realllvm-objdumpexits0on atruncated-but-ELF-magic file and
1when it cannot open the file at all, sothe two cases really are distinguishable in practice.
3.
--ndk ""silently became "no--ndkgiven"--ndk "$UNSET_VAR"in a caller's script fell through to auto-detection afterbeing handed an explicit NDK, and could then
PASSusing a toolchain nobodynamed. The
--ndk=form already errored, so the two spellings disagreed. Bothnow reject an empty value. Same for
--bundletool.4. Auto-detection chose the wrong NDK
highest_ndksorted whole paths withsort -t. -k1,1n -k2,2n -k3,3n. Thatputs
/…/ndk/28in field 1, where a numeric compare reads it as0on bothBSD and GNU sort — so the major version was never compared and only the minor
decided. With 26.3.x, 27.0.x and 28.2.x installed:
Not a BSD-vs-GNU split; it is wrong the same way on both.
sort -Vwould beGNU-only, so
version_gtdoes the compare in bash andhighest_ndkno longershells out.
5. CI is red on
mainThe
shellcheckstep has failed on every run so far, which is why the testshave never actually executed in CI.
test/run.shdisablesSC2329for itsindirectly-invoked test bodies, but
ubuntu-lateststill installs shellcheck0.9.0, which reports that finding as SC2317 — the split into SC2329
landed in 0.10. So it is clean on a current local shellcheck (0.11) and red on
CI. Both codes are disabled now, and CONTRIBUTING has a note about the version
gap so the next person does not rediscover it.
6. The install command in the README fails as written
/usr/local/binis root-owned on macOS and on a stock Ubuntu:Now has
sudo, plus a~/.local/binform for people who would rather not. Bothverified verbatim as a non-root user on Ubuntu and on macOS.
Checklist
shellcheck android-16kb-check test/run.sh test/stubs/*is cleantest/run.shpassesCHANGELOG.mdsays so, and theREADME table matches
Verified on macOS (shellcheck 0.11.0) and in
ubuntu:24.04with the 0.9.0 thatCI installs — clean lint and
40 passed, 0 failedon both. Six new tests, eachconfirmed failing against the unfixed script:
If this touches the exit codes
It does, in three places, all in the same direction — away from
0and awayfrom a claimed measurement:
.so0212--ndk ""/--bundletool ""02No new path can reach
0. One path that could is removed. What0,1and
2mean is unchanged — these were paths landing on the wrong one, sothis is a fix rather than a redefinition, and it sits under
[Unreleased]rather than taking a major.
VERSIONis left at1.0.0for you to bump whenyou cut a release.
What you ran it against
A real APK:
libc++_shared.soforarm64-v8a,x86_64andarmeabi-v7ataken from NDK 28.2.13676358, packed with
zip -X -0and aligned withzipalign -P 16 4. Real detection (noANDROID_HOMEset — it walked~/Library/Android/sdk), realllvm-objdump, realzipalign36.1.0:The same libraries packed without
-P 16giveexit 1at the archive stage,and
--ndk /nonexistentgivesexit 2, so all three answers were seen againsta real toolchain.
Two things I found and did not change
LIB_GLOBisbase/lib/*, so anunaligned
.soin a dynamic feature module is invisible and the run canPASS. Play generates APKs from those modules too. Filed separately ratherthan folded in here, since it changes what "the artifact" means.
[1.0.0]and[Unreleased]links in CHANGELOG.md 404 — there is nov1.0.0tag or release yet. Nothing to change in the file; it resolves whenyou tag.