effidevFlutter · Edge de Cloudflare · Optimización de costes en la nube
Español

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

Ilustración de un pipeline de despliegue CI/CD con los iconos de App Store y Google Play

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:

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:

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

  1. Selección de entorno Mac: Debes utilizar el runner macos-latest para las compilaciones de iOS. (Ten en cuenta que las tarifas de facturación son más altas que las de los runners de Linux).
  2. Optimización de compilación de Flutter: Para iOS, el comando flutter build ipa puede manejar todo hasta el archivado. En este caso, configurar Fastlane para que solo maneje el rol de carga es ventajoso para la velocidad.
  3. 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.