diff --git a/.github/workflows/flutterci.yml b/.github/workflows/flutterci.yml index 1bfeb5b8..62991ff1 100644 --- a/.github/workflows/flutterci.yml +++ b/.github/workflows/flutterci.yml @@ -37,10 +37,10 @@ jobs: # - run: flutter test # Step 8: Build APK using flutter build apk - - run: flutter build apk + - run: flutter build apk --release --flavor production # Step 9: Upload the built APK as an artifact - uses: actions/upload-artifact@v4 with: name: release-apk - path: build/app/outputs/apk/release/app-release.apk + path: build/app/outputs/flutter-apk/app-production-release.apk diff --git a/.github/workflows/nightlydepolyci.yml b/.github/workflows/nightlydepolyci.yml index 60399fce..30ce4d0e 100644 --- a/.github/workflows/nightlydepolyci.yml +++ b/.github/workflows/nightlydepolyci.yml @@ -32,32 +32,48 @@ jobs: - name: Get dependencies run: flutter pub get - # Step 6: Build APK + # Step 5: Decode signing secrets for keystore and properties + - name: Decode Signing Secrets + env: + NIGHTLY_KEYSTORE_B64: ${{ secrets.NIGHTLY_KEYSTORE_B64 }} + NIGHTLY_PROPERTIES_B64: ${{ secrets.NIGHTLY_PROPERTIES_B64 }} + run: | + echo "$NIGHTLY_KEYSTORE_B64" | base64 --decode > android/nightly.jks + echo "$NIGHTLY_PROPERTIES_B64" | base64 --decode > android/key_nightly.properties + + # Step 6: Build the APK with nightly flavor and release mode - name: Build APK - run: flutter build apk --build-number=${{ github.run_number }} --release - # No 'mv' command here yet + run: flutter build apk --flavor nightly --build-number=${{ github.run_number }} --release + + # Step 7: Verify the APK is signed + - name: Verify sign + run: keytool -printcert -jarfile build/app/outputs/flutter-apk/app-nightly-release.apk - # Step 7: Push the APK to the fdroid-repo branch + # Step 8: Configure git and push the APK to fdroid-repo branch - name: Configure and push to fdroid-repo run: | git config --global user.name "github-actions[bot]" git config --global user.email "github-actions[bot]@users.noreply.github.com" git fetch origin fdroid-repo:fdroid-repo git checkout fdroid-repo - - mkdir -p repo - # Don't remove the old APK! - # Copy the new APK with a unique name - mv build/app/outputs/flutter-apk/app-release.apk repo/com.ccextractor.taskwarriorflutter_${{ github.run_number }}.apk - + mv build/app/outputs/flutter-apk/app-nightly-release.apk repo/nightly.${{ github.run_number }}.apk git add repo/ - git commit -m "chore: Add new APK from build ${{ github.run_number }}" - # You can push here, or wait until after the fdroid update - # git push origin fdroid-repo + git commit -m "chore: Add new signed APK from build ${{ github.run_number }}" - # Step 8: Setup f-droid and run update - - name: Setup F-Droid - uses: subosito/flutter-action@v1 # A common action, but you'll need to install fdroidserver + # Step 9: Prune old APKs, keeping only the 5 most recent + - name: Prune Old APKs + run: | + echo "Checking for old APKs to prune..." + if [ $(ls -1 repo/*.apk 2>/dev/null | wc -l) -gt 5 ]; then + echo "More than 5 APKs found. Deleting all but the 5 most recent..." + ls -1 repo/*.apk | sort -V | head -n -5 | xargs rm -f + else + echo "5 or fewer APKs found. No cleanup needed." + fi + + # Step 10: Setup F-Droid (install fdroidserver) and update the repo + - name: Fdroid Install + uses: subosito/flutter-action@v1 - name: Run F-Droid Update env: FDROID_CONFIG_YML_B64: ${{ secrets.FDROID_CONFIG_YML }} @@ -74,9 +90,9 @@ jobs: # Run the update command, referencing the files fdroid update -c - # Step 9: Push the updated repo files + # Step 12: Push the updated repo files with amended commit - name: Push F-Droid updates run: | git add . - git commit -m "feat: F-Droid repo update n:${{ github.run_number }}" - git push origin fdroid-repo \ No newline at end of file + git commit --amend -m "chore: Add new signed APK from build ${{ github.run_number }} and update F-Droid metadata" + git push origin fdroid-repo --force diff --git a/android/.gitignore b/android/.gitignore index 6f568019..308c19aa 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -11,3 +11,4 @@ GeneratedPluginRegistrant.java key.properties **/*.keystore **/*.jks +key_nightly.properties \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index e8ad8945..a755ea05 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -26,14 +26,18 @@ def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) - } +} + +def nightlyKeystoreProperties = new Properties() +def nightlyKeystorePropertiesFile = rootProject.file('key_nightly.properties') +if (nightlyKeystorePropertiesFile.exists()) { + nightlyKeystoreProperties.load(new FileInputStream(nightlyKeystorePropertiesFile)) +} + android { namespace "com.ccextractor.taskwarriorflutter" compileSdkVersion 35 - // compileSdkVersion flutter.compileSdkVersion - - compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -47,29 +51,49 @@ android { main.java.srcDirs += 'src/main/kotlin' } + signingConfigs { + production { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + nightly { + keyAlias nightlyKeystoreProperties['keyAlias'] + keyPassword nightlyKeystoreProperties['keyPassword'] + storeFile nightlyKeystoreProperties['storeFile'] ? file(nightlyKeystoreProperties['storeFile']) : null + storePassword nightlyKeystoreProperties['storePassword'] + } + } + defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.ccextractor.taskwarriorflutter" - //minSdkVersion flutter.minSdkVersion - minSdkVersion flutter.minSdkVersion + minSdkVersion flutter.minSdkVersion targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } - signingConfigs { - release { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPassword'] - storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null - storePassword keystoreProperties['storePassword'] - } - } - buildTypes { - release { - signingConfig signingConfigs.debug - } - } + flavorDimensions "default" + productFlavors { + production { + dimension "default" + applicationId "com.ccextractor.taskwarrior" + signingConfig keystoreProperties.isEmpty() ? signingConfigs.debug : signingConfigs.production + } + nightly { + dimension "default" + applicationId "com.ccextractor.taskwarrior.nightly" + versionNameSuffix "-nightly" + signingConfig nightlyKeystoreProperties.isEmpty() ? signingConfigs.debug : signingConfigs.nightly + } + } + + buildTypes { + release { + minifyEnabled false + shrinkResources false + } + } } flutter { @@ -77,5 +101,5 @@ flutter { } dependencies { - } +