Skip to content

Add Android release workflow #1

Add Android release workflow

Add Android release workflow #1

Workflow file for this run

name: Android Release
on:
push:
tags:
- "android-v*"
permissions:
contents: write
concurrency:
group: android-release-${{ github.ref }}
cancel-in-progress: false
jobs:
android-apk:
name: Build and publish signed APK
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- uses: android-actions/setup-android@v4
with:
accept-android-sdk-licenses: true
packages: ""
- name: Install Android SDK packages
shell: bash
run: |
set -euo pipefail
sdkmanager "platforms;android-35" "build-tools;35.0.0" "platform-tools"
- name: Read Android version
id: version
shell: bash
run: |
set -euo pipefail
version_name="$(grep -E 'versionName[[:space:]]*=' android/app/build.gradle.kts | sed -E 's/.*"([^"]+)".*/\1/' | head -n 1)"
version_code="$(grep -E 'versionCode[[:space:]]*=' android/app/build.gradle.kts | sed -E 's/.*=[[:space:]]*([0-9]+).*/\1/' | head -n 1)"
test -n "$version_name"
test -n "$version_code"
expected_tag="android-v$version_name"
if [ "$GITHUB_REF_NAME" != "$expected_tag" ]; then
echo "::error::Tag $GITHUB_REF_NAME does not match Android versionName $version_name. Expected $expected_tag."
exit 1
fi
echo "version_name=$version_name" >> "$GITHUB_OUTPUT"
echo "version_code=$version_code" >> "$GITHUB_OUTPUT"
- name: Decode release keystore
shell: bash
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: |
set -euo pipefail
for name in ANDROID_KEYSTORE_BASE64 ANDROID_KEYSTORE_PASSWORD ANDROID_KEY_ALIAS ANDROID_KEY_PASSWORD; do
if [ -z "${!name:-}" ]; then
echo "::error::$name secret is required for Android release signing."
exit 1
fi
done
keystore_file="$RUNNER_TEMP/mebius-code-android-release.jks"
printf '%s' "$ANDROID_KEYSTORE_BASE64" | base64 --decode > "$keystore_file"
echo "ANDROID_KEYSTORE_FILE=$keystore_file" >> "$GITHUB_ENV"
- name: Build signed release APK
shell: bash
env:
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
run: |
set -euo pipefail
chmod +x android/gradlew
android/gradlew -p android :app:testDebugUnitTest :app:assembleRelease
- name: Stage release assets
id: stage
shell: bash
run: |
set -euo pipefail
mkdir -p release
apk="$(find android/app/build/outputs/apk/release -maxdepth 1 -name '*.apk' ! -name '*unsigned*' | head -n 1)"
if [ -z "$apk" ]; then
echo "::error::Signed release APK was not found."
find android/app/build/outputs/apk/release -maxdepth 1 -type f -print || true
exit 1
fi
apk_name="Mebius-Code-android-${{ steps.version.outputs.version_name }}.apk"
cp "$apk" "release/$apk_name"
sdk_root="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"
test -n "$sdk_root"
apksigner="$(find "$sdk_root/build-tools" -name apksigner -type f | sort -V | tail -n 1)"
test -n "$apksigner"
"$apksigner" verify --verbose "release/$apk_name"
(cd release && sha256sum "$apk_name" > SHA256SUMS)
cat > "$RUNNER_TEMP/android-release-notes.md" <<EOF
Signed Android APK for Mebius Code.
- Version: ${{ steps.version.outputs.version_name }} (${{ steps.version.outputs.version_code }})
- Default API: http://182.92.150.169/api
- The API address can be changed from the login and settings screens.
- This is a GitHub Release sideload APK; app store submission is not part of this release path.
Download the APK asset and use SHA256SUMS to verify it before installing when possible.
EOF
echo "apk_name=$apk_name" >> "$GITHUB_OUTPUT"
echo "release_name=Mebius Code Android ${{ steps.version.outputs.version_name }}" >> "$GITHUB_OUTPUT"
- name: Publish GitHub Release
uses: softprops/action-gh-release@v2
with:
name: ${{ steps.stage.outputs.release_name }}
body_path: ${{ runner.temp }}/android-release-notes.md
files: |
release/${{ steps.stage.outputs.apk_name }}
release/SHA256SUMS
fail_on_unmatched_files: true