mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-15 00:09:39 +08:00
187 lines
7.5 KiB
YAML
187 lines
7.5 KiB
YAML
name: Build Android
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
workflow_call:
|
|
inputs:
|
|
source_tag:
|
|
description: "Existing source tag for a standalone Android release."
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
outputs:
|
|
version:
|
|
description: "Independent Android version and build date."
|
|
value: ${{ jobs.build.outputs.version }}
|
|
pull_request:
|
|
paths:
|
|
- ".github/workflows/build-android.yml"
|
|
- ".github/workflows/build.yml"
|
|
- ".github/workflows/release-mobile.yml"
|
|
- ".gitmodules"
|
|
- "LICENSE"
|
|
- "apps/android/**"
|
|
- "apps/ios/CrossDeskMobile/Resources/ThirdPartyLicenses.json"
|
|
- "apps/ios/licenses/**"
|
|
- "apps/ios/scripts/generate_third_party_licenses.py"
|
|
- "deps/submodules/minirtc"
|
|
- "libs/wire/**"
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
build:
|
|
name: Build on Android (arm64)
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 120
|
|
outputs:
|
|
version: ${{ steps.package.outputs.version }}
|
|
env:
|
|
XMAKE_VERSION: "3.1.1"
|
|
CROSSDESK_SOURCE_TAG: ${{ inputs.source_tag || '' }}
|
|
CROSSDESK_RELEASE_BUILD: ${{ inputs.source_tag && 'YES' || 'NO' }}
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v5
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ inputs.source_tag || github.ref }}
|
|
submodules: recursive
|
|
persist-credentials: false
|
|
|
|
- name: Set up Java
|
|
uses: actions/setup-java@v5
|
|
with:
|
|
distribution: temurin
|
|
java-version: "17"
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v6
|
|
with:
|
|
python-version: "3.13"
|
|
|
|
- name: Install native build tools
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y --no-install-recommends \
|
|
build-essential cmake ninja-build pkg-config autoconf automake libtool nasm
|
|
python3 -m pip install setuptools wheel
|
|
|
|
- name: Set up Android SDK
|
|
uses: android-actions/setup-android@v3
|
|
with:
|
|
packages: "platform-tools platforms;android-36 build-tools;36.0.0 ndk;28.2.13676358"
|
|
|
|
- name: Install xmake
|
|
uses: xmake-io/github-action-setup-xmake@v1
|
|
with:
|
|
xmake-version: ${{ env.XMAKE_VERSION }}
|
|
|
|
# Cache installed packages only. build_native.py checks Xmake 3.1.1 and pins
|
|
# its own package repository; never reuse another platform's build/config.
|
|
- name: Cache native dependencies
|
|
uses: actions/cache@v5
|
|
with:
|
|
path: apps/android/.native/packages
|
|
key: ${{ runner.os }}-${{ runner.arch }}-android-arm64-native-v1-${{ hashFiles('apps/android/scripts/build_native.py', 'apps/android/native/xmake.lua', 'deps/submodules/minirtc/xmake.lua', 'deps/submodules/minirtc/thirdparty/**') }}
|
|
|
|
- name: Set up Gradle
|
|
uses: gradle/actions/setup-gradle@v6
|
|
with:
|
|
cache-provider: basic
|
|
cache-read-only: ${{ github.event_name == 'pull_request' }}
|
|
|
|
- name: Verify shared license catalog
|
|
run: python3 -B apps/ios/scripts/generate_third_party_licenses.py
|
|
|
|
- name: Build APKs and run Lint
|
|
working-directory: apps/android
|
|
run: |
|
|
./gradlew --no-daemon --stacktrace \
|
|
:app:assembleDebug :app:assembleRelease :app:assembleDebugAndroidTest \
|
|
:app:lintDebug :app:lintRelease
|
|
|
|
- name: Verify APKs and native protocol
|
|
working-directory: apps/android
|
|
run: |
|
|
python3 -B test/verify_apk.py app/build/outputs/apk/debug/app-debug.apk
|
|
python3 -B test/verify_apk.py app/build/outputs/apk/release/app-release-unsigned.apk
|
|
python3 -B test/run_native.py
|
|
"${ANDROID_HOME}/build-tools/36.0.0/apksigner" verify app/build/outputs/apk/debug/app-debug.apk
|
|
"${ANDROID_HOME}/build-tools/36.0.0/apksigner" verify app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk
|
|
|
|
- name: Package APKs with the independent Android version
|
|
id: package
|
|
shell: python
|
|
run: |
|
|
import datetime
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import re
|
|
import shutil
|
|
from zoneinfo import ZoneInfo
|
|
|
|
apk_dir = Path("apps/android/app/build/outputs/apk")
|
|
metadata = json.loads((apk_dir / "release/output-metadata.json").read_text())
|
|
version = metadata["elements"][0]["versionName"]
|
|
if not re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+", version):
|
|
raise ValueError(f"Invalid Android version: {version!r}")
|
|
build_date = datetime.datetime.now(ZoneInfo("Asia/Shanghai")).strftime("%Y%m%d")
|
|
# Match the dated release tags used by the desktop and iOS jobs.
|
|
tag = os.environ.get("CROSSDESK_SOURCE_TAG")
|
|
if not tag and os.environ["GITHUB_REF_TYPE"] == "tag":
|
|
tag = os.environ["GITHUB_REF_NAME"]
|
|
if tag:
|
|
tag = tag.removeprefix("android-")
|
|
match = re.fullmatch(r"v?[0-9]+(?:\.[0-9]+){1,3}-(?:[0-9]+-)?([0-9]{8})(?:-[0-9]+)?", tag)
|
|
if match:
|
|
build_date = match[1]
|
|
datetime.datetime.strptime(build_date, "%Y%m%d")
|
|
version = f"v{version}-{build_date}"
|
|
source_tag = os.environ.get("CROSSDESK_SOURCE_TAG", "")
|
|
if source_tag.startswith("android-v") and source_tag.removeprefix("android-") != version:
|
|
raise ValueError(f"Android source tag does not match the app version: {source_tag} vs {version}")
|
|
output = Path(os.environ["RUNNER_TEMP"]) / "crossdesk-android"
|
|
for variant, source in (
|
|
("unsigned", "release/app-release-unsigned.apk"),
|
|
("debug", "debug/app-debug.apk"),
|
|
("debug", "androidTest/debug/app-debug-androidTest.apk"),
|
|
):
|
|
destination = output / variant
|
|
destination.mkdir(parents=True, exist_ok=True)
|
|
suffix = "-test" if "androidTest/" in source else ""
|
|
shutil.copyfile(apk_dir / source, destination / f"crossdesk-android-arm64-{variant}-{version}{suffix}.apk")
|
|
with open(os.environ["GITHUB_OUTPUT"], "a") as stream:
|
|
stream.write(f"version={version}\n")
|
|
with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as stream:
|
|
stream.write(f"Android {version}: arm64, API 26+, 16 KB aligned.\n\n"
|
|
"Debug APK uses an ephemeral CI debug key; it is for testing and may require uninstalling an existing build. "
|
|
"The Release APK is unsigned and needs your own signing before installation.\n\n"
|
|
"Lint, native protocol/frame tests and APK checks passed. Device tests were compiled, not executed.\n")
|
|
|
|
- name: Upload unsigned Release APK
|
|
uses: actions/upload-artifact@v6
|
|
with:
|
|
name: crossdesk-android-arm64-unsigned-${{ steps.package.outputs.version }}
|
|
path: ${{ runner.temp }}/crossdesk-android/unsigned/*.apk
|
|
if-no-files-found: error
|
|
|
|
- name: Upload Debug and device test APKs
|
|
uses: actions/upload-artifact@v6
|
|
with:
|
|
name: crossdesk-android-arm64-debug-${{ steps.package.outputs.version }}
|
|
path: ${{ runner.temp }}/crossdesk-android/debug/*.apk
|
|
if-no-files-found: error
|
|
retention-days: 14
|
|
|
|
- name: Upload Lint reports
|
|
if: ${{ !cancelled() }}
|
|
uses: actions/upload-artifact@v6
|
|
with:
|
|
name: crossdesk-android-reports
|
|
path: apps/android/app/build/reports/
|
|
if-no-files-found: ignore
|
|
retention-days: 14
|