Passer au contenu principal
CI/CD

Construction automatique d'Capacitor IOS avec des GitHub actions avec certificat

Comment configurer une chaîne de construction continue (CI/CD) pour votre application IOS Ionic en utilisant Fastlane et des GitHub Actions en 5 minutes (2024)

Crédits de l'article

Martin Donadieu

Auteur

Valeria

Relecteur

Jordan

Éditeur

Construction automatique d'Capacitor IOS avec des GitHub actions avec certificat

Configurer la CI/CD pour les applications Capacitor peut être complexe et fastidieux. Voici ce dont vous avez besoin de savoir :

Nous recommandons maintenant d'utiliser Capgo Build avec le Capgo CLI pour les builds natifs Capacitor. Cette guide Fastlane est conservée pour les équipes qui maintiennent des pipelines d'actions GitHub existants, mais les nouveaux builds iOS devraient utiliser le Capgo CLI afin que vous ne deviez pas maintenir Fastlane, les exécutants Xcode, les certificats, et les scripts d'envoi.

Capgo Build pour la CI/CD par Capgo

Évitez la maintenance de Fastlane, de l'exécutant Xcode, du certificat, du profil de provisionnement, et du script d'envoi. Capgo Build exécute des builds iOS signés natifs à partir de votre pipeline CI/CD existant :

  • Fonctionne avec votre pipeline: Déclenchez Capgo Build à partir d'actions GitHub, de GitLab CI, de Jenkins, ou de scripts locaux après votre build web et npx cap sync.
  • Signer à partir de secrets CI: Gardez les clés App Store Connect, les certificats, les profils de provisioning, les mots de passe et les identifiants d'équipe dans vos propres secrets CI.
  • : Pas de maintenance du runner natif: Capgo Build fournit des environnements de construction Apple maintenus, vous n'avez donc pas à gérer les runners macOS, les images Xcode ou les voies Fastlane.
  • : Artéfacts et soumission: Téléchargez les artefacts signés pour les tests ou soumettez des builds de mise en production à travers le Capgo CLI.

Prix

  • : Plans Capgo commencent à 12 $/mois
  • : Inclut les mises à jour OTA et environ 15 constructions natives par mois
  • : Les minutes de construction supplémentaires sont facturées par minute à l'aide de crédits

: Installez Capgo Build dans CI/CD

: Guide de configuration manuel

Voici ce dont vous avez besoin :

Déploiement continu pour iOS en utilisant Fastlane et GitHub Actions et certificat

Prérequis

Avant de continuer avec le tutoriel :

  • Assurez-vous d'avoir Fastlane installé sur votre machine de développement.
  • Vérifiez que vous êtes membre du programme de développeur iOS.

Informations importantes sur le prix

Prix de l'action GitHub

https://github.com/features/actions

Le service est ‘gratuit jusqu'à la limite, en fonction de la machine choisie.
On va utiliser une machine macOS machine macOS, vous pouvez voir dans l'écran d'aperçu son prix et ses limites (tarifs au moment de la création de ce tutoriel, ils pourraient subir des changements à l'avenir)

Une fois averti des exigences et des prix, continuons.

Remarque : Dans l'article, je suppose que vous avez créé l'application dans App Store Connect. L'information importante sera copiée par Fastlane !

Qu'est-ce que vous allez apprendre dans ce tutoriel

Étapes à suivre dans cet article

  1. Utilisation d'App Store Connect API avec Fastlane
    • Exigences :
      • Création d'une clé App Store Connect API
      • Utiliser une clé App Store Connect API
  2. Copier les fichiers Fastlane
  3. Configurer les actions GitHub

1. Utiliser App Store Connect API avec Fastlane

À partir de février 2021, la deuxième factor d'authentification ou la vérification à deux étapes est obligatoire pour tous les utilisateurs pour se connecter à App Store Connect. Cette couche supplémentaire de sécurité pour votre identifiant Apple vous aide à vous assurer que vous êtes la seule personne qui peut accéder à votre compte.
Depuis Support Apple

Exigences

Pour que Fastlane puisse utiliser App Store Connect API pour télécharger votre application, vous devez fournir les éléments suivants trois choses :

  1. Identifiant émetteur
  2. ID de clé
  3. Fichier de clé ou Contenu de clé

Obtenir une clé d'App Store Connect API

Pour générer des clés, vous devez avoir les droits d'administrateur dans App Store Connect. Si vous n'avez pas ces droits, vous pouvez diriger la personne concernée à cet article.

  1. Se connecter à App Store Connect.

  2. Sélectionner Utilisateurs et accès.

Accès à l'utilisateur App Store Connect

3 — Sélectionner l'onglet Intégration.

Intégration d'App Store Connect API

  1. Cliquez sur Générer clé d'App Store Connect API ou le bouton Ajouter (+).

App Store Connect API clés créent

  1. Entrez un nom pour la clé. Le nom est uniquement pour votre référence et n'est pas partie de la clé elle-même.

App Store Connect API clés créent nom

6 — Sous Accès, sélectionnez le rôle pour la clé. Les rôles qui s'appliquent aux clés sont les mêmes rôles qui s'appliquent aux utilisateurs de votre équipe. Voir permissions de rôle. Nous recommandons de sélectionner gestionnaire d'applications.

  1. Cliquez sur Générer.

Un API clé d'accès ne peut pas être limité à des applications spécifiques.

Le nom de la nouvelle clé, l'ID de la clé, un lien de téléchargement et d'autres informations apparaissent sur la page.

App Store Connect télécharger les clés

Vous pouvez récupérer toutes les trois informations nécessaires ici.
<1> ID de la question. (APPLE_ISSUER_ID <2> ID de la clé. (
<3> Cliquez sur « Télécharger la clé __CAPGO_KEEP_0__ » pour télécharger votre clé __CAPGO_KEEP_1__ privée. Le lien de téléchargement n'apparaît que si la clé privée n'a pas encore été téléchargée. Apple ne garde pas de copie de la clé privée. Vous pouvez donc la télécharger qu'une seule fois.APPLE_KEY_ID Stockez votre clé privée dans un endroit sûr. Vous ne devez jamais partager vos clés, stocker des clés dans un __CAPGO_KEEP_0__ dépôt, ou inclure des clés dans un __CAPGO_KEEP_1__ côté client.
<3> Click “Download API Key” to download your API private key. The download link appears only if the private key has not yet been downloaded. Apple does not keep a copy of the private key. So, you can download it only once.

🔴 Store your private key in a safe place. You should never share your keys, store keys in a code repository, or include keys in client-side code.

Using an App Store Connect API Key

The API Key file (p8 file that you download), the key ID, and the issuer ID are required in order to create the JWT token for authorization. There are multiple ways that this information can be passed into Fastlane. I chose to use the Fastlane’s new action app_store_connect_api_key. Je montre cette méthode parce que je pense qu'elle est la plus facile à utiliser avec la plupart des CI, où vous pouvez définir des variables d'environnement. Veuillez convertir le fichier p8 que vous téléchargez en Base64 et le stocker sous forme de secret (secret)

secret)APPLE_KEY_CONTENT).

base64 -i APPLE_KEY_CONTENT.p8 | pbcopy

Now que nous pouvons gérer l'App Store Connect avec Fastlane à l'aide de la clé API, c'est génial !

2. Certificats

Ouvrez XCode et allez à Paramètres > Comptes > Identifiant Apple > Équipes et sélectionnez votre équipe.

Identités de signature Code

Appuyez sur Gérer les certificats.

Si vous n'avez pas encore créé de certificat, vous pouvez créer un nouveau certificat.

Appuyez sur + et sélectionnez Distribution Apple

Distribution Apple

Ensuite, vous devez vous rendre dans le cléchain pour télécharger le certificat sous forme de .p12 fichier.

Pour ce faire, vous devez vous rendre dans le cléchain, passer à la cléchain de connexion et puis la onglet login Mes Certificats.

Mes Certificats

Vous pouvez ensuite sélectionner le certificat que vous souhaitez télécharger. (Recherchez par la date du certificat)

Et puis, cliquez avec le bouton droit sur la clé privée du certificat et sélectionnez Exporter.

Choisissez le format de fichier Échange d'informations personnelles (.p12).

Cela téléchargera le certificat sous forme de .p12 fichier.

Veuillez ouvrir le fichier dans un terminal et utilisez la commande suivante pour le convertir en Base64 :

base64 -i BUILD_CERTIFICATE.p12 | pbcopy

Cela deviendra votre BUILD_CERTIFICATE_BASE64 secret. Il est également demandé de fournir le mot de passe du certificat. Ce mot de passe sera votre P12_PASSWORD secret.

3. Profils de provisioning

Ouvrir Apple Developer et sélectionnez l'équipe appropriée.

Créez ensuite un nouveau profil en cliquant sur +

Créer un nouveau profil

Et sélectionnez App Store Connect.

Sélectionnez App Store Connect

Sélectionnez ensuite l'application appropriée, soyez prudent car vous ne pouvez pas utiliser des wildcards sinon la signature ne fonctionnera pas.

Sélectionnez l'application appropriée

Choisissez le bon certificat que vous avez créé avant (cherchez la date d'expiration, elle doit correspondre au jour et au mois actuel) et cliquez sur Continuez.

Choisissez le bon certificat

Enfin, entrez le nom du profil et cliquez sur Générez.

Le nom sera utilisé pour identifier le profil dans Fastlane, sous la valeur de APPLE_PROFILE_NAME.

Générez le profil

Vous pouvez télécharger le profil sous forme de .mobileprovision fichier.

Téléchargez le profil

Veuillez convertir le profil en Base64 et le stocker sous forme de secret (BUILD_PROVISION_PROFILE_BASE64).

base64 -i BUILD_PROVISION_PROFILE.mobileprovision | pbcopy

4. Copiez les fichiers Fastlane

Fastlane est une bibliothèque Ruby créée pour automatiser les tâches de développement mobile courantes. En utilisant Fastlane, vous pouvez configurer des « voies » personnalisées qui rassemblent une série d'« actions » qui exécutent des tâches que vous effectueriez normalement à l'aide d'Android Studio. Vous pouvez faire beaucoup avec Fastlane, mais pour les besoins de ce tutoriel, nous utiliserons uniquement une poignée d'actions clés.

Créez le dossier Fastlane au niveau de racine de votre projet Capacitor Ionic et ajoutez-y le fichier Fastfile:

  • Dossier : <project-root>/fastlane/
  • Fichier : <project-root>/fastlane/Fastfile

C'est au même niveau que package.json, capacitor.config.*, et le ios/ dossier. N'ajoutez pas ce dossier à l'intérieur 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. Configuration des secrets

Actions de GitHub utilisent les secrets de repository que vous configurez dans l'étape suivante. Vous n'avez besoin que d'un fichier local si vous souhaitez exécuter ou tester Fastlane à partir de votre propre machine. .env Pour les tests locaux, créez

à côté du <project-root>/fastlane/.env 5. Paramètres de confidentialité Fastfile. Ne pas commettre ce fichier. Ajoutez fastlane/.env à votre .gitignore premier (ou vérifiez s'il est déjà ignoré). Voici un exemple :

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=

Récupérer l'ID d'équipe d'APP STORE CONNECT

Allez à Centre de développement et descendez jusqu'à Membership details section. C'est la valeur que vous devez saisir dans le Team ID secret. APP_STORE_CONNECT_TEAM_ID app-store-connect-team-id

Récupérer l'IDENTIFIANT DU BUNDLE

app-store-connect-team-id

  1. Ouvrir Xcode
  2. Double-cliquez sur le App dans le navigateur de projet
  3. Cliquez ensuite sur l'onglet Signing and Capabilities
  4. Copiez la valeur de la Bundle identifierC'est la valeur que vous devez saisir dans le BUNDLE_IDENTIFIER secret.
bundle-identifier-xcode

6. Traitement de la construction

Dans GitHub Actions, vous êtes facturé en fonction des minutes que vous avez utilisées pour exécuter votre flux de CI/CD. D'après mon expérience, il faut environ 10–15 minutes avant que la construction puisse être traitée dans App Store Connect.

For les projets privés, le coût estimé par build peut aller jusqu'à $0,08/min x 15 min = $1,2, ou plus, en fonction de la configuration et des dépendances de votre projet.

Si vous vous inquiétez des coûts pour les projets privés, vous pouvez configurer skip_waiting_for_build_processing à true. Cela sauvegardera les minutes de build en ne pas attendre que App Store Connect ait terminé de traiter la build.

Cependant, il y a un compromis - vous devrez mettre à jour manuellement les informations de conformité de votre application dans App Store Connect avant de pouvoir distribuer la build aux utilisateurs.

Cette optimisation est principalement utile pour les projets privés où les minutes de build coûtent de l'argent. Pour les projets publics/gratuits, les minutes de build sont gratuites, il n'y a donc pas besoin d'activer cette fonctionnalité. Voir la page de tarification de GitHub pour plus de détails. 7. Configurer les Actions __CAPGO_KEEP_0__

Configurer les secrets GitHub

7. Configurer les Actions de GitHub

Veuillez copier les secrets du fichier et les coller dans les secrets du dépôt __CAPGO_KEEP_0__. .env Veuillez copier les secrets du fichier et les coller dans les secrets du dépôt GitHub.

Allez à Paramètres &gt; Secrets et variables &gt; Actions &gt; Nouveau secret de dépôt

github-secrets

2. BUILD_CERTIFICATE_BASE64 - Certificat encodé en Base64.

3. BUILD_PROVISION_PROFILE_BASE64 - Le profil de provisioning encodé en Base64.

4. BUNDLE_IDENTIFIER - L'identifiant de votre application.

5. APPLE_KEY_ID — La clé App Store Connect API 🔺ID de la clé.

6. APPLE_ISSUER_ID — La clé App Store Connect API 🔺ID de l'émetteur.

7. APPLE_KEY_CONTENT — La clé App Store Connect API 🔺Contenu de la clé. .p8, Vérifiez-le.

8. Configurez le fichier de flux GitHub

Créez un répertoire de flux GitHub

cd .github/workflows

Dans le dossier, créez un fichier nommé workflow et ajoutez les éléments suivants. build-upload-ios.ymlcheck it

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

Ce flux de travail doit être déclenché après chaque GitHub tagsi vous avez besoin d'automatiser les tags, veuillez vous référer à L'automatisation de la construction et de la mise en production avec GitHub actions tout d'abord.

Ensuite, ce flux de travail va récupérer vos dépendances NodeJS, les installer et construire votre application JavaScript.

Chaque fois que vous envoyez un nouveau commit, une mise en production sera créée dans TestFlight.

Votre application n'a pas besoin d'utiliser Ionic, seule la base Capacitor est obligatoire. Elle peut avoir des anciens modules Cordova, mais les plugins JavaScript Capacitor sont préférés.

8. Déclenchez le flux de travail

Créez un Commit

Faites un commitVous devriez voir le workflow actif dans le dépôt.

Déclenchez le workflow

Envoi des nouveaux commits vers la branch main ou development Comment déclencher le workflow ?

Comment déclencher le workflow ?

Commencé avec le commit

Après quelques minutes, la build devrait être disponible dans votre tableau de bord App Store Connect.

Tableau de bord Testflight

9. Puis-je déployer depuis la machine locale ?

Oui, vous pouvez, et cela est sans effort.

Guides de configuration CI/CD

Alternatives de plateformes CI/CD

Mises à jour en temps réel &amp; Déploiement

Merci

Cet article est basé sur les articles suivants :

Continuez à partir de la mise en œuvre automatique Capacitor IOS avec les GitHub actions avec certificat

Si vous utilisez La mise en œuvre automatique Capacitor IOS avec les GitHub actions avec certificat pour planifier l'automatisation CI/CD, connectez-l’à Capgo CI/CD pour le flux de travail du produit dans Capgo CI/CD, Capgo Builds natifs pour le flux de travail du produit dans Capgo Builds natifs, Capgo Intégrations pour le flux de travail du produit dans Capgo Intégrations, Intégration CI/CD pour les détails d'implémentation dans l'intégration CI/CD, et GitHub Intégration d'actions pour les détails d'implémentation dans GitHub Intégration d'actions.

Mises à jour en temps réel pour les applications 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.

Lorsqu'un bug de la couche web est en direct, expédiez la correction par __CAPGO_KEEP_0__ au lieu d'attendre des jours pour l'approbation de l'app store. Les utilisateurs reçoivent l'actualisation en arrière-plan tandis que les modifications natives restent dans la voie de revue normale.

Contexte : Page/area : Site de marketing Capgo. Rôle : Description de soutien ou de description métadonnées. Vu dans : composant GetStarted.astro. Préservons les termes de produit/marque et les termes de développeur exactement. Clé de message `instant_updates_for_capacitor_apps_description` (Description des mises à jour instantanées pour les applications Capacitor).

Support humain de Martin

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