name: Build Release on: workflow_dispatch: inputs: versionName: required: true description: This releases version name default: "1.0.0" versionCode: required: true description: This releases version code default: "1000" permissions: contents: write jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup JDK 17 uses: actions/setup-java@v3 with: distribution: "temurin" java-version: 17 - name: Setup Android SDK uses: android-actions/setup-android@v2.0.10 - name: Set Version uses: chkfung/android-version-actions@v1.1 with: gradlePath: app/build.gradle.kts versionCode: ${{github.event.inputs.versionCode}} versionName: ${{github.event.inputs.versionName}} - name: Bump Version continue-on-error: true run: | git config --local user.email "actions@github.com" git config --local user.name "GitHub Actions" git add app/build.gradle.kts if ! git diff --quiet app/build.gradle.kts; then git commit -m "chore: Bump version to ${{github.event.inputs.versionName}} (${{github.event.inputs.versionCode}})" git push else echo "No changes to version file, skipping commit" fi - name: Build Signed APK run: | # Ensure keystore secret is present if [ -z "${{ secrets.keystore }}" ]; then echo "Keystore secret missing, aborting" exit 1 fi echo "${{ secrets.keystore }}" | base64 -d > $GITHUB_WORKSPACE/signing-key.jks chmod +x ./gradlew # Retry gradle up to 3 times to mitigate transient network/cache service issues ATTEMPT=0 until [ $ATTEMPT -ge 3 ] do ./gradlew packageReleaseUniversalApk \ -Pandroid.injected.signing.store.file=$GITHUB_WORKSPACE/signing-key.jks \ -Pandroid.injected.signing.store.password=${{ secrets.keystore_password }} \ -Pandroid.injected.signing.key.alias=${{ secrets.key_alias }} \ -Pandroid.injected.signing.key.password=${{ secrets.key_password }} --no-daemon --stacktrace && break ATTEMPT=$((ATTEMPT+1)) echo "Gradle build failed, retrying ($ATTEMPT/3)..." sleep 5 done if [ $ATTEMPT -ge 3 ]; then echo "Gradle build failed after 3 attempts" exit 1 fi - name: Release run: | set -e echo "Locating built APK(s) under app/build/outputs..." # Find APK files produced by the build in common output locations apk_paths=$(find app/build/outputs -type f -name "*.apk" 2>/dev/null || true) if [ -z "$apk_paths" ]; then echo "ERROR: No APK files found under app/build/outputs" echo "Diagnostics: top-level listing of app/build/outputs:" ls -la app/build/outputs || true echo "Diagnostics: recursive listing (files only):" find app/build/outputs -type f -maxdepth 6 -print || true echo "Failing the job so you can inspect the build logs and diagnostics above." exit 1 fi # Prepare a directory to collect APKs for the release mkdir -p release-apks echo "Copying found APK(s) to release-apks/ for upload:" for apk in $apk_paths; do echo " - $apk" cp "$apk" "release-apks/$(basename "$apk")" done # Keep backward compatibility: if exactly one APK found, copy it to the root as app-release.apk apk_count=$(echo "$apk_paths" | wc -w) if [ "$apk_count" -eq 1 ]; then single_apk=$(echo "$apk_paths") cp "$single_apk" ./app-release.apk echo "Single APK copied to ./app-release.apk" else echo "Multiple APKs found ($apk_count). All copied to release-apks/" fi git config --local user.email "actions@github.com" git config --local user.name "GitHub Actions" tag="${{ github.event.inputs.versionCode }}" git tag "$tag" git push origin "$tag" # Create the GitHub release including all APK(s) we collected (debug + release) gh release create "$tag" \ --title "${{ github.event.inputs.versionName }}" \ --generate-notes \ release-apks/* env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}