Saltate a 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)

Martin Donadieu

Martin Donadieu

Contento Marketer

Automatic Capacitor IOS build with GitHub actions with certificate

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

Ahora recomendamos utilizar Capgo Construcción con el Capgo CLI para compilaciones nativas Capacitor. Este guía de Fastlane se mantiene para los equipos que mantienen existentes pipelines de acciones GitHub, pero los nuevos compilados iOS deben utilizar el Capgo CLI para que no tengas que mantener Fastlane, ejecutores de Xcode, certificados y scripts de carga por tu cuenta.

Compilación Capgo para CI/CD por Capgo

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

  • Funciona con tu pipeline: Dispara la Compilación Capgo desde acciones de GitHub, CI de GitLab, Jenkins o scripts locales después de tu compilación web y npx cap sync.
  • Desde secretos de CI: Mantén las llaves de App Store Connect, certificados, perfiles de provisión, contraseñas y IDs de equipo en tus propios secretos de CI.
  • No mantenimiento de ejecutor nativo: La Compilación Capgo proporciona entornos de compilación Apple mantenidos, por lo que no tienes que gestionar ejecutores de macOS, imágenes de Xcode o rutas de Fastlane.
  • Artículos y envío: Descargar artefactos firmados para QA o enviar builds de liberación a través de Capgo CLI.

Precios

  • Los planes Capgo comienzan en $12/mes
  • Incluye actualizaciones OTA y aproximadamente 15 builds nativos por mes
  • Los minutos adicionales de compilación se facturan por minuto a través de créditos

Configura Capgo Build en CI/CD

Guía de configuración manual

Aquí está lo que 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 instalado en tu máquina de desarrollo.
  • Asegúrate de que eres parte del programa de membresía de desarrollador de iOS.

Información importante sobre el precio

Precio GitHub Action

https://github.com/features/actions

El servicio es ‘gratuito’ hasta la cantidad límite, dependiendo de la máquina elegida.
Vamos a utilizar un macOS máquina, puedes ver en la captura su precio y límites (precios a la creación del tutorial, pueden sufrir cambios 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
      • Usar 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 tu ID de Apple ayuda a asegurarte de que eres la única persona que puede acceder a tu cuenta.
Desde Soporte de Apple

Requisitos

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

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

Obteniendo una clave de App Store Connect API

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

  1. Iniciar sesión en Conectar con App Store.

  2. Seleccione Usuarios y Acceso.

Acceso de usuario de App Store Connect

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

Conectar con App Store API Integración

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

Las claves de App Store Connect API crean

  1. Proporcione un nombre para la clave. El nombre es solo para su referencia y no forma parte de la clave en sí.

Claves de App Store Connect API crean nombre

6 — En Acceso, seleccione el rol para la clave. Los roles que se aplican a las claves son los mismos roles que se aplican a los usuarios de su equipo. Consulte permisos de rolRecomendamos seleccionar Administrador de la aplicación.

  1. Haga clic en Generar.

Un clave API no puede tener acceso limitado a aplicaciones específicas.

Los detalles de la nueva clave, incluyendo el nombre de la clave, el ID de la clave, un enlace de descarga y otra información aparecen en la página.

Descargar claves de App Store Connect

Puede obtener toda la información necesaria aquí.
1. ID de la incidencia. (APPLE_ISSUER_ID secret)
2. ID de la clave. (APPLE_KEY_ID secret)
Haz clic en “Descargar API Clave” para descargar tu API clave 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 puedes descargarla una vez.

🔴 Almacena tu clave privada en un lugar seguro. Nunca debes compartir tus 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 descargas), la clave ID y el ID 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 de Fastlane nueva app_store_connect_api_keyHaz clic en documentación de Fastlanepara aprender otras formas. Muestro este método porque creo que es la forma más fácil de trabajar con la mayoría de los CI, donde puedes establecer variables de entorno.

Por favor, convierte el archivo p8 que descargas a Base64 y almacénalo como un secreto (APPLE_KEY_CONTENT).

base64 -i APPLE_KEY_CONTENT.p8 | pbcopy

Ahora podemos gestionar App Store Connect con Fastlane utilizando la clave API, ¡genial!

2. Certificados

Abre XCode y ve a Configuración > Cuentas > ID de Apple > Equipos y selecciona tu equipo.

Code identidades de firma

Haz clic en Administrar certificados.

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

Haz clic en + y seleccionar Distribución de Apple

Distribución de Apple

Entonces debes ir a la llave de cadena para descargar el certificado como un .p12 archivo.

Para hacerlo, debes ir a la llave de cadena, cambiar a la llave de cadena de inicio de sesión y luego la pestaña Certificados míos Certificados míos Entonces 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 seleccionar

y seleccionar

Distribución de Apple Certificado de Apple Exportar.

Seleccione el formato de archivo Intercambio de información personal (.p12).

Se descargará el certificado como un .p12 archivo.

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

base64 -i BUILD_CERTIFICATE.p12 | pbcopy

Esto se convertirá en su BUILD_CERTIFICATE_BASE64 segredo. También, cuando se le pregunte, por favor proporcione la contraseña del certificado. Esta contraseña será su P12_PASSWORD segredo.

3. Perfiles de configuración

Abrir Desarrollador de Apple y seleccionar el equipo adecuado.

Crear un nuevo perfil, haciendo clic en +

Crear un nuevo perfil

Y seleccionar App Store Connect.

Seleccionar App Store Connect

Entonces debes seleccionar la aplicación correcta, ten cuidado, no puedes usar wildcard de lo contrario la firma fallará.

Seleccionar la aplicación correcta

Seleccionar el certificado correcto que creaste antes (busca la fecha de vencimiento, debe ser el mismo día y mes que hoy) y hacer clic en Continuar.

Seleccionar el certificado correcto

Finalmente ingresa el nombre del perfil y haz clic en Generar.

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

Generar el perfil

Puedes descargar el perfil como un .mobileprovision archivo.

Descargar el perfil

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

base64 -i BUILD_PROVISION_PROFILE.mobileprovision | pbcopy

4. Copiar archivos de Fastlane

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

Create the Fastlane folder at the root of your Capacitor/Ionic project and add the Fastfile there:

  • personalizados que agrupan una serie de <project-root>/fastlane/
  • acciones <project-root>/fastlane/Fastfile

Este nivel es el mismo que package.json, capacitor.config.*, y el ios/ carpeta. No cree este 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 Las acciones utilizan los secretos de repositorio que configuras en el siguiente paso. Solo necesitas un archivo local .env si deseas ejecutar o probar Fastlane desde tu propia máquina.

Para pruebas locales, crea <project-root>/fastlane/.env al lado de Fastfile. No comitas 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=

Obtener el ID del equipo de APP STORE CONNECT

Vaya a Centro de Desarrolladores y desplácese hacia abajo hasta Membership details sección. Team ID es el valor que debes establecer en el APP_STORE_CONNECT_TEAM_ID secret.app-store-connect-team-id

Obtener el BUNDLE_IDENTIFIER

Abra Xcode

  1. Doble clic en el
  2. en el navegador de proyectos App Entonces haga clic en la pestaña
  3. __CAPGO_KEEP_0__ Signing and Capabilities
  4. copie el valor de la Bundle identifierEsto es el valor que debes establecer en la BUNDLE_IDENTIFIER secret.
bundle-identifier-xcode

6. Procesamiento de

En GitHub Actions, se facturan minutos según el tiempo que has utilizado para ejecutar tu flujo de trabajo CI/CD. De mi experiencia, tarda unos 10-15 minutos antes de que un build pueda ser procesado en App Store Connect. Para proyectos privados, el costo estimado por build 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

7. Build Processing skip_waiting_for_build_processing To trueEsto ahorrará minutos de compilación ya que no se espera a que App Store Connect termine de procesar la compilación.

Sin embargo, hay un tradeof - deberá actualizar manualmente la información de cumplimiento de la aplicación en App Store Connect antes de poder distribuir la compilació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 __CAPGO_KEEP_0__ para obtener más detalles.

7. Configuración de GitHub Actions

Configuración de GitHub secrets

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

Vaya a Configuración &gt; Secretos y variables &gt; Acciones &gt; Nueva secreta de repositorio

github-secrets

2. BUILD_CERTIFICATE_BASE64 - Certificado codificado en Base64.

3. BUILD_PROVISION_PROFILE_BASE64 - Perfil de provisión codificado en Base64.

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 — Configuración de la Tienda de Mac App Store API Key 🔺 Contenido de la clave .p8, verifique esto

8. Configura el archivo de flujo de trabajo GitHub

Crear un directorio de flujo de trabajo GitHub

cd .github/workflows

Dentro del workflow directorio, crea un archivo llamado build-upload-ios.ymly agrega 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 la etiqueta, consulte Automatic build and release con acciones de GitHub primero.

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

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

No es necesario que su aplicación utilice Ionic, solo es necesario que tenga la base Capacitor obligatoria, puede tener módulos de Cordova antiguos, pero se recomienda utilizar el plugin de JavaScript Capacitor.

8. Desencadene el flujo de trabajo

Crear un commit

Hacer un commit, debería ver el flujo de trabajo activo en el repositorio.

Desencadene el flujo de trabajo

Pushe los nuevos commits a la rama main o development para desencadenar el flujo de trabajo.

Comenzado con el commit

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?

Sí, puedes, y es sencillo.

Puedes utilizar Xcode para compilar y firmar tu aplicación, como siempre.

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:

Keep going from Automatic Capacitor IOS build with GitHub actions with certificate

Si estás utilizando Automatic Capacitor IOS build with GitHub actions with certificate para planificar la automatización de CI/CD, conectarlo 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 el detalle de implementación en Integración de CI/CD, y GitHub Integración de Acciones para el detalle de implementación en GitHub Integración de Acciones.

Actualizaciones en vivo para aplicaciones de Capacitor

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 error de capa de web está vivo, envía la corrección a través de __CAPGO_KEEP_0__ en lugar de esperar días por la aprobación de la tienda de aplicaciones. Los usuarios reciben la actualización en segundo plano mientras los cambios nativos siguen en el camino de revisión normal."Contenido del contexto: Página/área: Sitio web de marketing de Capgo. Rol: Oración de 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. Clave de mensaje `instant_updates_for_capacitor_apps_description` (Descripción de Actualizaciones Instantáneas para Aplicaciones de Capacitor).". Contenido del contexto: Página/área: Página de inicio de marketing de copia. Rol: Oración de copia de sitio web. Visto en: componente HumanSupport.astro, componente pricing/Plans.astro. Clave de mensaje `home_hero_human_support` (Soporte Humano del Hero de la Página de Inicio).

Inicia Ahora

Últimas noticias de nuestro Blog

Capgo te brinda las mejores herramientas para crear una aplicación móvil profesional de verdad.