FN-7014: publish Android APK release artifacts

Adds Android APK generation to binary release and rehearsal workflows so GitHub releases ship mobile assets.

- Add Android build jobs that sync Capacitor, assemble the debug APK, and upload APK/checksum artifacts.
- Include Android artifacts in release and test-release collection dependencies and file matching.
- Document Android release outputs and extend workflow shape tests for the new asset path.

Files changed:
 .github/workflows/release.yml                      | 86 +++++++++++++++++++++-
 .github/workflows/test-release.yml                 | 85 ++++++++++++++++++++-
 MOBILE.md                                          |  2 +-
 RELEASING.md                                       | 10 ++-
 packages/cli/src/__tests__/ci-workflow.test.ts     |  6 +-
 packages/desktop/README.md                         |  1 +
 .../desktop/src/__tests__/release-workflow.test.ts | 24 +++++-
 7 files changed, 201 insertions(+), 13 deletions(-)

Fusion-Task-Id: FN-7014
Fusion-Task-Lineage: 8ed94f64-399b-433f-add4-0294fc5722d1
This commit is contained in:
gsxdsm
2026-06-25 17:42:22 -07:00
parent 90c0e9936e
commit dba65933e5
7 changed files with 201 additions and 13 deletions

View File

@@ -358,10 +358,92 @@ jobs:
packages/desktop/dist-electron/Fusion-*-linux-*.tar.gz.asc
packages/desktop/dist-electron/latest-linux.yml
# ── Build Android APK artifact ───────────────────────────────────────
# FNXC:Release 2026-06-25-12:00:
# Android release assets used to be limited to the manual mobile workflow's
# short-lived CI artifacts. Tagged binary releases now build the Capacitor
# Android shell in this workflow so the public GitHub Release includes a
# stable APK and checksum beside desktop and CLI binaries.
build-android:
name: Build Android APK
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node and install dependencies
uses: ./.github/actions/setup-node-pnpm
- name: Setup Java 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"
- name: Cache Android Gradle caches
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('pnpm-lock.yaml', 'packages/mobile/capacitor.config.ts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build dashboard client
run: pnpm --filter @fusion/dashboard build
- name: Create and sync Capacitor Android project
run: |
# FNXC:Release 2026-06-25-12:00:
# The Capacitor Android platform directory is gitignored and absent in
# clean release checkouts, so initialize it from pinned package metadata
# before syncing web assets instead of silently skipping the APK leg.
if [ ! -d packages/mobile/android ]; then
pnpm --filter @fusion/mobile cap add android
fi
pnpm --filter @fusion/mobile cap sync android
- name: Build Android APK
run: |
cd packages/mobile/android
chmod +x gradlew
./gradlew assembleDebug
- name: Normalize Android APK asset
run: |
# FNXC:Release 2026-06-25-12:00:
# Ship the secret-free debug APK because this repo has no Android
# signing keystore configured; signed release APK/AAB distribution is a
# separate product task, not a binary-release plumbing prerequisite.
APK="packages/mobile/android/app/build/outputs/apk/debug/app-debug.apk"
if [ ! -f "$APK" ]; then
echo "::error::Expected Android APK missing at $APK" >&2
exit 1
fi
mkdir -p packages/mobile/dist
cp "$APK" packages/mobile/dist/fusion-android.apk
- name: Generate Android APK checksum
run: |
cd packages/mobile/dist
sha256sum fusion-android.apk > fusion-android.apk.sha256
- name: Upload Android APK artifact
uses: actions/upload-artifact@v4
with:
name: fusion-android-apk
path: |
packages/mobile/dist/fusion-android.apk
packages/mobile/dist/fusion-android.apk.sha256
# ── Create GitHub Release ─────────────────────────────────────────────
github-release:
name: Create GitHub Release
needs: [build-binaries, build-desktop-windows, build-desktop-macos, build-desktop-linux]
needs: [build-binaries, build-desktop-windows, build-desktop-macos, build-desktop-linux, build-android]
# Run as long as the workflow wasn't cancelled, even if some build legs failed,
# so a single failing matrix leg doesn't suppress publishing the ones that did
# build. Gated to tag pushes only: a workflow_dispatch run on a branch is a
@@ -394,7 +476,7 @@ jobs:
id: collect
run: |
mkdir release-files
find artifacts -type f \( -name "fn-*" -o -name "*.sha256" -o -name "*.asc" -o -name "*.exe" -o -name "*.exe.sha256" -o -name "*.blockmap" -o -name "*.dmg" -o -name "*.dmg.sha256" -o -name "*.zip" -o -name "*.zip.sha256" -o -name "*.AppImage" -o -name "*.AppImage.sha256" -o -name "*.deb" -o -name "*.deb.sha256" -o -name "*.tar.gz" -o -name "*.tar.gz.sha256" -o -name "latest*.yml" \) -exec cp {} release-files/ \;
find artifacts -type f \( -name "fn-*" -o -name "*.sha256" -o -name "*.asc" -o -name "*.exe" -o -name "*.exe.sha256" -o -name "*.blockmap" -o -name "*.dmg" -o -name "*.dmg.sha256" -o -name "*.zip" -o -name "*.zip.sha256" -o -name "*.apk" -o -name "*.AppImage" -o -name "*.AppImage.sha256" -o -name "*.deb" -o -name "*.deb.sha256" -o -name "*.tar.gz" -o -name "*.tar.gz.sha256" -o -name "latest*.yml" \) -exec cp {} release-files/ \;
ls -la release-files/
count=$(find release-files -type f | wc -l | tr -d ' ')
echo "count=$count" >> "$GITHUB_OUTPUT"

View File

@@ -345,10 +345,91 @@ jobs:
packages/desktop/dist-electron/Fusion-*-linux-*.tar.gz.asc
packages/desktop/dist-electron/latest-linux.yml
# ── Build Android APK artifact ───────────────────────────────────────
# FNXC:Release 2026-06-25-12:00:
# Keep the tag-less rehearsal workflow in parity with release.yml so APK
# generation, checksum output, and artifact collection are validated before a
# version tag tries to publish the Android asset publicly.
build-android:
name: Build Android APK
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node and install dependencies
uses: ./.github/actions/setup-node-pnpm
- name: Setup Java 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"
- name: Cache Android Gradle caches
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('pnpm-lock.yaml', 'packages/mobile/capacitor.config.ts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build dashboard client
run: pnpm --filter @fusion/dashboard build
- name: Create and sync Capacitor Android project
run: |
# FNXC:Release 2026-06-25-12:00:
# The Capacitor Android platform directory is gitignored and absent in
# clean release checkouts, so initialize it from pinned package metadata
# before syncing web assets instead of silently skipping the APK leg.
if [ ! -d packages/mobile/android ]; then
pnpm --filter @fusion/mobile cap add android
fi
pnpm --filter @fusion/mobile cap sync android
- name: Build Android APK
run: |
cd packages/mobile/android
chmod +x gradlew
./gradlew assembleDebug
- name: Normalize Android APK asset
run: |
# FNXC:Release 2026-06-25-12:00:
# Ship the secret-free debug APK because this repo has no Android
# signing keystore configured; signed release APK/AAB distribution is a
# separate product task, not a binary-release plumbing prerequisite.
APK="packages/mobile/android/app/build/outputs/apk/debug/app-debug.apk"
if [ ! -f "$APK" ]; then
echo "::error::Expected Android APK missing at $APK" >&2
exit 1
fi
mkdir -p packages/mobile/dist
cp "$APK" packages/mobile/dist/fusion-android.apk
- name: Generate Android APK checksum
run: |
cd packages/mobile/dist
sha256sum fusion-android.apk > fusion-android.apk.sha256
- name: Upload Android APK artifact
uses: actions/upload-artifact@v4
with:
name: fusion-android-apk
path: |
packages/mobile/dist/fusion-android.apk
packages/mobile/dist/fusion-android.apk.sha256
# ── Collect all artifacts ─────────────────────────────────────────────
collect:
name: Collect Artifacts
needs: [build-binaries, build-desktop-windows, build-desktop-macos, build-desktop-linux]
needs: [build-binaries, build-desktop-windows, build-desktop-macos, build-desktop-linux, build-android]
runs-on: ubuntu-latest
steps:
@@ -360,7 +441,7 @@ jobs:
- name: Combine artifacts
run: |
mkdir combined
find artifacts -type f \( -name "fn-*" -o -name "*.sha256" -o -name "*.asc" -o -name "*.exe" -o -name "*.exe.sha256" -o -name "*.blockmap" -o -name "*.dmg" -o -name "*.dmg.sha256" -o -name "*.zip" -o -name "*.zip.sha256" -o -name "*.AppImage" -o -name "*.AppImage.sha256" -o -name "*.deb" -o -name "*.deb.sha256" -o -name "*.tar.gz" -o -name "*.tar.gz.sha256" -o -name "latest*.yml" \) -exec cp {} combined/ \;
find artifacts -type f \( -name "fn-*" -o -name "*.sha256" -o -name "*.asc" -o -name "*.exe" -o -name "*.exe.sha256" -o -name "*.blockmap" -o -name "*.dmg" -o -name "*.dmg.sha256" -o -name "*.zip" -o -name "*.zip.sha256" -o -name "*.apk" -o -name "*.AppImage" -o -name "*.AppImage.sha256" -o -name "*.deb" -o -name "*.deb.sha256" -o -name "*.tar.gz" -o -name "*.tar.gz.sha256" -o -name "latest*.yml" \) -exec cp {} combined/ \;
ls -la combined/
- name: Upload combined archive