diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 0000000..ac0ce3d --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,187 @@ +name: Android CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + inputs: + build_type: + description: 'Build type to run' + required: true + default: 'all' + type: choice + options: + - all + - debug + - release + - signed-release + +env: + JAVA_VERSION: '17' + +jobs: + build-debug: + name: Build Debug APK + runs-on: ubuntu-latest + if: ${{ github.event_name != 'workflow_dispatch' || github.event.inputs.build_type == 'all' || github.event.inputs.build_type == 'debug' }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Create dummy keystore.properties + run: | + echo "storeFile=dummy.keystore" > keystore.properties + echo "storePassword=dummy" >> keystore.properties + echo "keyAlias=dummy" >> keystore.properties + echo "keyPassword=dummy" >> keystore.properties + + - name: Build Debug APK + run: ./gradlew assembleDebug + + - name: Upload Debug APK + uses: actions/upload-artifact@v4 + with: + name: app-debug + path: app/build/outputs/apk/debug/*.apk + retention-days: 14 + + build-release: + name: Build Release APK (Unsigned) + runs-on: ubuntu-latest + if: ${{ github.event_name != 'workflow_dispatch' || github.event.inputs.build_type == 'all' || github.event.inputs.build_type == 'release' }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Create dummy keystore.properties + run: | + echo "storeFile=dummy.keystore" > keystore.properties + echo "storePassword=dummy" >> keystore.properties + echo "keyAlias=dummy" >> keystore.properties + echo "keyPassword=dummy" >> keystore.properties + + - name: Build Unsigned Release APK + run: ./gradlew assembleRelease -x validateSigningRelease || ./gradlew assembleRelease --info + continue-on-error: true + + - name: Upload Unsigned Release APK + uses: actions/upload-artifact@v4 + if: success() + with: + name: app-release-unsigned + path: app/build/outputs/apk/release/*.apk + retention-days: 14 + + build-signed-release: + name: Build Signed Release APK + runs-on: ubuntu-latest + if: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'workflow_dispatch' && (github.event.inputs.build_type == 'all' || github.event.inputs.build_type == 'signed-release')) }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Decode Keystore + env: + KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} + run: | + echo "$KEYSTORE_BASE64" | base64 --decode > app/release.keystore + + - name: Create keystore.properties + env: + KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} + KEY_ALIAS: ${{ secrets.KEY_ALIAS }} + KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} + run: | + echo "storeFile=app/release.keystore" > keystore.properties + echo "storePassword=$KEYSTORE_PASSWORD" >> keystore.properties + echo "keyAlias=$KEY_ALIAS" >> keystore.properties + echo "keyPassword=$KEY_PASSWORD" >> keystore.properties + + - name: Build Signed Release APK + run: ./gradlew assembleRelease + + - name: Upload Signed Release APK + uses: actions/upload-artifact@v4 + with: + name: app-release-signed + path: app/build/outputs/apk/release/*.apk + retention-days: 30 + + test: + name: Run Unit Tests + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: ${{ env.JAVA_VERSION }} + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Create dummy keystore.properties + run: | + echo "storeFile=dummy.keystore" > keystore.properties + echo "storePassword=dummy" >> keystore.properties + echo "keyAlias=dummy" >> keystore.properties + echo "keyPassword=dummy" >> keystore.properties + + - name: Run Unit Tests + run: ./gradlew test + + - name: Upload Test Results + uses: actions/upload-artifact@v4 + if: always() + with: + name: test-results + path: '**/build/reports/tests/' + retention-days: 14 \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index fdac2b3..97e6dc6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,7 +4,9 @@ import java.util.Properties val keystorePropertiesFile = rootProject.file("keystore.properties") val keystoreProperties = Properties() -keystoreProperties.load(FileInputStream(keystorePropertiesFile)) +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(FileInputStream(keystorePropertiesFile)) +} plugins { alias(libs.plugins.android.application) @@ -34,11 +36,13 @@ android { } signingConfigs { - create("release") { - storeFile = rootProject.file(keystoreProperties["storeFile"] as String) - storePassword = keystoreProperties["storePassword"] as String - keyAlias = keystoreProperties["keyAlias"] as String - keyPassword = keystoreProperties["keyPassword"] as String + if (keystoreProperties.containsKey("storeFile")) { + create("release") { + storeFile = rootProject.file(keystoreProperties["storeFile"] as String) + storePassword = keystoreProperties["storePassword"] as String + keyAlias = keystoreProperties["keyAlias"] as String + keyPassword = keystoreProperties["keyPassword"] as String + } } } @@ -54,7 +58,9 @@ android { getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) - signingConfig = signingConfigs.getByName("release") + if (keystoreProperties.containsKey("storeFile")) { + signingConfig = signingConfigs.getByName("release") + } ndk { debugSymbolLevel = "SYMBOL_TABLE" }