ZaStoGram/docs/superpowers/specs/2026-06-27-abi-split-apk-design.md
loop-uh d8559b8810
All checks were successful
Build four ZaStoGram APKs / build (arm64-v8a, ZaStoGram-standalone-arm64-v8a, Arm64, arm64) (push) Successful in 17m13s
Build four ZaStoGram APKs / build (armeabi-v7a, ZaStoGram-standalone-armeabi-v7a, Armv7, armv7) (push) Successful in 7m57s
Build four ZaStoGram APKs / build (x86, ZaStoGram-standalone-x86, X86, x86) (push) Successful in 7m48s
Build four ZaStoGram APKs / build (x86_64, ZaStoGram-standalone-x86_64, X64, x64) (push) Successful in 10m35s
ZaStoGram source guards / guards (push) Successful in 19s
Убрать совместимость workflow с GitHub
2026-08-07 06:57:28 +03:00

100 lines
4.2 KiB
Markdown

# ABI-Split APK Forgejo Actions Design
## Goal
Build four installable ZaStoGram standalone APKs in Forgejo Actions instead of one fat `afat` APK:
- `arm64-v8a`
- `armeabi-v7a`
- `x86`
- `x86_64`
Each successful workflow run should expose architecture-specific APK outputs instead of a single universal APK.
## Current State
The existing workflow builds `:TMessagesProj_AppStandalone:assembleAfatStandalone` and uploads the resulting APK through `actions/upload-artifact`.
`TMessagesProj_AppStandalone/build.gradle` currently has a single `afat` flavor whose `ndk.abiFilters` include all four supported ABIs. That produces one universal APK containing native libraries for every architecture, which makes the output larger than needed for a single device.
## Architecture
Add explicit ABI product flavors in `TMessagesProj_AppStandalone/build.gradle`.
Each flavor keeps the standalone build type and manifest behavior, but restricts native output to one ABI:
- `arm64` -> `arm64-v8a`
- `armv7` -> `armeabi-v7a`
- `x86` -> `x86`
- `x64` -> `x86_64`
Keep the existing `afat` flavor as a fallback for local/manual universal builds unless it causes a Gradle conflict.
Each ABI flavor gets a distinct two-digit `abiVersionCode` above the old universal `afat` suffix `9`. The `applicationVariants` version-code rule remains the central place that derives the final version code from `APP_VERSION_CODE` and the flavor suffix, using `APP_VERSION_CODE * 100 + abiVersionCode` so ABI split APKs can update over previously installed universal APKs.
The existing `variantFilter` must also allow the new ABI flavors for the `standalone` build type; otherwise Gradle will not create the matrix task names.
## Forgejo Actions
Refactor `.forgejo/workflows/build-apk.yml` to use a matrix with one entry per ABI flavor.
Shared setup remains in one job definition:
- checkout
- disk cleanup
- JDK 17 setup
- Android SDK/NDK/CMake install
- legacy `dx` compatibility hack
- ccache setup
- optional Telegram API secret injection
- MTProxy diagnostic log enablement
- signing keystore setup
- MTProxy guard suite
The build step becomes matrix-driven:
- `:TMessagesProj_AppStandalone:assembleArm64Standalone`
- `:TMessagesProj_AppStandalone:assembleArmv7Standalone`
- `:TMessagesProj_AppStandalone:assembleX86Standalone`
- `:TMessagesProj_AppStandalone:assembleX64Standalone`
Each matrix leg stages exactly one APK into `dist/` with a stable architecture-specific name:
- `dist/ZaStoGram-standalone-arm64-v8a.apk`
- `dist/ZaStoGram-standalone-armeabi-v7a.apk`
- `dist/ZaStoGram-standalone-x86.apk`
- `dist/ZaStoGram-standalone-x86_64.apk`
## Outputs
At minimum, Forgejo Actions should upload four architecture-specific artifacts, each containing the matching APK.
The workflow can also publish a run-specific prerelease with four direct `.apk` assets if direct install links are desired. If enabled, the prerelease should use a run-specific tag based on `forgejo.run_number` and `forgejo.run_attempt`.
Forgejo Actions artifacts may remain for CI history. They are not the same as direct APK release assets because Forgejo downloads artifacts as ZIP files.
## Caching
Use ABI-aware ccache keys so architectures do not fight over the same native object cache.
Gradle cache setup can remain shared through `actions/setup-java`, because Gradle's own cache separates task inputs.
## Verification
Local verification should include:
- static inspection that the standalone Gradle file defines all four ABI flavors with the expected `abiFilters`
- static inspection that the workflow matrix contains all four ABI entries
- static inspection that APK staging names are architecture-specific
- static inspection that uploaded output names are ABI-specific
- if release publishing is enabled, static inspection that release upload publishes `.apk` files directly
- the existing MTProxy guard suite remains part of CI
If full Gradle assembly cannot run locally because of SDK/NDK configuration, that must be reported separately from the YAML/Gradle contract verification.
## Out Of Scope
- Changing app package names or signing policy.
- Removing the universal `afat` fallback unless Gradle requires it.
- Reworking MTProxy runtime logic.
- Creating four copy-pasted workflow files.