Primary bug — step-level env is not visible in that same step's `if:`
expression. `Decode signing keystore` had
if: env.ANDROID_KEYSTORE_BASE64 != ''
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
so the env context seen by the `if:` evaluator was empty regardless of
whether the secret was configured. The step was skipped, keystore.present
never became 'true', and every release tag silently fell back to
assembleDebug. Result: APKs named `LedGrab-0.4.0-android-debug.apk` that
can't upgrade a previously-release-signed install (signature mismatch).
Fix — move ANDROID_KEYSTORE_BASE64 to the job-level env block. It's now
resolvable in the if-expression of any step in the job, and the shell
inherits it exactly the same way as before.
Secondary — add a "Guard release tag against missing keystore" step that
fires between the decode attempt and the gradle build. If is_release=true
but keystore.present!='true', the job fails with a clear error directing
the operator to configure the four signing secrets. Previously a
misconfigured Gitea silently shipped debug APKs labeled as releases.
build-android.yml
- Attach step upserts the Gitea release: GET /releases/tags/<TAG>, and
POST to create it on 404 instead of warning-and-skipping. Removes the
ordering dependency on release.yml's create-release job — the Android
workflow can now own its own release attachment end-to-end.
- Fail loudly on broken DEPLOY_TOKEN: curl -f on every asset call so
403/422 surface as job failures instead of "Uploaded" lies, and an
explicit check that the token is non-empty before starting.
- Preserve the pre-existing replace-on-re-run behavior for idempotent
asset uploads.
release.yml
- Add workflow_dispatch trigger with optional `version` input so the
Windows/Linux/Docker builds can be exercised on demand between real
releases (was tag-push only).
- Gate create-release on github.event_name == 'push' so a manual
dispatch doesn't create a stray Gitea release.
- Each build job gets `if: !cancelled() && (needs.create-release.result
in (success, skipped))` so dispatch runs still produce artifacts even
though create-release was skipped.
- Gate each "Attach * to release" step on github.event_name == 'push'.
- Docker: login + push are push-only; build runs on both triggers so
dispatch validates the Dockerfile without needing registry creds.
- Create android/app/src/main/python before `ln -sfn` — the parent dir
isn't committed (android/.gitignore:17 ignores /ledgrab inside it) so
fresh CI checkouts had nothing to link into, failing with
"No such file or directory".
- Also wrap the step with `set -euo pipefail` and a `test -d` check so a
broken link aborts the job instead of producing a silently-empty APK.
- Drop the `branches: [master]` push trigger and the `paths:` filter —
every master commit touching android/** or server/src/ledgrab/** was
queueing a ~100 MB APK build that nobody used. Only tag pushes (v*)
and workflow_dispatch remain.
Adds .gitea/workflows/build-android.yml — Linux runner installs JDK 17,
Python 3.11, Android SDK/NDK, symlinks server/src/ledgrab into the
Chaquopy python source dir, and runs assembleDebug on master pushes /
assembleRelease on v* tags. APK is uploaded as an artifact and attached
to the Gitea release on tag push. Conditional signing config in
build.gradle.kts reads keystore from env vars (CI secrets) and falls
back to debug signing locally. Gradle wrapper (gradlew/gradlew.bat/
gradle-wrapper.jar) committed so CI can drive the build.
Rebuilds pydantic-core wheels for arm64-v8a and x86_64 — both were
missing libpython3.11.so in NEEDED, which would have crashed at import
on real devices. build-pydantic-core.sh rewritten as a multi-ABI builder:
selects targets via args, sets RUSTFLAGS=-C link-arg=-Wl,--no-as-needed
-C link-arg=-lpython3.11 to force the symbol-resolution dependency,
uses the per-ABI sysconfigdata + libpython staged in
android/.build-cache/, prefers `py -3.11` on Windows (Git Bash's
python3.11 is an MSStore stub), uses the .cmd clang wrapper on Windows
(fixes os error 193), and verifies NEEDED via llvm-readelf after each
build. abiFilters restored to the full triple in build.gradle.kts;
multi-ABI debug APK builds cleanly (~99 MB).