name: Build Android on: workflow_call: inputs: version: description: Release version without the v prefix required: false type: string default: 1.0.0 secrets: ANDROID_KEYSTORE_BASE64: required: false ANDROID_KEYSTORE_PASSWORD: required: false ANDROID_KEY_ALIAS: required: false ANDROID_KEY_PASSWORD: required: false workflow_dispatch: inputs: version: description: Release version without the v prefix required: true default: 1.0.0 pull_request: paths: - "android/**" - "mobile/**" - "internal/**" - "go.mod" - "go.sum" - ".github/workflows/build-android.yml" permissions: contents: read jobs: build: runs-on: ubuntu-latest timeout-minutes: 45 env: VERSION: ${{ inputs.version || github.event.inputs.version || '1.0.0' }} ANDROID_VERSION_NAME: ${{ inputs.version || github.event.inputs.version || '1.0.0' }} ANDROID_VERSION_CODE: "10000" KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} steps: - uses: actions/checkout@v7 - uses: actions/setup-go@v7 with: go-version-file: go.mod cache: true - uses: actions/setup-java@v5 with: distribution: temurin java-version: "17" - name: Set up Android SDK 36 uses: android-actions/setup-android@v4 with: packages: "platform-tools platforms;android-36 build-tools;36.0.0" - uses: gradle/actions/setup-gradle@v6 - name: Verify Android SDK tools shell: bash run: | command -v sdkmanager sdkmanager --version test -d "$ANDROID_SDK_ROOT/platforms/android-36" test -d "$ANDROID_SDK_ROOT/build-tools/36.0.0" - name: Build Go mobile bridge shell: bash run: | go install golang.org/x/mobile/cmd/gomobile@latest go install golang.org/x/mobile/cmd/gobind@latest export PATH="$PATH:$(go env GOPATH)/bin" gomobile init chmod +x android/build_go_mobile.sh android/build_go_mobile.sh - name: Prepare Android signing shell: bash env: SECRET_STORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} SECRET_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} SECRET_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} run: | mkdir -p android/keystore if [[ -n "$KEYSTORE_BASE64" && -n "$SECRET_STORE_PASSWORD" && -n "$SECRET_KEY_ALIAS" && -n "$SECRET_KEY_PASSWORD" ]]; then printf '%s' "$KEYSTORE_BASE64" | base64 --decode > android/keystore/release.keystore store_password="$SECRET_STORE_PASSWORD" key_alias="$SECRET_KEY_ALIAS" key_password="$SECRET_KEY_PASSWORD" else store_password="senpai-ci-1.0.0" key_alias="senpai-ci" key_password="senpai-ci-1.0.0" keytool -genkeypair -noprompt -keystore android/keystore/release.keystore \ -storepass "$store_password" -alias "$key_alias" -keypass "$key_password" \ -keyalg RSA -keysize 3072 -validity 3650 -dname "CN=SenPaiScanner CI,O=SenPaiScanner,C=IR" echo "::warning::Android signing secrets are missing; artifacts use an ephemeral CI key and cannot upgrade a Play Store build." fi { echo "ORG_GRADLE_PROJECT_KEYSTORE_PASSWORD=$store_password" echo "ORG_GRADLE_PROJECT_KEY_ALIAS=$key_alias" echo "ORG_GRADLE_PROJECT_KEY_PASSWORD=$key_password" } >> "$GITHUB_ENV" - name: Lint, test, and build Android APKs working-directory: android shell: bash run: | chmod +x gradlew ./gradlew --no-daemon --stacktrace clean testDebugUnitTest assembleDebugAndroidTest lintRelease assembleRelease - name: Prepare Android artifacts shell: bash run: | mkdir -p release-artifacts find android/app/build/outputs/apk/release -name '*.apk' -print0 | while IFS= read -r -d '' apk; do abi="$(basename "$apk" | sed -E 's/^app-(.*)-release\.apk$/\1/')" cp "$apk" "release-artifacts/SenPaiScanner-${VERSION}-android-${abi}.apk" done - uses: actions/upload-artifact@v4 with: name: android-release path: release-artifacts/* if-no-files-found: error retention-days: 14