Skip to content

Android Release

Android Release #504

Workflow file for this run

---
name: Android Release
permissions:
contents: read
id-token: write
on:
workflow_dispatch:
inputs:
ref_name:
description: A git commit/hash/tag (optional)
type: string
default: ""
buildEnv:
description: The Android env to be built (optional)
type: choice
default: ""
options:
- ""
- dev
- prod
upload_to_google_play:
description: Upload build to Google Play
type: choice
default: "yes"
options:
- "yes"
- "no"
release_notes:
description: Google Play release notes (optional)
type: string
default: ""
schedule:
# Runs every day at midnight PST/PDT time (8am UTC/GMT)
- cron: "0 8 * * *"
concurrency:
group:
${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: "22"
RUBY_VERSION: 3.1.4
JAVA_VERSION: "17"
SKIP_COCOAPODS: "yes"
# Google Play Console API configuration (Workload Identity Federation)
GCP_WORKLOAD_IDENTITY_PROVIDER: ${{ vars.GCP_WORKLOAD_IDENTITY_PROVIDER }}
GCP_SERVICE_ACCOUNT_EMAIL: ${{ vars.GCP_SERVICE_ACCOUNT_EMAIL }}
# Android Keystores configuration (for create_keystore_file)
ANDROID_DEV_KEYSTORE_CONTENT: ${{ secrets.ANDROID_DEV_KEYSTORE_CONTENT }}
ANDROID_PROD_KEYSTORE_CONTENT: ${{ secrets.ANDROID_PROD_KEYSTORE_CONTENT }}
# Android Keystore Passwords and Aliases (for build.gradle)
ANDROID_DEV_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_DEV_KEYSTORE_PASSWORD }}
ANDROID_DEV_KEYSTORE_ALIAS: ${{ vars.ANDROID_DEV_KEYSTORE_ALIAS }}
ANDROID_PROD_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_PROD_KEYSTORE_PASSWORD }}
ANDROID_PROD_KEYSTORE_ALIAS: ${{ vars.ANDROID_PROD_KEYSTORE_ALIAS }}
# Gradle clean configuration
FORCE_GRADLE_CLEAN: ${{ vars.FORCE_GRADLE_CLEAN }}
# Sentry configuration
SENTRY_PROPERTIES_CONTENT: ${{ secrets.SENTRY_PROPERTIES_CONTENT }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
# Amplitude Analytics
AMPLITUDE_API_KEY: ${{ secrets.AMPLITUDE_API_KEY }}
AMPLITUDE_EXPERIMENT_DEPLOYMENT_KEY:
${{ secrets.AMPLITUDE_EXPERIMENT_DEPLOYMENT_KEY }}
# Backend URLs
FREIGHTER_BACKEND_V1_PROD_URL: ${{ vars.FREIGHTER_BACKEND_V1_PROD_URL }}
FREIGHTER_BACKEND_V1_STG_URL: ${{ vars.FREIGHTER_BACKEND_V1_STG_URL }}
FREIGHTER_BACKEND_V1_DEV_URL: ${{ vars.FREIGHTER_BACKEND_V1_DEV_URL }}
FREIGHTER_BACKEND_V2_PROD_URL: ${{ vars.FREIGHTER_BACKEND_V2_PROD_URL }}
FREIGHTER_BACKEND_V2_STG_URL: ${{ vars.FREIGHTER_BACKEND_V2_STG_URL }}
FREIGHTER_BACKEND_V2_DEV_URL: ${{ vars.FREIGHTER_BACKEND_V2_DEV_URL }}
# Wallet Kit Configuration (Production)
WALLET_KIT_PROJECT_ID_PROD: ${{ secrets.WALLET_KIT_PROJECT_ID_PROD }}
WALLET_KIT_MT_NAME_PROD: ${{ vars.WALLET_KIT_MT_NAME_PROD }}
WALLET_KIT_MT_DESCRIPTION_PROD: ${{ vars.WALLET_KIT_MT_DESCRIPTION_PROD }}
WALLET_KIT_MT_URL_PROD: ${{ vars.WALLET_KIT_MT_URL_PROD }}
WALLET_KIT_MT_ICON_PROD: ${{ vars.WALLET_KIT_MT_ICON_PROD }}
WALLET_KIT_MT_REDIRECT_NATIVE_PROD:
${{ vars.WALLET_KIT_MT_REDIRECT_NATIVE_PROD }}
# Wallet Kit Configuration (Development)
WALLET_KIT_PROJECT_ID_DEV: ${{ secrets.WALLET_KIT_PROJECT_ID_DEV }}
WALLET_KIT_MT_NAME_DEV: ${{ vars.WALLET_KIT_MT_NAME_DEV }}
WALLET_KIT_MT_DESCRIPTION_DEV: ${{ vars.WALLET_KIT_MT_DESCRIPTION_DEV }}
WALLET_KIT_MT_URL_DEV: ${{ vars.WALLET_KIT_MT_URL_DEV }}
WALLET_KIT_MT_ICON_DEV: ${{ vars.WALLET_KIT_MT_ICON_DEV }}
WALLET_KIT_MT_REDIRECT_NATIVE_DEV:
${{ vars.WALLET_KIT_MT_REDIRECT_NATIVE_DEV }}
# MP Collections Addresses (comma-separated list of collection addresses)
MP_COLLECTIONS_ADDRESSES: ${{ vars.MP_COLLECTIONS_ADDRESSES }}
# E2E test vars: defined here for consistency with E2E workflow files (ios-e2e, android-e2e).
# They are shared by gh-android-env → EnvFileCreator (.env) in both release and E2E workflows.
IS_E2E_TEST: "false"
E2E_TEST_RECOVERY_PHRASE: ""
jobs:
build:
name: Build Android
runs-on: ubuntu-latest-16-cores
timeout-minutes: 45
steps:
- name: Set ref
run: |
if [[ "${{ github.event.inputs.ref_name }}" != "" ]]; then
echo "REF_NAME=${{ github.event.inputs.ref_name }}" >> $GITHUB_ENV
else
echo "REF_NAME=${{ github.ref_name }}" >> $GITHUB_ENV
fi
- name: Checkout repo
uses: actions/checkout@v5
with:
ref: ${{ env.REF_NAME }}
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ env.GCP_WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ env.GCP_SERVICE_ACCOUNT_EMAIL }}
# Fastlane's supply action reads from SUPPLY_JSON_KEY, not GOOGLE_APPLICATION_CREDENTIALS
- name: Set Fastlane Google credentials
run:
echo "SUPPLY_JSON_KEY=$GOOGLE_APPLICATION_CREDENTIALS" >> $GITHUB_ENV
- name: Make scripts executable
run: find scripts -type f -exec chmod +x {} \;
- name: Set env
run: |
# If the workflow is triggered by a scheduled event, always upload to Google Play.
if [[ "${{ github.event_name }}" == "schedule" ]]; then
echo "UPLOAD_TO_GOOGLE_PLAY=yes" >> $GITHUB_ENV
else
echo "UPLOAD_TO_GOOGLE_PLAY=${{ github.event.inputs.upload_to_google_play }}" >> $GITHUB_ENV
fi
# Translate buildEnv input to Android flavor
if [[ "${{ github.event.inputs.buildEnv }}" == "prod" ]]; then
export ANDROID_FLAVOR="prod"
else
export ANDROID_FLAVOR="dev"
fi
./scripts/gh-android-env >> $GITHUB_ENV
- name: Generate release notes
env:
INPUT_RELEASE_NOTES: ${{ github.event.inputs.release_notes || '' }}
run: scripts/generate-release-notes.sh
- name: Decode and save sentry.properties
run:
echo "$SENTRY_PROPERTIES_CONTENT" | base64 --decode >
./android/sentry.properties
- name: Print Build config
run: |
echo "UPLOAD_TO_GOOGLE_PLAY=${UPLOAD_TO_GOOGLE_PLAY}"
echo "BUILD_VERSION=${BUILD_VERSION}"
echo "REF_NAME=${REF_NAME}"
echo "APP_VERSION=${APP_VERSION}"
echo "APP_ID=${APP_ID}"
echo "APP_NAME=${APP_NAME}"
echo "ANDROID_FLAVOR=${ANDROID_FLAVOR}"
echo "FASTLANE_LANE=${FASTLANE_LANE}"
- name: Enable Corepack
run: corepack enable
- name: Set up Node
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: "yarn"
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ env.RUBY_VERSION }}
bundler-cache: true
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: zulu
cache: gradle
- name: Set up Android SDK and NDK for 16KB page size alignment
run: ./scripts/setup-android-ndk-16kb
- name: Run Yarn Install
run: yarn install --immutable
- name: Run Post Install
run: yarn postinstall
- name: Build and Distribute Application
id: fastlane
run: |
bundle exec fastlane --version
bundle exec fastlane android ${{ env.FASTLANE_LANE }}
# Dev builds: Short retention for rapid iteration
- name: Upload dev build artifacts
uses: actions/upload-artifact@v4
if: always() && env.ANDROID_FLAVOR == 'dev'
with:
name: android-build-dev-${{ env.BUILD_VERSION }}
path: android/app/build/outputs/bundle/devRelease/
retention-days: 7
# Production builds: Extended retention given less frequent uploads
- name: Upload prod build artifacts
uses: actions/upload-artifact@v4
if: always() && env.ANDROID_FLAVOR == 'prod'
with:
name: android-build-prod-${{ env.BUILD_VERSION }}
path: android/app/build/outputs/bundle/prodRelease/
retention-days: 30