Saltar al contenido principal
CI/CD

Automático Capacitor IOS build con GitHub acciones con certificado

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

Automático 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 pipelines de acciones de GitHub, pero los nuevos builds de iOS deben utilizar el Capgo CLI para que no tengas que mantener Fastlane, ejecutores de Xcode, certificados y scripts de carga por tu cuenta.

Capgo Build para CI/CD por Capgo

Evite la configuración de Fastlane, Xcode runner, certificado, perfil de provisión y script de carga. Capgo Construcción Ejecuta compilaciones nativas de iOS firmadas desde tu pipeline de CI/CD existente:

  • Funciona con tu pipelineDesencadena la construcción de Capgo desde GitHub Actions, GitLab CI, Jenkins o scripts locales después de tu compilación web. npx cap sync.
  • Firmar desde secretos de CIGuarde las llaves de App Store Connect, certificados, perfiles de configuración de provisión, contraseñas y IDs de equipo en tus propios secretos de CI.
  • No mantenimiento de ejecución nativa: Capgo Build ofrece entornos de compilación de Apple mantenidos, por lo que no tiene 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 del Capgo CLI.

Precio

  • Planes de Capgo comienzan en $12/mes
  • Incluye actualizaciones OTA y aproximadamente 15 compilaciones nativas por mes
  • Los minutos adicionales de construcción se facturan por minuto mediante 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 Fastlane instalado en tu máquina de desarrollo.
  • Asegúrate de ser parte del programa de membresía de desarrollador de iOS.

Información importante sobre el precio

Precio GitHub Acción

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 advertidos de los requisitos y precios, sigamos adelante.

Nota: En el post asumo 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 GitHub Acciones

1. Usando 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 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 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

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

  2. Seleccionar Usuarios y Acceso.

Acceso del usuario de App Store Connect

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

App Store Connect API Integración

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

Las claves de App Store Connect API crean

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

App Store Connect API claves crean nombre

6 — Debajo de 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 rol. Recomendamos seleccionar App manager.

  1. Haga clic en Generar.

Un clave de acceso API no puede limitarse a aplicaciones específicas.

El nombre de la clave, la clave ID, 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. Identificador de problema. (APPLE_ISSUER_ID secreto)
2. Identificador de clave. (APPLE_KEY_ID secreto)
3. Haga clic en "Descargar clave API" para descargar su clave privada API. 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, puede descargarla solo una vez.

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

Usando una clave de App Store Connect API

El archivo de clave API (p8 que descargó), la clave ID y la 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_key. Puede 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 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

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

2. Certificados

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

Code identidades de firma

Haz clic en Administrar certificados.

Si no has creado ya 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 caja fuerte y cambiar a login clave y luego la pestaña 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 en el certificado y selecciona Export.

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 clave secreta. También, cuando se le pregunte, por favor proporcione la contraseña del certificado. Esta contraseña será su P12_PASSWORD clave secreta.

3. Perfiles de configuración

Abrir Desarrollador de Apple y seleccione el equipo correcto.

Luego crea un nuevo perfil, haciendo clic en +

Crear un nuevo perfil

Y selecciona App Store Connect.

Seleccionar App Store Connect

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

Seleccionar la aplicación correcta

Selecciona 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, 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 is a Ruby library created to automate common mobile development tasks. Using Fastlane, you can configure custom “lanes” which bundle a series of “actions” that perform tasks that you’d normally perform using Android studio. You can do a lot with Fastlane, but for the purposes of this tutorial, we’ll be using only a handful of core actions.

Cree el carpeta Fastlane en la raíz de su proyecto Capacitor/Ionic y agregue el archivo Fastfile allí:

  • Folder: <project-root>/fastlane/
  • acciones <project-root>/fastlane/Fastfile

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

a continuación del <project-root>/fastlane/.env al lado de FastfileNo cometas este archivo. Agrega fastlane/.env a tu .gitignore Obtener el ID del equipo de APP STORE CONNECT

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 de equipo de App Store Connect

secrets Centro de Desarrolladores y desplázate hacia abajo hasta Membership details section. The Team ID es el valor que debes establecer en el APP_STORE_CONNECT_TEAM_ID secret.

app-store-connect-team-id

app-store-connect-team-id

  1. Abre Xcode
  2. Doble clic en el App en el navegador de proyectos
  3. en el navegador de proyectos Signing and Capabilities
  4. Luego haz clic en la pestaña Bundle identifier. Este es el valor que debes establecer en el BUNDLE_IDENTIFIER secret.
bundle-identifier-xcode

6. Procesamiento de compilación

En GitHub Actions, you are billed based on the minutes you have used for running your CI/CD workflow. From my experience, it takes about 10–15 minutes before a build can be processed in App Store Connect.

Para proyectos privados, el costo estimado por construcción puede llegar a , 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

Si estás preocupado por los costos para proyectos privados, puedes configurar 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 tradeo - 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 7. Configuración de __CAPGO_KEEP_0__ Actions Configuración de __CAPGO_KEEP_0__ secrets

7. Configura GitHub Acciones

Configura secretos GitHub

Por favor copie los secretos desde el .env péguelos en el secreto de repositorio GitHub.

Vaya a Settings &gt; Secretos y variables &gt; Acciones &gt; Nueva clave secreta de repositorio

github-secrets

2. BUILD_CERTIFICATE_BASE64 - Certificado codificado en Base64.

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

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

5. APPLE_KEY_ID — App Store Connect API Clave 🔺ID 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, revisa esto

8. Configure GitHub workflow file

Crea un directorio de flujo de trabajo GitHub.

cd .github/workflows

Dentro de workflow el 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 necesitas automatizar la etiqueta, por favor, consulta Automatic build and release con GitHub actions 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.

Su aplicación no necesita utilizar Ionic, solo es necesario la base Capacitor, 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

Haga 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 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 CI/CD alternativas

Actualizaciones en vivo y despliegue

Gracias

Este blog se basa en los siguientes artículos:

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

Si estás utilizando Construcción automática de IOS de Capacitor 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 Construcción Nativa para el flujo de trabajo del producto en Capgo Construcción Nativa 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 Integración de Acciones para el detalle de implementación en GitHub Integración de Acciones

Actualizaciones en vivo para aplicaciones de Capacitor

¿Cuándo un error de capa web está en vivo, envía la solución a través de Capgo 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.

Últimas noticias de nuestro Blog

Capgo te da las mejores perspectivas que necesitas para crear una aplicación móvil verdaderamente profesional.