Skip to content

Implement device registration and internal mode management (#15) #19

Implement device registration and internal mode management (#15)

Implement device registration and internal mode management (#15) #19

Workflow file for this run

name: Release APK
on:
workflow_dispatch:
inputs:
release_name:
description: Override release name (defaults to tag or ref name).
required: false
play_track:
description: Google Play release track (internal, alpha, beta, production).
required: false
default: internal
type: choice
options:
- internal
- alpha
- beta
- production
push:
branches:
- main
permissions:
contents: write
env:
BUILD_TOOLS_VERSION: 35.0.0
RELEASE_BUNDLE_PATH: app/build/outputs/bundle/release/app-release.aab
jobs:
release:
name: Build and Publish
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Verify ref on main (workflow_dispatch)
if: github.event_name == 'workflow_dispatch'
run: |
if [ "${GITHUB_REF}" != "refs/heads/main" ]; then
echo "Workflow must target the main branch. Ref: ${GITHUB_REF}" >&2
exit 1
fi
- name: Set up Java
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: Accept Android SDK licenses and install packages
run: |
# Find sdkmanager in common locations
if [ -f "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" ]; then
SDK_MANAGER="$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager"
elif [ -f "$ANDROID_HOME/cmdline-tools/bin/sdkmanager" ]; then
SDK_MANAGER="$ANDROID_HOME/cmdline-tools/bin/sdkmanager"
elif [ -f "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" ]; then
SDK_MANAGER="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager"
else
echo "Error: sdkmanager not found"
exit 1
fi
echo "Using sdkmanager at: $SDK_MANAGER"
# Accept all licenses first
yes | "$SDK_MANAGER" --licenses
# Install packages separately (as per Stack Overflow solution)
# Install platform-tools first
yes | "$SDK_MANAGER" "platform-tools"
# Install Android API 35
yes | "$SDK_MANAGER" "platforms;android-35"
# Install build-tools
yes | "$SDK_MANAGER" "build-tools;${{ env.BUILD_TOOLS_VERSION }}"
# Install Android API 36
yes | "$SDK_MANAGER" "platforms;android-36"
- name: Cache Gradle
uses: gradle/actions/setup-gradle@v4
- name: Grant execute permission for Gradle wrapper
run: chmod +x gradlew
- name: Auto-increment version code from Google Play
continue-on-error: true
env:
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
run: |
if [ -z "$GOOGLE_PLAY_SERVICE_ACCOUNT_JSON" ]; then
echo "Google Play service account not configured, skipping version code check"
exit 0
fi
# Write service account JSON to file
echo "$GOOGLE_PLAY_SERVICE_ACCOUNT_JSON" > /tmp/service_account.json
# Install Python dependencies
python3 -m pip install --quiet google-api-python-client google-auth-httplib2 google-auth-oauthlib
# Run the version code increment script
python3 scripts/increment_version_code.py
- name: Build release bundle
run: ./gradlew bundleRelease
- name: Decode keystore
run: |
if [ -z "${{ secrets.ANDROID_SIGNING_KEYSTORE_BASE64 }}" ]; then
echo "ERROR: ANDROID_SIGNING_KEYSTORE_BASE64 secret is missing. Signing secrets are required for release builds." >&2
exit 1
fi
echo "${{ secrets.ANDROID_SIGNING_KEYSTORE_BASE64 }}" | base64 --decode > release.keystore
if [ ! -f "release.keystore" ] || [ ! -s "release.keystore" ]; then
echo "ERROR: Failed to decode keystore. The secret may be invalid." >&2
exit 1
fi
- name: Sign AAB
env:
KEY_ALIAS: ${{ secrets.ANDROID_SIGNING_KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.ANDROID_SIGNING_KEY_PASSWORD }}
STORE_PASSWORD: ${{ secrets.ANDROID_SIGNING_KEYSTORE_PASSWORD }}
run: |
# Validate all signing secrets are present
if [ -z "$KEY_ALIAS" ] || [ -z "$KEY_PASSWORD" ] || [ -z "$STORE_PASSWORD" ]; then
echo "ERROR: One or more signing secrets are missing:" >&2
echo " - ANDROID_SIGNING_KEY_ALIAS: $([ -z "$KEY_ALIAS" ] && echo 'MISSING' || echo 'present')" >&2
echo " - ANDROID_SIGNING_KEY_PASSWORD: $([ -z "$KEY_PASSWORD" ] && echo 'MISSING' || echo 'present')" >&2
echo " - ANDROID_SIGNING_KEYSTORE_PASSWORD: $([ -z "$STORE_PASSWORD" ] && echo 'MISSING' || echo 'present')" >&2
exit 1
fi
if [ ! -f "release.keystore" ]; then
echo "ERROR: Keystore file not found. Decode keystore step must have failed." >&2
exit 1
fi
AAB_PATH=$(ls app/build/outputs/bundle/release/*.aab | head -n 1)
if [ -z "$AAB_PATH" ]; then
echo "ERROR: No AAB produced at app/build/outputs/bundle/release." >&2
exit 1
fi
# Sign AAB using jarsigner
jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 \
-keystore release.keystore \
-storepass "$STORE_PASSWORD" \
-keypass "$KEY_PASSWORD" \
"$AAB_PATH" \
"$KEY_ALIAS"
# Verify the signature
jarsigner -verify -verbose -certs "$AAB_PATH"
if [ $? -ne 0 ]; then
echo "ERROR: Signature verification failed." >&2
exit 1
fi
echo "✓ AAB signed and verified successfully"
- name: Set release variables
id: release_vars
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "play_track=${{ github.event.inputs.play_track || 'internal' }}" >> $GITHUB_OUTPUT
echo "release_name=${{ github.event.inputs.release_name || github.ref_name }}" >> $GITHUB_OUTPUT
else
# Automatic upload to internal track for main branch pushes
echo "play_track=internal" >> $GITHUB_OUTPUT
echo "release_name=main-${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
fi
- name: Upload release artifact
uses: actions/upload-artifact@v4
with:
name: release-bundle
path: app/build/outputs/bundle/release/*.aab
- name: Upload to Google Play Console
continue-on-error: true
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
packageName: llc.fungee.IngrediCheck
releaseFiles: app/build/outputs/bundle/release/*.aab
track: ${{ steps.release_vars.outputs.play_track }}
status: completed