Saltar al contenido principal
CI/CD

Construcción automática de IOS con Capacitor y acciones de GitHub con certificado

Cómo configurar una pipeline de CI/CD para tu aplicación IOS Ionic utilizando fastlane y GitHub Actions en 5 minutos (2024)

Créditos del artículo

Martin Donadieu

Escritor

Valeria

Revisor

Jordan

Editor

Automatic Capacitor IOS build con GitHub acciones con certificado

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

Ahora recomendamos utilizar Capgo Construcción con el Capgo CLI para construcciones nativas Capacitor. Esta guía de Fastlane se mantiene para equipos que mantienen existentes líneas de acción de 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 Construcción para CI/CD por Capgo

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

  • Funciona con tu pipeline: Desencadena la construcción de Capgo desde GitHub Actions, GitLab CI, Jenkins o scripts locales después de tu construcción web y npx cap sync.
  • : Firma 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.
  • : La construcción de __CAPGO_KEEP_0__ no requiere mantenimiento de ejecutores nativos, ya que proporciona entornos de construcción Apple mantenidos, por lo que no tienes que administrar ejecutores macOS, imágenes de Xcode o rutas de Fastlane.: Descarga artefactos firmados para QA o envía builds de lanzamiento a través de la Capgo __CAPGO_KEEP_1__.
  • Precio: Download signed artifacts for QA or submit release builds through the Capgo CLI.

: Incluye actualizaciones OTA y aproximadamente 15 construcciones nativas por mes

  • Capgo plans start at $12/month
  • : Los minutos adicionales de construcción se facturan por minuto a través de créditos
  • Extra build minutes are billed by minute through credits

Configura Capgo Build en CI/CD

Guía de configuración manual

Esto es 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 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 de la __CAPGO_KEEP_0__ Acción

Setup de GitHub Build en CI/CD automático

https://github.com/features/actions

El servicio es ‘gratuito’ hasta el límite, dependiendo de la máquina elegida.
Vamos a utilizar una 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, continuemos.

Nota: En el post supongo que ya 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 API de App Store Connect
      • Usar una clave de API de App Store Connect
  2. Copiar archivos de Fastlane
  3. Configurar acciones de GitHub

1. Usar App Store Connect API con Fastlane

A partir de 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 de emisor
  2. ID de clave
  3. Archivo de clave o contenido de clave

Obteniendo una clave de App Store Connect API

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 con App Store Connect.

  2. Seleccionar Usuarios y acceso.

Acceso de usuario de App Store Connect

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

Integración de App Store Connect API

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

Las llaves API de App Store Connect crean

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

Las llaves API de App Store Connect crean nombre

6 — En Acceso, seleccione el rol para la llave. Los roles que se aplican a las llaves son los mismos roles que se aplican a los usuarios de su equipo. Consulte permisos de rol . Se recomienda seleccionar Administrador de aplicaciones.

  1. Haga clic en Generar.

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

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

Descargar claves de App Store Connect

Puedes obtener toda la información necesaria aquí.
<1> Identificador de la incidencia. (APPLE_ISSUER_ID secret)
<2> Identificador de la clave. (APPLE_KEY_ID secret)
<3> Haz clic en “Descargar Clave API” 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 (p8 que descargas), 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 al Fastlane. Eligió usar la acción nueva del Fastlane app_store_connect_api_keyPuedes aprender otras formas en documentación de Fastlane. Muestro este método porque creo que es la forma más fácil de trabajar con la mayoría de las CI allí, donde puedes establecer variables de entorno.

Por favor, convierte el archivo p8 que descargaste 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 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 llave de cadena para descargar el certificado como un .p12 archivo.

Para hacerlo, debes ir a la llave de cadena, cambiar a la sección y Iniciar sesión clave de cadena y luego la pestaña Mi Certificados.

Mi Certificados

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 selecciona Exportar.

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

Esto 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

Esto se convertirá en su BUILD_CERTIFICATE_BASE64 clave secreta. Además, cuando se le pregunte, por favor proporcione la contraseña del certificado. Esta contraseña será su P12_PASSWORD clave secreta.

3. Perfiles de provisión

Abrir Desarrollador de Apple y seleccione el equipo correcto.

Entonces cree un nuevo perfil, haciendo clic en +

Crear un nuevo perfil

Y seleccione App Store Connect.

Seleccione App Store Connect

Luego debes seleccionar la aplicación correcta, ten cuidado, ya que no puedes utilizar un 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 haz 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, 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. Al utilizar Fastlane, puede 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

que realizan tareas que normalmente se harían utilizando Android Studio. Puede hacer mucho con Fastlane, pero para los propósitos de este tutorial, utilizaremos solo una pequeña cantidad de acciones básicas. package.json, capacitor.config.*Cree la carpeta de Fastlane en la raíz de su proyecto __CAPGO_KEEP_0__/Ionic y agregue el archivo Fastfile allí: ios/ Carpeta: 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

Archivo:

GitHub Actions uses the repository secrets you configure in the next step. You only need a local .env , y la carpeta. No lo cree dentro de la carpeta de Fastlane. 5. Configuración de secretos __CAPGO_KEEP_0__ Acciones utiliza los secretos de repositorio que configura en el siguiente paso. Solo necesita un archivo local si desea ejecutar o probar Fastlane desde su propia máquina.

Para la prueba local, crea <project-root>/fastlane/.env al lado de 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 a la Membership details sección. La Team ID es el valor que debes establecer en el APP_STORE_CONNECT_TEAM_ID secret.

id de equipo de app store connect

Obtener el identificador de paquete

  1. Abrir Xcode
  2. Haz clic con el botón derecho en el App En el navegador de proyectos
  3. Luego haz clic en la pestaña Signing and Capabilities
  4. Copia el valor del Bundle identifierEste es el valor que debes establecer en el BUNDLE_IDENTIFIER secret.
identificador-de-paquete-xcode

6. Procesamiento de compilación

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

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

Si se preocupa por los costos para proyectos privados, puede establecer skip_waiting_for_build_processing para trueEsta opción ahorrará minutos de compilación no esperando a que App Store Connect termine de procesar la compilación.

Sin embargo, hay un tradeoff - deberá actualizar manualmente la información de cumplimiento de su 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. Configura GitHub Acciones

Configura GitHub secretos

Por favor copia los secretos del archivo y pégalos en los secretos de variables del repositorio __CAPGO_KEEP_0__. .env file and paste them into the GitHub repository secrets.

Ajustes &gt; Secretos y variables &gt; Acciones &gt; Nueva secretos de repositorio Nuevo

github-secretos

2. BUILD_CERTIFICATE_BASE64 - Certificado Base64 codificado.

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

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

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

6. APPLE_ISSUER_ID — Clave de App Store Connect API 🔺ID 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 carpeta, 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

This workflow should be triggered after each GitHub etiquetasi necesitas automatizar la etiqueta, por favor, consulta Automatic build and release with GitHub actions primero.

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

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

Your App doesn’t need to use Ionic, only Capacitor base is mandatory., it can have old Cordova module, but Capacitor JS plugin should be preferred.

base

8. Desencadena el flujo de trabajo

Haz un commit, deberías ver el flujo de trabajo activo en el repositorio.

Activar el flujo de trabajo

Envía los nuevos commits a la rama main o development ¿Cómo puedo hacer que el flujo de trabajo se active?

Para activar el flujo de trabajo

Comenzaste 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?

Puede utilizar Xcode para compilar y firmar su 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, conecta con Capgo automatización de CI/CD para el flujo de trabajo del producto en Capgo automatización de 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 CI/CD para el detalle de implementación en Integración CI/CD, y GitHub Acciones de Integración para el detalle de implementación en GitHub Acciones de Integración.

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 bug de 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 del contexto: Página/área: Sitio web de marketing de Capgo. Rol: Oración de copia de sitio web. Visto en: componente GetStarted.astro. Preservar términos de producto/marca y términos de desarrollador exactamente. Mensaje clave `instant_updates_for_capacitor_apps_description` (Descripción de Actualizaciones Instantáneas Para Aplicaciones de Capacitor).

Apoyo humano de Martin

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