diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml new file mode 100644 index 0000000..e7dc7d0 --- /dev/null +++ b/.github/workflows/android-release.yml @@ -0,0 +1,75 @@ +name: Release + +on: + push: + tags: + - 'v*.*.*' + +permissions: + contents: write + +jobs: + build: + name: Build and publish release APK + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '17' + cache: gradle + + - name: Set up Android SDK + uses: android-actions/setup-android@v3 + + - name: Make Gradle wrapper executable + run: chmod +x ./gradlew + + - name: Decode release keystore + env: + RELEASE_KEYSTORE_BASE64: ${{ secrets.RELEASE_KEYSTORE_BASE64 }} + run: | + set -euo pipefail + if [ -n "${RELEASE_KEYSTORE_BASE64:-}" ]; then + echo "$RELEASE_KEYSTORE_BASE64" | base64 -d > "$RUNNER_TEMP/release.keystore" + echo "RELEASE_KEYSTORE_PATH=$RUNNER_TEMP/release.keystore" >> "$GITHUB_ENV" + else + echo "::warning::RELEASE_KEYSTORE_BASE64 secret not set; release APK will be debug-signed." + fi + + - name: Build release APK + env: + RELEASE_KEYSTORE_PASSWORD: ${{ secrets.RELEASE_KEYSTORE_PASSWORD }} + RELEASE_KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }} + RELEASE_KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }} + run: ./gradlew :app:assembleRelease --stacktrace + + - name: Prepare release APK + run: | + set -euo pipefail + mkdir -p dist + APK_PATH="$(find app/build/outputs/apk/release -name '*.apk' | head -n 1)" + cp "$APK_PATH" "dist/Sploot-${GITHUB_REF_NAME}.apk" + + - name: Upload release APK artifact + uses: actions/upload-artifact@v4 + with: + name: Sploot-release-apk + path: dist/Sploot-${{ github.ref_name }}.apk + if-no-files-found: error + + - name: Create GitHub release + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + gh release create "${GITHUB_REF_NAME}" "dist/Sploot-${GITHUB_REF_NAME}.apk" \ + --title "Sploot ${GITHUB_REF_NAME}" \ + --generate-notes diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f04e639..7f834b6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -19,6 +19,18 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } + val releaseKeystorePath = System.getenv("RELEASE_KEYSTORE_PATH") + signingConfigs { + if (releaseKeystorePath != null) { + create("release") { + storeFile = file(releaseKeystorePath) + storePassword = System.getenv("RELEASE_KEYSTORE_PASSWORD") + keyAlias = System.getenv("RELEASE_KEY_ALIAS") + keyPassword = System.getenv("RELEASE_KEY_PASSWORD") + } + } + } + buildTypes { release { isMinifyEnabled = true @@ -26,6 +38,10 @@ android { getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) + // Falls back to debug signing for local builds where the release + // keystore env vars aren't set, e.g. outside of the release CI job. + signingConfig = signingConfigs.findByName("release") + ?: signingConfigs.getByName("debug") } }