Saltar al contenido principal
CI/CD

Automatic Capacitor IOS build with GitHub actions with certificate

How to set up a CI/CD pipeline for your IOS Ionic app using fastlane and GitHub Actions in 5 mins (2024)

Créditos del artículo

Martin Donadieu

Escritor

Valeria

Revisor

Jordan

Editor

Automatic Capacitor IOS build with GitHub actions with certificate

Configurando CI/CD para aplicaciones Capacitor puede ser complejo y tiempo consumidor. Aquí está lo que debes saber:

Ahora recomendamos utilizar Capgo Build con el Capgo CLI para construcciones nativas Capacitor. Esta guía de Fastlane se mantiene para equipos que mantienen existentes pipelines de acciones GitHub, pero nuevos builds de iOS deben utilizar el Capgo CLI para que no tengas que mantener Fastlane, ejecutores de Xcode, certificados y scripts de carga.

Capgo Build para CI/CD por Capgo

Saltate la mantenimiento de Fastlane, ejecutor de Xcode, certificado, perfil de provisión y script de carga. Capgo Build ejecuta construcciones nativas de iOS firmadas desde tu pipeline de CI/CD existente:

  • Funciona con tu pipeline: Disparar Capgo Build desde GitHub Actions, GitLab CI, Jenkins o scripts locales después de tu build web y npx cap sync.
  • Configuración de firma desde secretos de CI: Mantenga las claves de App Store Connect, certificados, perfiles de configuración, contraseñas y IDs de equipo en sus propios secretos de CI.
  • No mantenimiento del ejecutor nativo: Capgo Build proporciona entornos de compilación Apple mantenidos, por lo que no tiene que gestionar ejecutores macOS, imágenes de Xcode o rutas de Fastlane.
  • Artículos y presentación: Descargue artículos firmados para QA o presente builds de lanzamiento a través del Capgo CLI.

Precio

  • Capgo plans start at $12/month
  • Los planes de __CAPGO_KEEP_0__ comienzan en $12/mes
  • Incluye actualizaciones OTA y aproximadamente 15 compilaciones nativas por mes

Set up Capgo Build in CI/CD

contexto: Página/área: Capgo Builder / producto de compilación nativa en la nube. Papel: Oración de copia de sitio web. Visto en: página native-build.astro. Clave de mensaje `native_build_builder_minutos_de_compilación` (Minutos de compilación del constructor de compilación nativa).

¿Qué debes hacer:

Entrega continua para iOS utilizando Fastlane y GitHub Acciones y certificado

Requisitos previos

Antes de continuar con el tutorial:

  • Asegúrate de tener instalado Fastlane en tu máquina de desarrollo. Asegúrate de ser parte del programa de membresía de desarrolladores de iOS.
  • Información importante sobre el precio

Precio de la acción __CAPGO_KEEP_0__

https://GitHub.com/features/actions

https://github.com/features/actions

Continuous Delivery for iOS using Fastlane and __CAPGO_KEEP_0__ Actions and certificategratis hasta el límite, dependiendo de la máquina elegida.
Vamos a utilizar una máquina macOS máquina macOS, puedes ver en la captura de pantalla su precio y límites (precios a la creación de este tutorial, pueden cambiar en el futuro)

Una vez advertido de los requisitos y precios, sigamos.

Nota: En el post supongo que tienes la aplicación creada en App Store Connect. La información importante se copiará con Fastlane!

¿Qué aprenderás en el tutorial?

Pasos a seguir en el post

  1. Usando App Store Connect API con Fastlane
    • Requisitos:
      • Crear una clave de App Store Connect API
      • Usando una clave de App Store Connect API
  2. Copiar archivos de Fastlane
  3. Configurar acciones de GitHub

1. Usando App Store Connect API con Fastlane

Desde febrero de 2021, se requiere autenticación en dos factores o verificación en dos pasos para todos los usuarios para iniciar sesión en App Store Connect. Esta capa adicional de seguridad para su ID de Apple ayuda a asegurarse de que solo usted puede acceder a su cuenta.
Desde Soporte de Apple

Requisitos

Para que Fastlane pueda utilizar App Store Connect API para subir su aplicación, necesita proporcionar los siguientes tres cosas:

  1. ID del emisor
  2. ID de clave
  3. Archivo de clave o contenido de clave

Obtener una clave de API de App Store Connect

Para generar claves, debe tener permiso de Administrador en App Store Connect. Si no tiene ese permiso, puede dirigir a la persona relevante a este artículo.

  1. Iniciar sesión en Conectar a App Store Connect.

  2. Seleccionar Usuarios y acceso a App Store Connect.

Acceso de usuario a App Store Connect

3 — Seleccionar la pestaña de Integración.

Integración de App Store Connect de API

  1. Haga clic en Generar clave de API o en el botón de agregar (+).

App Store Connect API llaves crean

  1. Ingresa un nombre para la llave. El nombre es solo para tu referencia y no forma parte de la llave en sí.

App Store Connect API llaves crean nombre

6 — Debajo de Acceso, selecciona el rol para la llave. Los roles que se aplican a las llaves son los mismos roles que se aplican a los usuarios en tu equipo. Consulta permisos de rol. Recomendamos seleccionar administrador de aplicaciones.

  1. Haz clic en Generar.

El acceso de una llave API no puede limitarse a aplicaciones específicas.

El nombre, el ID de la llave, un enlace de descarga y otra información aparecen en la página.

App Store Connect descargar llaves

Puedes obtener toda la información necesaria aquí.
<1> Identificador de la cuestión. (APPLE_ISSUER_ID secret)
<2> Identificador de la clave. (APPLE_KEY_ID secret)
<3> Haga clic en “Descargar la clave API” para descargar su clave API privada. El enlace de descarga aparece solo si la clave privada no se ha descargado aún. Apple no almacena una copia de la clave privada. Por lo tanto, solo puede descargarla una vez.

🔴 Almacene su clave privada en un lugar seguro. Nunca debe compartir sus claves, almacenar claves en un code repositorio o incluir claves en el lado del cliente code.

Usando una clave API de App Store Connect

El archivo de la clave API (archivo p8 que descargó), el identificador de la clave y el identificador del emisor son necesarios para crear el token JWT de autorización. Hay varias formas de pasar esta información a Fastlane. Eligió usar la acción nueva de Fastlane app_store_connect_api_keyUsted puede aprender otras formas en documentación de FastlaneLe muestro este método porque creo que es la forma más fácil de trabajar con la mayoría de los CI allí, donde puede establecer variables de entorno.

Por favor, convierta el archivo p8 que descargó a Base64 y almacénelo como un secreto (APPLE_KEY_CONTENT).

base64 -i APPLE_KEY_CONTENT.p8 | pbcopy

Now podemos administrar App Store Connect con Fastlane utilizando la clave API, ¡genial!

2. Certificados

Abra XCode y vaya a Ajustes > Cuentas > ID de Apple > Equipos y seleccione su equipo.

Code identidades de firma

Haz clic en Gestiona certificados.

Si aún no has creado un certificado, puedes crear un nuevo certificado.

Haz clic en + y selecciona Distribución de Apple

Distribución de Apple

Luego debes ir a la caja de llaves para descargar el certificado como un .p12 archivo.

Para hacerlo, debes ir a la caja de llaves, cambiar a la caja de llaves de inicio de sesión y luego la pestaña de inicio de sesión caja de llaves Mis Certificados.

Mis Certificados

Luego, puedes seleccionar el certificado que deseas descargar. (Busca por la fecha del certificado)

Y luego haz clic derecho en la clave privada del certificado y selecciona Exportar.

Elige el formato de archivo Intercambio de Información Personal (.p12).

Eso descargará el certificado como un .p12 archivo.

Por favor, abre el archivo en una terminal y utiliza el siguiente comando para convertirlo a Base64:

base64 -i BUILD_CERTIFICATE.p12 | pbcopy

Eso se convertirá en tu BUILD_CERTIFICATE_BASE64 clave secreta. También, cuando se te pregunte, por favor proporciona la contraseña del certificado. Esta contraseña será tu P12_PASSWORD secret.

3. Perfiles de configuración

Abrir Desarrollador de Apple y seleccionar el equipo correcto.

Luego crea un nuevo perfil, haciendo clic en +

Crear un nuevo perfil

Y seleccionar App Store Connect.

Seleccionar App Store Connect

Luego debes seleccionar la aplicación correcta, ten cuidado, ya que no puedes utilizar wildcards de lo contrario el proceso de firma fallará.

Seleccionar la aplicación correcta

Seleccione el certificado correcto que creó antes (busque la fecha de vencimiento, debe ser el mismo día y mes que hoy) y haga clic en Continuar.

Seleccione el certificado correcto

Finalmente, ingrese el nombre del perfil y haga clic en Generar.

El nombre se utilizará para identificar el perfil en Fastlane, bajo el valor de APPLE_PROFILE_NAME.

Generar el perfil

Puede descargar el perfil como un .mobileprovision archivo.

Descargar el perfil

Por favor, convierta el perfil a Base64 y almacénelo como un secreto (BUILD_PROVISION_PROFILE_BASE64).

base64 -i BUILD_PROVISION_PROFILE.mobileprovision | pbcopy

4. Copie los archivos de Fastlane

Fastlane es una biblioteca de Ruby creada para automatizar tareas comunes de desarrollo móvil. Utilizando Fastlane, puedes configurar

Crea la carpeta Fastlane en la raíz de tu proyecto Capacitor/Ionic y agrega el archivo Fastfile allí:

  • Carpeta: <project-root>/fastlane/
  • Archivo: <project-root>/fastlane/Fastfile

Este nivel es el mismo que package.json, capacitor.config.*, y el ios/ carpeta. No lo crees dentro de ios/App/.

platform :ios do
  desc 'Export ipa and submit to TestFlight'
  lane :beta do
    keychain_info = { keychain_name: "ios-build-#{Time.now.to_i}.keychain", keychain_password: SecureRandom.uuid }
    
    begin
      setup_signing(keychain_info)
      bump_build_number
      build_app_with_signing(keychain_info)
      submit_to_testflight
    ensure
      cleanup_keychain(keychain_info)
    end
  end

  private_lane :setup_signing do |options|
    create_keychain(
      name: options[:keychain_name],
      password: options[:keychain_password],
      unlock: true,
      timeout: 0,
      lock_when_sleeps: false, 
      add_to_search_list: true
    )
    import_cert(options)
    install_profile
    update_project_settings
  end

  lane :bump_build_number do
		file = File.read('../package.json')
		data_hash = JSON.parse(file)
		api_key = app_store_connect_api_key(
      key_id: ENV['APPLE_KEY_ID'],
      issuer_id: ENV['APPLE_ISSUER_ID'],
      key_content: ENV['APPLE_KEY_CONTENT'],
      is_key_content_base64: true,
      duration: 1200,
      in_house: false
    )
		build_num = app_store_build_number(
      api_key: api_key,
			app_identifier: ENV['BUNDLE_IDENTIFIER'],
			live: false
    )
		build_num = build_num + 1
		UI.message("Bumped build number to #{build_num}")
		increment_build_number(
			build_number: build_num,
			xcodeproj: "./ios/App/App.xcodeproj",
			skip_info_plist: true
		)
	end

  private_lane :import_cert do |options|
    cert_path = "#{Dir.tmpdir}/build_certificate.p12"
    File.write(cert_path, Base64.decode64(ENV['BUILD_CERTIFICATE_BASE64']))
    import_certificate(
      certificate_path: cert_path,
      certificate_password: ENV['P12_PASSWORD'] || "",
      keychain_name: options[:keychain_name],
      keychain_password: options[:keychain_password],
      log_output: true
    )
    File.delete(cert_path)
  end  
  
  private_lane :cleanup_keychain do |options|
    delete_keychain(
      name: options[:keychain_name]
    )
  end  

  private_lane :install_profile do
    profile_path = "#{Dir.tmpdir}/build_pp.mobileprovision"
    File.write(profile_path, Base64.decode64(ENV['BUILD_PROVISION_PROFILE_BASE64']))
    UI.user_error!("Failed to create provisioning profile at #{profile_path}") unless File.exist?(profile_path)
    ENV['PROVISIONING_PROFILE_PATH'] = profile_path
    install_provisioning_profile(path: profile_path)
    File.delete(profile_path)
  end

  private_lane :update_project_settings do
    update_code_signing_settings(
      use_automatic_signing: false,
      path: "./ios/App/App.xcodeproj",
      code_sign_identity: "iPhone Distribution",
      profile_name: ENV['APPLE_PROFILE_NAME'],
      bundle_identifier: ENV['BUNDLE_IDENTIFIER'],
      team_id: ENV['APP_STORE_CONNECT_TEAM_ID']
    )
    update_project_team(
      path: "./ios/App/App.xcodeproj",
      teamid: ENV['APP_STORE_CONNECT_TEAM_ID']
    )
  end

  private_lane :build_app_with_signing do |options|
    unlock_keychain(
      path: options[:keychain_name],
      password: options[:keychain_password],
      set_default: false
    )
    build_app(
      workspace: "./ios/App/App.xcworkspace",
      scheme: "App",
      configuration: "Release",
      export_method: "app-store",
      output_name: "App.ipa",
      export_options: {
        provisioningProfiles: {
          ENV['BUNDLE_IDENTIFIER'] => ENV['APPLE_PROFILE_NAME']
        }
      },
      xcargs: "-verbose",
      buildlog_path: "./build_logs",
      export_xcargs: "-allowProvisioningUpdates",
    )
  end   

  private_lane :submit_to_testflight do
    api_key = app_store_connect_api_key(
      key_id: ENV['APPLE_KEY_ID'],
      issuer_id: ENV['APPLE_ISSUER_ID'],
      key_content: ENV['APPLE_KEY_CONTENT'],
      is_key_content_base64: true,
      duration: 1200,
      in_house: false
    )
    pilot(
      api_key: api_key,
      skip_waiting_for_build_processing: true,
      skip_submission: true,
      distribute_external: false,
      notify_external_testers: false,
      ipa: "./App.ipa"
    )
  end
end

5. Configuración de secretos

GitHub Actions uses the repository secrets you configure in the next step. You only need a local .env Para pruebas locales, crea

al lado de <project-root>/fastlane/.env __CAPGO_KEEP_0__ Fastfile. No cometas este archivo. Agrega fastlane/.env a tu .gitignore primero (o verifica que ya está ignorado). Aquí tienes un ejemplo:

APP_STORE_CONNECT_TEAM_ID=UVTJ336J2D
BUNDLE_IDENTIFIER=ee.forgr.testfastlane
# See previous section for these secrets
BUILD_CERTIFICATE_BASE64=
BUILD_PROVISION_PROFILE_BASE64=
APPLE_KEY_ID=
APPLE_ISSUER_ID=
APPLE_KEY_CONTENT=
P12_PASSWORD=
APPLE_PROFILE_NAME=

Obteniendo el APP_STORE_CONNECT_TEAM_ID

Ve a Centro de Desarrolladores y desplázate hacia abajo hasta la Membership details sección. La Team ID es el valor que debes establecer en el APP_STORE_CONNECT_TEAM_ID secret.

app-store-connect-team-id

Obteniendo el BUNDLE_IDENTIFIER

  1. Abra Xcode
  2. Doble haga clic en el App en el navegador de proyectos
  3. Luego haga clic en la pestaña Signing and Capabilities
  4. Copie el valor del Bundle identifier. Este es el valor que necesita establecer en el BUNDLE_IDENTIFIER secret.
identificador-de-bundle-xcode

6. Procesamiento de compilación

En GitHub Actions, se le facturan según los minutos que ha utilizado para ejecutar su flujo de trabajo de CI/CD. Desde mi experiencia, tarda unos 10-15 minutos antes de que se pueda procesar una compilación en App Store Connect.

For proyectos privados, el costo estimado por construcción puede llegar a $0.08/min x 15 min = $1.2, o más, dependiendo de la configuración y dependencias de tu proyecto.

Si estás preocupado por los costos para proyectos privados, puedes establecer skip_waiting_for_build_processing para true. Esto ahorrará minutos de construcción ya que no se espera a que App Store Connect termine de procesar la construcción.

Sin embargo, hay un tradeoff - tendrás que actualizar manualmente la información de cumplimiento de tu aplicación en App Store Connect antes de poder distribuir la construcción a los usuarios.

This optimization is mainly useful for private projects where build minutes cost money. For public/free projects, the build minutes are free so there’s no need to enable this setting. See GitHub’s página de precios de para obtener más detalles.

7. Setup GitHub Actions

Configure GitHub secrets

Por favor, copie los secretos del archivo .env y péguelos en los secretos del repositorio GitHub.

Vaya a Ajustes &gt; Secretos y variables &gt; Acciones &gt; Nuevo secreto de repositorio

github-secrets

2. BUILD_CERTIFICATE_BASE64 - Certificado en formato Base64.

3. BUILD_PROVISION_PROFILE_BASE64 - Perfil de configuración Base64 codificado.

4. BUNDLE_IDENTIFIER - identificador de paquete de tu aplicación.

5. APPLE_KEY_ID — Clave de App Store Connect API 🔺 Identificador de clave.

6. APPLE_ISSUER_ID — Clave de App Store Connect API 🔺 Identificador de emisor.

7. APPLE_KEY_CONTENT — Clave de App Store Connect API 🔺 Contenido de la clave. .p8, verificarlo

8. Configura el archivo de flujo de trabajo GitHub

Crear un directorio de flujo de trabajo GitHub

cd .github/workflows

Dentro del workflow folder, crear un archivo llamado build-upload-ios.ymly agregar lo siguiente.

name: Build source code on ios

on:
  push:
    tags:
      - '*'

jobs:
  build_ios:
    runs-on: macOS-latest
    steps:
      - uses: actions/checkout@v6
      - name: Set Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: npm
      - name: Install dependencies
        id: install_code
        run: npm ci
      - name: Build
        id: build_code
        run: npm run build
      - uses: actions/cache@v5
        with:
          path: ios/App/Pods
          key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-pods-
      - name: Sync
        id: sync_code
        run: npx cap sync
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.0'
          bundler-cache: true
      - uses: maierj/fastlane-action@v3.1.0
        env:
          APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
          BUNDLE_IDENTIFIER: ${{ secrets.BUNDLE_IDENTIFIER }}
          BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
          BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
          APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
          APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
          APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
          P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
          APPLE_PROFILE_NAME: ${{ secrets.APPLE_PROFILE_NAME }}
        with:
          lane: ios beta
      - name: Upload release bundle
        uses: actions/upload-artifact@v6
        with:
          name: ios-release
          path: ./App.ipa
          retention-days: 10

Este flujo de trabajo debe ser desencadenado después de cada GitHub etiquetasi necesita automatizar etiquetas, consulte Compilación y lanzamiento automático con GitHub acciones primero.

Luego, este flujo de trabajo extraerá sus dependencias NodeJS, las instalará y compilará su aplicación de JavaScript.

Cada vez que envíe un nuevo commit, se construirá una versión de prueba en TestFlight.

Su aplicación no necesita utilizar Ionic, solo es obligatorio el Capacitor base, puede tener módulos de Cordova antiguos, pero se recomienda utilizar el Capacitor plugin de JavaScript.

8. Desencadene el flujo de trabajo

Crear un Commit

Hacer un commitverás el flujo de trabajo activo en el repositorio.

Activar el flujo de trabajo

Pushear los nuevos commits a la rama main o development ¿Qué sucede si no utilizo Capacitor?

¿Qué sucede si no utilizo Appflow?

¿Qué sucede si no utilizo Capwesome?

¿Qué sucede si no utilizo Appflow?

Después de unos minutos, el build debería estar disponible en tu panel de control de App Store Connect.

Panel de control de Testflight

9. ¿Puedo desplegar desde la máquina local?

Guías de configuración de CI/CD

Plataformas de CI/CD alternativas

Actualizaciones en vivo y despliegue

Gracias

Este blog se basa en los siguientes artículos:

Sigue adelante desde la compilación Capacitor IOS automática con GitHub acciones con certificado

Si estás utilizando La compilación Capacitor IOS automática con GitHub acciones con certificado para planificar la automatización de CI/CD, conecta con Capgo CI/CD para el flujo de trabajo del producto en Capgo CI/CD, Capgo Compilaciones nativas para el flujo de trabajo del producto en Capgo Compilaciones nativas, Capgo Integraciones para el flujo de trabajo del producto en Capgo Integraciones, Integración de CI/CD para los detalles de implementación en la Integración CI/CD, y GitHub Integración de Acciones para los detalles de implementación en GitHub Integración de Acciones.

Actualizaciones en vivo para Capacitor aplicaciones

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

Cuando un bug en la capa web está vivo, envíe la corrección a través de __CAPGO_KEEP_0__ en lugar de esperar días para la aprobación de la tienda de aplicaciones. Los usuarios obtienen la actualización en segundo plano mientras los cambios nativos siguen en el camino de revisión normal.

Contenido: Página/área: Sitio web de marketing de Capgo. Rol: Descripción de apoyo o descripción meta. Visto en: componente GetStarted.astro. Preservar términos de producto/marca y términos de desarrollador exactamente. Mensaje clave `descripcion_actualizaciones_instantaneas_para_aplicaciones_capacitor` (Descripción De Actualizaciones Instantáneas Para Aplicaciones Capacitor).

Apoyo humano de Martin

Capgo gives you the best insights you need to create a truly professional mobile app.