From e476139352a26b1b51925fdf15acca678b6ad51f Mon Sep 17 00:00:00 2001 From: Dradebo Date: Mon, 19 Jan 2026 12:40:59 +0300 Subject: [PATCH 1/7] ci: remove hardcoded org.gradle.java.home for CI portability --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4ca049e..1ffeb37 100644 --- a/gradle.properties +++ b/gradle.properties @@ -23,4 +23,4 @@ kotlin.code.style=official android.nonTransitiveRClass=true # Use Android Studio's bundled JDK 21 instead of system Java 24 -org.gradle.java.home=/Applications/Android Studio.app/Contents/jbr/Contents/Home \ No newline at end of file +# org.gradle.java.home=/Applications/Android Studio.app/Contents/jbr/Contents/Home \ No newline at end of file From 5a4052dc08aef2f5a1ef971a5af8a09d06ce19a3 Mon Sep 17 00:00:00 2001 From: Dradebo Date: Mon, 19 Jan 2026 12:44:25 +0300 Subject: [PATCH 2/7] Update keystore secret references in release workflow --- .github/workflows/release.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7bf3cb5..7f9b3c7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,16 +23,16 @@ jobs: - uses: gradle/actions/setup-gradle@v4 - name: Decode keystore - if: ${{ secrets.ANDROID_KEYSTORE_BASE64 != '' }} + if: ${{ secrets.KEYSTORE_BASE64 != '' }} run: | - echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 --decode > "$RUNNER_TEMP/keystore.jks" + echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > "$RUNNER_TEMP/keystore.jks" - name: Build release APK and AAB env: ANDROID_KEYSTORE_PATH: ${{ runner.temp }}/keystore.jks - ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} - ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} - ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} + ANDROID_KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} + ANDROID_KEY_ALIAS: ${{ secrets.KEY_ALIAS }} + ANDROID_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} run: ./gradlew assembleRelease bundleRelease - name: Upload APK artifact From 18c4982614f39ae1fc431b81e348cd21a6120559 Mon Sep 17 00:00:00 2001 From: Dradebo Date: Mon, 19 Jan 2026 12:52:18 +0300 Subject: [PATCH 3/7] Refactor Android release workflow for better keystore management Updated the Android release workflow to improve keystore handling and build process. --- .github/workflows/release.yml | 41 +++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7f9b3c7..1492650 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,5 +1,3 @@ -name: Android Release - on: push: tags: @@ -9,6 +7,8 @@ on: permissions: contents: write +name: Android Release + jobs: build-release: runs-on: ubuntu-latest @@ -18,22 +18,45 @@ jobs: - uses: actions/setup-java@v4 with: distribution: "temurin" - java-version: "21" + java-version: "11" - uses: gradle/actions/setup-gradle@v4 - - name: Decode keystore - if: ${{ secrets.KEYSTORE_BASE64 != '' }} + - name: Decode keystore (if provided) run: | + if [ -z "${{ secrets.KEYSTORE_BASE64 }}" ]; then + echo "KEYSTORE_BASE64 not set — skipping keystore decode (build will be unsigned)" + exit 0 + fi + # create runner temp directory path and decode keystore there echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > "$RUNNER_TEMP/keystore.jks" - + echo "Keystore decoded to $RUNNER_TEMP/keystore.jks" - name: Build release APK and AAB env: - ANDROID_KEYSTORE_PATH: ${{ runner.temp }}/keystore.jks ANDROID_KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} ANDROID_KEY_ALIAS: ${{ secrets.KEY_ALIAS }} ANDROID_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - run: ./gradlew assembleRelease bundleRelease + run: | + # If keystore was decoded, RUNNER_TEMP/keystore.jks exists. Use injected signing props so no keystore info is committed. + STORE_FILE="$RUNNER_TEMP/keystore.jks" + STORE_ARG="" + if [ -f "$STORE_FILE" ]; then + STORE_ARG="-Pandroid.injected.signing.store.file=$STORE_FILE -Pandroid.injected.signing.store.password=$ANDROID_KEYSTORE_PASSWORD -Pandroid.injected.signing.key.alias=$ANDROID_KEY_ALIAS -Pandroid.injected.signing.key.password=$ANDROID_KEY_PASSWORD" + echo "Signing with keystore at $STORE_FILE" + else + echo "No keystore found at $STORE_FILE; building unsigned artifacts" + fi + # Force Gradle to use the setup-java JDK on the runner in case project has local overrides + ./gradlew assembleRelease bundleRelease -Dorg.gradle.java.home="$JAVA_HOME" $STORE_ARG + - name: Remove keystore file if present + if: always() + run: | + if [ -f "$RUNNER_TEMP/keystore.jks" ]; then + shred -u "$RUNNER_TEMP/keystore.jks" || rm -f "$RUNNER_TEMP/keystore.jks" + echo "Keystore removed" + else + echo "No keystore to remove" + fi - name: Upload APK artifact uses: actions/upload-artifact@v4 @@ -48,7 +71,7 @@ jobs: path: app/build/outputs/bundle/release/*.aab - name: Create GitHub Release - if: startsWith(github.ref, 'refs/tags/') + if: ${{ startsWith(github.ref, 'refs/tags/') }} uses: softprops/action-gh-release@v2 with: files: | From d30979e739746762d265951d066df2ceeb8077b7 Mon Sep 17 00:00:00 2001 From: Dradebo Date: Mon, 19 Jan 2026 13:16:57 +0300 Subject: [PATCH 4/7] Upgrade Java version and add debug step Updated Java version from 11 to 17 and added debugging step. --- .github/workflows/release.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1492650..0cf9665 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,13 @@ jobs: - uses: actions/setup-java@v4 with: distribution: "temurin" - java-version: "11" + java-version: "17" + + - name: Debug Java + run: | + echo "JAVA_HOME=$JAVA_HOME" + java -version + ./gradlew -version - uses: gradle/actions/setup-gradle@v4 From 02df48ab59bd7a33614093f1c140c737829c929c Mon Sep 17 00:00:00 2001 From: Dradebo Date: Mon, 19 Jan 2026 13:33:12 +0300 Subject: [PATCH 5/7] Upgrade Java version to 21 in release workflow Updated Java setup to JDK 21 and removed debug step. --- .github/workflows/release.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0cf9665..0a6877d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,16 +15,15 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 with: - distribution: "temurin" - java-version: "17" + distribution: temurin + java-version: '21' + + - name: Stop any existing Gradle daemons + run: ./gradlew --stop || true - - name: Debug Java - run: | - echo "JAVA_HOME=$JAVA_HOME" - java -version - ./gradlew -version - uses: gradle/actions/setup-gradle@v4 From 1af6bcdffbfa90fa96c130fb7ed79a7a2dea0f2c Mon Sep 17 00:00:00 2001 From: Dradebo Date: Mon, 19 Jan 2026 14:39:24 +0300 Subject: [PATCH 6/7] Upgrade JDK from 11 to 21 in release workflow --- .github/workflows/release.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 17f5817..9d55a9d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,12 +22,14 @@ jobs: with: fetch-depth: 0 - - name: Set up JDK 11 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: distribution: temurin - java-version: '11' + java-version: '21' + - name: Stop any existing Gradle daemons + run: ./gradlew --stop || true - name: Cache Gradle uses: actions/cache@v4 with: From e456cf1e0dee5f3b31555946cf86cd652e159201 Mon Sep 17 00:00:00 2001 From: Dradebo Date: Mon, 19 Jan 2026 15:07:07 +0300 Subject: [PATCH 7/7] Refactor release workflow for keystore handling and uploads Updated the release workflow to handle keystore decoding and APK/AAB uploads more securely. Added conditional checks for keystore presence and improved artifact upload steps. --- .github/workflows/release.yml | 87 +++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9d55a9d..9311780 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,51 +40,58 @@ jobs: restore-keys: | gradle-${{ runner.os }}- - - name: Decode keystore from secret + - name: Decode keystore (if provided) run: | - mkdir -p android/app - echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > android/app/keystore.jks - ls -l android/app/keystore.jks - shell: bash - - - name: Build release APK (signed via injected signing props) + if [ -z "${{ secrets.KEYSTORE_BASE64 }}" ]; then + echo "KEYSTORE_BASE64 not set — skipping keystore decode (build will be unsigned)" + exit 0 + fi + # create runner temp directory path and decode keystore there + echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > "$RUNNER_TEMP/keystore.jks" + echo "Keystore decoded to $RUNNER_TEMP/keystore.jks" + - name: Build release APK and AAB env: - KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} - KEY_ALIAS: ${{ secrets.KEY_ALIAS }} - KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} + ANDROID_KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} + ANDROID_KEY_ALIAS: ${{ secrets.KEY_ALIAS }} + ANDROID_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} run: | - # Adjust path if your module is not "app" or if project root differs (React Native android/ vs native) - ./gradlew assembleRelease \ - -Pandroid.injected.signing.store.file=android/app/keystore.jks \ - -Pandroid.injected.signing.store.password="$KEYSTORE_PASSWORD" \ - -Pandroid.injected.signing.key.alias="$KEY_ALIAS" \ - -Pandroid.injected.signing.key.password="$KEY_PASSWORD" - shell: bash - - - name: Gather release APK(s) + # If keystore was decoded, RUNNER_TEMP/keystore.jks exists. Use injected signing props so no keystore info is committed. + STORE_FILE="$RUNNER_TEMP/keystore.jks" + STORE_ARG="" + if [ -f "$STORE_FILE" ]; then + STORE_ARG="-Pandroid.injected.signing.store.file=$STORE_FILE -Pandroid.injected.signing.store.password=$ANDROID_KEYSTORE_PASSWORD -Pandroid.injected.signing.key.alias=$ANDROID_KEY_ALIAS -Pandroid.injected.signing.key.password=$ANDROID_KEY_PASSWORD" + echo "Signing with keystore at $STORE_FILE" + else + echo "No keystore found at $STORE_FILE; building unsigned artifacts" + fi + # Force Gradle to use the setup-java JDK on the runner in case project has local overrides + ./gradlew assembleRelease bundleRelease -Dorg.gradle.java.home="$JAVA_HOME" $STORE_ARG + - name: Remove keystore file if present + if: always() run: | - mkdir -p $SIGNED_APK_DIR - APK_PATH=$(find . -type f -path "*/app/build/outputs/apk/release/*release*.apk" | head -n 1) - if [ -z "$APK_PATH" ]; then - echo "ERROR: release APK not found" - exit 1 + if [ -f "$RUNNER_TEMP/keystore.jks" ]; then + shred -u "$RUNNER_TEMP/keystore.jks" || rm -f "$RUNNER_TEMP/keystore.jks" + echo "Keystore removed" + else + echo "No keystore to remove" fi - BASENAME="app-release-${GITHUB_SHA::7}.apk" - cp "$APK_PATH" "$SIGNED_APK_DIR/$BASENAME" - echo "Signed APK copied to $SIGNED_APK_DIR/$BASENAME" - shell: bash - - name: Remove keystore file securely - run: | - shred -u android/app/keystore.jks || rm -f android/app/keystore.jks - shell: bash + - name: Upload APK artifact + uses: actions/upload-artifact@v4 + with: + name: simple-data-entry-apk + path: app/build/outputs/apk/release/*.apk + + - name: Upload AAB artifact + uses: actions/upload-artifact@v4 + with: + name: simple-data-entry-aab + path: app/build/outputs/bundle/release/*.aab - - name: Create GitHub Release and upload APK(s) - uses: ncipollo/release-action@v1 + - name: Create GitHub Release + if: ${{ startsWith(github.ref, 'refs/tags/') }} + uses: softprops/action-gh-release@v2 with: - tag: ${{ env.RELEASE_TAG }} - name: Signed APK - ${{ github.sha }} - body: | - Signed APK built for commit ${{ github.sha }} on branch ${{ github.ref_name }}. - This release was generated automatically by the CI workflow. - files: ${{ env.SIGNED_APK_DIR }}/*.apk + files: | + app/build/outputs/apk/release/*.apk + app/build/outputs/bundle/release/*.aab