Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 51 additions & 42 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -38,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
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
# org.gradle.java.home=/Applications/Android Studio.app/Contents/jbr/Contents/Home