summaryrefslogtreecommitdiff
path: root/bin/publish-apk
AgeCommit message (Collapse)Author
2026-09-25publish-apk: allow publishing from another machine over sshHEADmainClaude
The host gate stopped the Fedora laptop publishing at all, which left a build made there with nowhere to go. It now takes PUBLISH_SSH and sends the file to the real host instead. The gate itself is unchanged in spirit: without PUBLISH_SSH a build from elsewhere is still refused, because the failure it guards against is writing to a local path that merely looks like the deploy host's. Two tests cover that -- the error names the way out, and a failed remote publish never falls back to writing locally. Transfers land on a temporary name and move into place only once complete, and the remote copy is hash-compared against the source before the served bytes are checked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
2026-09-21publish-apk: cap the backups it createsClaude
Four publishes in one evening left 448MB of .bak copies of a 112MB APK, in a public web directory. A backup policy with no retention becomes the problem it was guarding against. Keeps the two most recent, configurable with --keep. Prunes before copying, so a failed publish doesn't skip the pruning as well. The first version of the test gave all four fixture backups the same mtime, so 'ls -t' ordered them arbitrarily and 'keeps the most recent' proved nothing -- it only failed because the arbitrary order happened to go the wrong way. Worth recording: a test that passes for the wrong reason is the same class of problem as the dead code these guards exist to catch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
2026-09-21publish-apk: fix a SIGPIPE this repo's own README warns aboutClaude
The zip check used `unzip -l | grep -q`. Under pipefail, grep exits on its first match and SIGPIPEs unzip, so the pipeline fails on a perfectly valid file. It rejected a real 112MB APK as 'not an APK'. That exact trap is in the README's table, written after it broke crash detection in android-launch-check. Knowing about a trap is not the same as not falling into it, which is the argument for these scripts existing at all. Captures the listing first and tests it with `case`, and the new test builds a 300-entry zip so grep matches long before the listing ends -- which is when SIGPIPE actually bites. A single-entry fixture would have passed either way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
2026-09-21Add gradle-report, android-ui and publish-apkClaude
Three more wrappers, each from a failure that actually happened while building Listen rather than an imagined one. gradle-report: detekt rejects an invalid config property before analysing anything, exits non-zero, and leaves the previous run's XML in place. That file was read as current findings three times in one session; the tell was line numbers that never moved after a refactor. It now names the rejected property and refuses any report older than the run. Both real shapes of the message are covered -- a misspelled property and structurally invalid YAML say different things. android-ui: a blind `input tap 400 300` landed in FeeDreader's alarm settings, and the screenshot taken immediately after was reported as Listen. Every command verifies the foreground package before acting, and taps resolve by label rather than coordinate. A label matching several elements refuses rather than taking the first -- in a list where every row has the same Play button, the first match is rarely the one meant. The node parsing is a separate file on purpose. The first version inlined it as python3 -c inside a bash case block and the nested quoting mangled the regexes silently: the dump reported one element and a tap landed somewhere else entirely. Shell-quoted parsers are their own trap. publish-apk: publishing is where a silent mistake costs most -- a stale published APK once sat for eight weeks and installing it threw a Room downgrade. It checks the host, proves the file is a real APK rather than an HTML error page, byte-compares what landed against what was tested, and confirms the server serves those same bytes. Test suite is 25 cases, still weighted toward the negative ones: a wrapper that only ever reports PASS is worse than no wrapper. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B