Even after the dnsmasq DNS cache, the Hetzner vSwitch still blips
mid-transfer. Two spots kept killing ~25min builds: the fdroidserver
tarball 'curl -sL | tar' (an empty stream -> 'gzip: unexpected end of
file') and maven/pub fetches mid-Gradle ('Network is unreachable').
Download fdroidserver to a file with curl --retry (+ -f + validate the
gzip before extract), and wrap fdroid build in a 3-attempt loop gated on
the APK actually appearing (fdroid build exits 0 even on failure).
F-Droid's reproducible-build verification failed: the native .so
(Flutter libapp/libdartjni + tesseract4android libjpeg/leptonica/pngx/
libtesseract) differed byte-for-byte. Root cause: F-Droid builds under
/home/vagrant/build/<appid> (its buildserver path) while our reference
built under /tmp/fdroiddata/build/<appid> — the differing absolute build
path leaks into the native libs (debug info / embedded paths). Build the
reference under /home/vagrant so app + srclib paths match F-Droid's.
Also: add a workflow_dispatch ref_tag input to rebuild+re-upload an
existing release's reference APKs (idempotent asset replace) without
cutting a new tag or re-deploying to Play — so reproducibility fixes can
be iterated on the same v* release.
A tag push started play (AAB → Play) and fdroid_reference_armeabi_v7a at
the same instant; two heavy Android builds on the shared runner
(capacity:2) OOM-killed play's Gradle daemon ('daemon disappeared') deep
in bundleRelease. Chain the fdroid references after play with needs:play
+ if:always() so only one Android build runs at a time. if:always() keeps
the fdroid chain independent of play's result (still runs when play fails
or, on workflow_dispatch, is skipped).
- play job: apply the same two fixes the fdroid recipe uses (strip
flutter_tesseract_ocr's dead-jcenter buildscript; cap Gradle heap to
-Xmx4g + no daemon) so a cold-cache production AAB build can't hit
either blocker. play builds the AAB directly, not via the recipe, so
it was still exposed.
- pubspec: 0.1.9+11 -> 0.1.10+12.
- fdroid recipe: versionName 0.1.10, versionCodes 121/122/123,
commit v0.1.10, CurrentVersion(Code) 0.1.10/123. binary: uses %v so
it resolves to the v0.1.10 release assets the tag build will upload.
The v0.1.10 tag is intentionally NOT cut here: cutting it deploys to
Google Play PRODUCTION (100%) and uploads the 3 signed reference APKs.
Closes the physical↔digital loop the labels opened: the QR on a printed
envelope (tane://seed, already encoded by seed_label_codec) can now be
scanned from the inventory bar. A known label opens its variety; an
unknown one asks before adding anything, then creates the variety (species
linked by exact scientific name when bundled) with a lot carrying the
label's year and origin. Scanner is pure ZXing (zxing_barcode_scanner,
MIT) — no ML Kit, no Play Services, F-Droid-safe, the stack Ğ1nkgo ships.
Mobile-only; other platforms don't show the button (OCR precedent).
The post-scan flow is a plain function (handleScannedPayload) so it's
widget-tested without a camera.
The cirruslabs/flutter job image has no Node.js, so JS-based actions fail with
'exec: node: not found'. Check out with plain git over the internal forgejo:3000
URL + job token, keeping the workflows Node-free.
git.comunes.org runs Forgejo Actions, not GitLab CI, so the tag-triggered
signed-AAB build + fastlane Play upload now lives in .forgejo/workflows/release.yml
(single job, no cross-job artifact passing). Removed the equivalent GitLab jobs;
.gitlab-ci.yml keeps only the analyze/test gate. Play service account is reused
from Ğ1nkgo. docs/release.md updated (Forgejo secrets).