- write SHA256SUMS into the subtracks-nightly artifact
- assert at least one changelog exists in the metadata test
- drop the unused assembleDebug from the Forgejo CI
- only claim the AAB was uploaded to Play for stable releases
- clean up the export-certificate keystore with a trap
Drop the separate build-nightly workflow: on a push to main the CI job
uploads the debug and nightly APKs as the subtracks-nightly artifact, so
the nightly variant is built once instead of twice (and there is no
second Nix/cache setup).
Add :app:assembleNightly to the CI Gradle invocation so the R8 minify,
resource shrinking and packaging path is exercised on every PR (signed
with the committed debug key, so no secrets are needed).
Replace the reusable workflow with .github/actions/build plus a nested
nix setup action, invoked as a step. CI and the next build stay a single
job (no extra runner or Nix restore); the release keeps its build/publish
split for credential isolation.
Extract checkout, nix, signing and the Gradle run into a reusable build
workflow used by CI, the next build and the release build job. The build
job holds only the signing secrets; the publish job is the only one with
a write token and the Play credential. The Play service account is now
written to a 0600 file and passed via --json_key instead of on argv.
The v4 pair targets Node 20, which GitHub now forces onto Node 24 (Node 20 is
deprecated). The Forgejo runner is v13, which runs Node 24, so both copies move
together. Pin the GitHub runner to ubuntu-26.04: ubuntu-latest migrates to it
over Oct 19 - Nov 19, 2026, and Nix supplies the toolchain either way.
Add .github/workflows/ci.yml, a copy of the Forgejo CI workflow adapted to
GitHub-hosted runners (ubuntu-latest + cachix/install-nix-action), so pull
requests on the GitHub mirror get the lint, unit-test and integration checks.
The GitHub copy uses a 90 minute timeout so a cold run can finish and warm the
caches, caps the Nix cache so it cannot evict the Gradle/music caches from
GitHub's 10 GB per-repo budget, and pins the job token to contents:read.