Automatiza la compilación, firma de código y despliegue en App Store para Flutter iOS/Android con Fastlane + GitHub Actions

Desarrollar aplicaciones con Flutter es divertido, pero el proceso de desplegar la aplicación terminada en la App Store y Google Play Store a menudo causa un gran estrés a los desarrolladores. Administrar certificados, emparejar perfiles de aprovisionamiento, incrementar la versión de compilación y cargarla a la tienda requieren demasiados pasos manuales.
Esta guía cubre cómo combinar Fastlane y GitHub Actions para automatizar por completo la compilación de iOS y Android, la firma de código y el proceso de despliegue en la tienda para tu aplicación Flutter.
¿Por qué necesitamos automatización CI/CD?
Los siguientes problemas ocurren con frecuencia durante el proceso de despliegue manual:
- Error humano: Errores como asignar certificados incorrectos u olvidar incrementar la versión de compilación.
- Pérdida de tiempo: Tiempo perdido esperando mientras se archiva en una máquina local y se sube a la tienda.
- Dependencia: El proceso de despliegue depende del entorno local de un desarrollador específico (especialmente Mac) y sus cuentas.
Al usar GitHub Actions y Fastlane, puedes manejar todos estos procesos de manera segura en la nube simplemente subiendo código a la rama main o release.
1. Configuración de Fastlane (Local)
Primero, debes inicializar Fastlane en los directorios android e ios de tu proyecto Flutter, respectivamente.
Inicialización de Fastlane para Android
cd android
fastlane init
Durante el proceso de inicialización, te pedirá el nombre del paquete y la ruta a la clave secreta JSON. Necesitas la clave JSON de la cuenta de servicio (Service Account) emitida por Google Play Console.
Ejemplo de android/fastlane/Fastfile:
default_platform(:android)
platform :android do
desc "Submit a new Beta Build to Crashlytics"
lane :beta do
gradle(task: "clean bundleRelease")
upload_to_play_store(track: 'beta')
end
end
Inicialización de Fastlane para iOS
Para el despliegue en iOS, gestionar los certificados y los perfiles de aprovisionamiento es crucial. El uso de match de Fastlane te permite compartir de forma segura este proceso con los miembros del equipo a través de un repositorio Git y cargarlo fácilmente en CI/CD.
cd ios
fastlane init
fastlane match init
Ejemplo de ios/fastlane/Fastfile:
default_platform(:ios)
platform :ios do
desc "Push a new beta build to TestFlight"
lane :beta do
setup_ci
match(type: "appstore", readonly: true)
# Dado que las compilaciones de Flutter se realizan en GitHub Actions, Fastlane maneja la aplicación ya compilada.
build_app(workspace: "Runner.xcworkspace", scheme: "Runner")
upload_to_testflight
end
end
[!IMPORTANT] Para ejecutar la firma de código de iOS en un entorno de CI, se recomienda encarecidamente utilizar Fastlane Match. Es mucho más seguro y fácil de administrar que exportar certificados localmente y subirlos a CI.
2. Configuración del flujo de trabajo de GitHub Actions
Ahora, crea un archivo .github/workflows/deploy.yml en la raíz del repositorio.
Estructura básica del flujo de trabajo y variables de entorno
Debes guardar los siguientes valores en GitHub Secrets por adelantado:
MATCH_PASSWORD: Contraseña de descifrado de Fastlane MatchMATCH_GIT_BASIC_AUTHORIZATION: PAT (Personal Access Token) para acceso al repositorio de MatchAPP_STORE_CONNECT_API_KEY_KEY_ID: App Store Connect API Key IDAPP_STORE_CONNECT_API_KEY_ISSUER_ID: App Store Connect API Issuer IDAPP_STORE_CONNECT_API_KEY_KEY: App Store Connect API Key (contenido .p8)PLAY_STORE_CONFIG_JSON: Contenido JSON de la cuenta de servicio de Google Play
Script completo del flujo de trabajo
name: Deploy to App Store & Google Play
on:
push:
tags:
- 'v*' # Se ejecuta al hacer push de etiquetas como v1.0.0
jobs:
build-and-deploy:
runs-on: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '17'
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
- name: Install dependencies
run: flutter pub get
# --- Pipeline de despliegue iOS ---
- name: Setup Ruby for Fastlane
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
working-directory: ios
- name: Decode App Store Connect API Key
run: |
mkdir -p ~/.appstoreconnect/private_keys/
echo "${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }}" > ~/.appstoreconnect/private_keys/AuthKey_${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}.p8
- name: Build iOS App
run: flutter build ipa --release --export-options-plist=ios/ExportOptions.plist
- name: Deploy iOS to TestFlight
working-directory: ios
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }}
run: bundle exec fastlane beta
# --- Pipeline de despliegue Android ---
- name: Setup Ruby for Fastlane (Android)
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
working-directory: android
- name: Decode Play Store JSON
run: echo "${{ secrets.PLAY_STORE_CONFIG_JSON }}" > android/play_store_config.json
- name: Build Android App
run: flutter build appbundle --release
- name: Deploy Android to Play Store
working-directory: android
run: bundle exec fastlane beta
Consideraciones clave
- Selección de entorno Mac: Debes utilizar el runner
macos-latestpara las compilaciones de iOS. (Ten en cuenta que las tarifas de facturación son más altas que las de los runners de Linux). - Optimización de compilación de Flutter: Para iOS, el comando
flutter build ipapuede manejar todo hasta el archivado. En este caso, configurar Fastlane para que solo maneje el rol de carga es ventajoso para la velocidad. - Autenticación mediante API Key: El método tradicional de ID de Apple/contraseña es muy difícil de usar en entornos de CI debido al 2FA (autenticación de dos factores). Asegúrate de emitir y utilizar una App Store Connect API Key.
Guía de solución de problemas
| Síntoma | Causa y Solución |
|---|---|
Missing private key for ... (iOS) |
No se puede acceder al repositorio de Fastlane Match, o la MATCH_PASSWORD es incorrecta. Verifica los valores de Secret. |
Google Api Error: Invalid request - Invalid package name (Android) |
Ocurre cuando la aplicación nunca se ha registrado en Google Play Console. El primer despliegue debe subirse manualmente como un AAB. |
Code signing is required for product type 'Application' (iOS) |
La configuración de firma en el archivo del proyecto Xcode (.pbxproj) está establecida en ‘Automatic’, y el perfil de aprovisionamiento no está inyectado. Cambia la configuración del proyecto para usar Match. |
Conclusión
Construir un pipeline de CI/CD puede tomar medio día para la configuración inicial, pero una vez establecido, ahorra una tremenda cantidad de tiempo y estrés en docenas o cientos de despliegues posteriores. Especialmente en el desarrollo en equipo, transforma positivamente la cultura de desarrollo al eliminar la preocupación de ‘quién va a desplegar’.
Introduce Fastlane y GitHub Actions en tu proyecto ahora mismo y crea un entorno donde puedas concentrarte únicamente en el desarrollo.