Skip to content

Build Mobile

Build Mobile #2

Workflow file for this run

# Production mobile binaries are compiled on GitHub runners with EAS Build's local engine.
# EAS remains the credential store and, when requested, uploads the signed artifacts to the stores.
name: Build Mobile
on:
workflow_dispatch:
inputs:
submit:
description: Upload the completed builds to TestFlight and Google Play internal testing
type: boolean
required: true
default: false
concurrency:
group: build-mobile-production
cancel-in-progress: false
permissions:
contents: read
env:
MOBILE_DIR: apps/mobile
NODE_OPTIONS: --max-old-space-size=4096
jobs:
preflight:
name: Validate release request
runs-on: ${{ vars.CI_RUNNER_LINUX || 'ubuntu-latest' }}
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Check submit configuration
if: ${{ inputs.submit }}
run: |
asc_app_id="$(jq -r '.submit.production.ios.ascAppId // empty' apps/mobile/eas.json)"
if [ -z "$asc_app_id" ]; then
echo "::error::Set submit.production.ios.ascAppId in apps/mobile/eas.json before enabling submit"
exit 1
fi
build:
name: Build ${{ matrix.platform }}
needs: preflight
runs-on: ${{ matrix.os }}
timeout-minutes: 120
environment: release
strategy:
fail-fast: false
matrix:
include:
- platform: android
extension: aab
os: ${{ vars.CI_RUNNER_LINUX || 'ubuntu-latest' }}
- platform: ios
extension: ipa
os: ${{ vars.CI_RUNNER_MACOS || 'macos-26' }}
steps:
- name: Check release configuration
shell: bash
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN_MOBILE: ${{ secrets.SENTRY_DSN_MOBILE }}
POSTHOG_PROJECT_TOKEN: ${{ secrets.POSTHOG_PROJECT_TOKEN }}
POSTHOG_HOST: ${{ vars.POSTHOG_HOST }}
run: |
set -euo pipefail
missing=false
for variable in EXPO_TOKEN SENTRY_AUTH_TOKEN SENTRY_DSN_MOBILE POSTHOG_PROJECT_TOKEN POSTHOG_HOST; do
if [ -z "${!variable}" ]; then
echo "::error::Missing GitHub Actions secret or variable: ${variable}"
missing=true
fi
done
if [ "$missing" = true ]; then
exit 1
fi
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Setup EAS
uses: ./.github/actions/setup-eas
- name: Setup Java
if: ${{ matrix.platform == 'android' }}
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: 17
- name: Verify native toolchain
shell: bash
run: |
set -euo pipefail
if [ "${{ matrix.platform }}" = ios ]; then
xcodebuild -version
pod --version
fastlane --version
read -r _ xcode_version < <(xcodebuild -version)
xcode_major="${xcode_version%%.*}"
if [ "$xcode_major" -lt 26 ]; then
echo "::error::Xcode 26 or newer is required; found ${xcode_version}"
exit 1
fi
else
java -version
if [ -z "${ANDROID_HOME:-}" ] || [ ! -d "$ANDROID_HOME" ]; then
echo "::error::ANDROID_HOME does not point to an installed Android SDK"
exit 1
fi
fi
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build signed artifact locally
working-directory: ${{ env.MOBILE_DIR }}
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
EXPO_PUBLIC_SENTRY_DSN: ${{ secrets.SENTRY_DSN_MOBILE }}
EXPO_PUBLIC_POSTHOG_PROJECT_TOKEN: ${{ secrets.POSTHOG_PROJECT_TOKEN }}
EXPO_PUBLIC_POSTHOG_HOST: ${{ vars.POSTHOG_HOST }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
run: eas build --local --platform "${{ matrix.platform }}" --profile production --output "$RUNNER_TEMP/linkcode-${{ matrix.platform }}.${{ matrix.extension }}" --non-interactive
- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: mobile-${{ matrix.platform }}
path: ${{ runner.temp }}/linkcode-${{ matrix.platform }}.${{ matrix.extension }}
if-no-files-found: error
retention-days: 7
submit:
name: Submit ${{ matrix.platform }}
if: ${{ inputs.submit }}
needs: build
runs-on: ${{ vars.CI_RUNNER_LINUX || 'ubuntu-latest' }}
timeout-minutes: 30
environment: release
strategy:
fail-fast: false
matrix:
include:
- platform: android
extension: aab
- platform: ios
extension: ipa
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Setup EAS
uses: ./.github/actions/setup-eas
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Download artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: mobile-${{ matrix.platform }}
path: ${{ runner.temp }}
- name: Submit artifact
working-directory: ${{ env.MOBILE_DIR }}
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
run: eas submit --platform "${{ matrix.platform }}" --profile production --path "$RUNNER_TEMP/linkcode-${{ matrix.platform }}.${{ matrix.extension }}" --non-interactive --wait