Files
Steven EnamakelGitHubgithub-actions[bot] <github-actions[bot]@users.noreply.github.com>
0881023866 feat(orchestration): chat rework, Agent graph, global Kanban, presence (#4722)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-08 22:14:41 -07:00

270 lines
9.2 KiB
YAML

---
name: Android Build and Publish
on:
workflow_dispatch:
inputs:
build_ref:
description: Git ref/SHA to build. Leave empty to use the selected workflow ref.
required: false
type: string
default: ""
publish_to_play:
description: Sign and upload the Android App Bundle to Google Play.
required: false
type: boolean
default: false
play_track:
description: Google Play release track.
required: false
type: choice
default: internal
options: [internal, alpha, beta, production]
play_status:
description: Google Play release status.
required: false
type: choice
default: completed
options: [completed, draft, inProgress, halted]
workflow_call:
inputs:
build_ref:
description: Git ref/SHA to build.
required: true
type: string
publish_to_play:
description: Sign and upload the Android App Bundle to Google Play.
required: false
type: boolean
default: false
play_track:
description: Google Play release track.
required: false
type: string
default: internal
play_status:
description: Google Play release status.
required: false
type: string
default: completed
secrets:
ANDROID_UPLOAD_KEYSTORE_BASE64:
description: Base64-encoded Play upload keystore.
required: false
ANDROID_UPLOAD_KEY_ALIAS:
description: Alias for the Play upload key.
required: false
ANDROID_UPLOAD_KEYSTORE_PASSWORD:
description: Password for the Play upload keystore.
required: false
ANDROID_UPLOAD_KEY_PASSWORD:
description: Password for the Play upload key.
required: false
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON:
description: Google Play service account JSON.
required: false
permissions:
# `actions: read` lets scripts/ci-cancel-aware.sh poll the run status so
# cancelled builds inside container jobs stop themselves (docker exec
# swallows the runner's signals).
actions: read
contents: read
pull-requests: read
env:
# Consumed by scripts/ci-cancel-aware.sh's cancellation watchdog.
GH_TOKEN: ${{ github.token }}
concurrency:
group: ${{ github.workflow }}-${{ inputs.build_ref || github.event.pull_request.number || github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
build-android:
name: Build Android App Bundle
runs-on: ubuntu-latest
timeout-minutes: 30
outputs:
version_name: ${{ steps.version.outputs.version_name }}
version_code: ${{ steps.version.outputs.version_code }}
steps:
- name: Checkout code
uses: actions/checkout@v7
with:
ref: ${{ inputs.build_ref || github.ref }}
fetch-depth: 1
# Mobile crate uses stock Tauri (no CEF) — no submodules needed.
submodules: false
- name: Set up Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: "1.93.0"
targets: aarch64-linux-android,armv7-linux-androideabi
- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
workspaces: |
app/src-tauri-mobile -> target
packages/tauri-plugin-ptt -> target
cache-on-failure: true
- name: Set up Java
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: "17"
- name: Set up Android SDK
uses: android-actions/setup-android@v4
- name: Install Android SDK packages
shell: bash
run: |
sdkmanager \
"platform-tools" \
"platforms;android-36" \
"build-tools;35.0.0" \
"ndk;27.0.12077973"
- name: Set up pnpm
uses: pnpm/action-setup@v6
with:
version: 10.10.0
- name: Set up Node
uses: actions/setup-node@v6
with:
node-version: "24"
cache: "pnpm"
- name: Install dependencies
run: bash scripts/ci-cancel-aware.sh pnpm install --frozen-lockfile
- name: Initialize Android project
env:
NDK_HOME: ${{ env.ANDROID_HOME }}/ndk/27.0.12077973
run: bash scripts/ci-cancel-aware.sh pnpm tauri:android:init
- name: Verify version sync
run: node scripts/release/verify-version-sync.js
- name: Build Android App Bundle
env:
NDK_HOME: ${{ env.ANDROID_HOME }}/ndk/27.0.12077973
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: ${{ env.ANDROID_HOME }}/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang
CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: ${{ env.ANDROID_HOME }}/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang
run: |
bash scripts/ci-cancel-aware.sh \
pnpm --filter openhuman-app tauri:android:build --aab --target aarch64 --target armv7
- name: Resolve AAB
id: aab
shell: bash
run: |
mapfile -t bundles < <(find app/src-tauri-mobile/gen/android/app/build/outputs/bundle -type f -name "*.aab" | sort)
if [ "${#bundles[@]}" -ne 1 ]; then
printf 'Expected exactly one Android App Bundle, found %s:\n' "${#bundles[@]}"
printf ' %s\n' "${bundles[@]:-}"
exit 1
fi
mkdir -p android-release
cp "${bundles[0]}" android-release/openhuman-android-release-unsigned.aab
echo "path=android-release/openhuman-android-release-unsigned.aab" >> "$GITHUB_OUTPUT"
- name: Resolve Android version
id: version
shell: bash
run: |
props="app/src-tauri-mobile/gen/android/app/tauri.properties"
version_name="$(grep '^tauri.android.versionName=' "$props" | cut -d= -f2-)"
version_code="$(grep '^tauri.android.versionCode=' "$props" | cut -d= -f2-)"
if [ -z "$version_name" ] || [ -z "$version_code" ]; then
echo "Failed to read Android version from $props"
exit 1
fi
echo "version_name=$version_name" >> "$GITHUB_OUTPUT"
echo "version_code=$version_code" >> "$GITHUB_OUTPUT"
echo "Android versionName=$version_name versionCode=$version_code"
- name: Upload unsigned AAB artifact
uses: actions/upload-artifact@v7
with:
name: openhuman-android-aab-unsigned
path: ${{ steps.aab.outputs.path }}
if-no-files-found: error
retention-days: 14
publish-play:
name: Publish Google Play
if: ${{ inputs.publish_to_play }}
runs-on: ubuntu-latest
timeout-minutes: 15
needs: [build-android]
environment: Production
steps:
- name: Download unsigned AAB
uses: actions/download-artifact@v8
with:
name: openhuman-android-aab-unsigned
path: android-release
- name: Set up Java
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: "17"
- name: Sign Android App Bundle
id: sign
shell: bash
env:
ANDROID_UPLOAD_KEYSTORE_BASE64: ${{ secrets.ANDROID_UPLOAD_KEYSTORE_BASE64 }}
ANDROID_UPLOAD_KEY_ALIAS: ${{ secrets.ANDROID_UPLOAD_KEY_ALIAS }}
ANDROID_UPLOAD_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_UPLOAD_KEYSTORE_PASSWORD }}
ANDROID_UPLOAD_KEY_PASSWORD: ${{ secrets.ANDROID_UPLOAD_KEY_PASSWORD }}
run: |
required=(
ANDROID_UPLOAD_KEYSTORE_BASE64
ANDROID_UPLOAD_KEY_ALIAS
ANDROID_UPLOAD_KEYSTORE_PASSWORD
ANDROID_UPLOAD_KEY_PASSWORD
)
for name in "${required[@]}"; do
if [ -z "${!name}" ]; then
echo "::error::$name is required to sign the Android release."
exit 1
fi
done
mkdir -p signing signed
printf '%s' "$ANDROID_UPLOAD_KEYSTORE_BASE64" | base64 --decode > signing/upload-keystore.jks
jarsigner \
-keystore signing/upload-keystore.jks \
-storepass "$ANDROID_UPLOAD_KEYSTORE_PASSWORD" \
-keypass "$ANDROID_UPLOAD_KEY_PASSWORD" \
-signedjar signed/openhuman-android-release.aab \
android-release/openhuman-android-release-unsigned.aab \
"$ANDROID_UPLOAD_KEY_ALIAS"
jarsigner -verify -certs -verbose signed/openhuman-android-release.aab >/dev/null
echo "path=signed/openhuman-android-release.aab" >> "$GITHUB_OUTPUT"
- name: Upload signed AAB artifact
uses: actions/upload-artifact@v7
with:
name: openhuman-android-aab-signed
path: ${{ steps.sign.outputs.path }}
if-no-files-found: error
retention-days: 30
- name: Upload to Google Play
uses: r0adkll/upload-google-play@v1.1.5
with:
serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
packageName: com.openhuman.app
releaseFiles: ${{ steps.sign.outputs.path }}
track: ${{ inputs.play_track }}
status: ${{ inputs.play_status }}