Builds iOS automatiques avec des actions GitHub via Match
Configurer la CI/CD pour les apps Capacitor peut être complexe et chronophage. Voici ce qu'il faut savoir :
Recommandé pour les nouveaux builds : utilisez Capgo Build
Nous recommandons désormais d'utiliser Capgo Build avec Capgo CLI pour les builds natifs Capacitor. Ce guide Fastlane Match est conservé pour les équipes qui maintiennent des pipelines GitHub Actions existants, mais les nouveaux builds iOS devraient utiliser Capgo CLI pour vous éviter de gérer vous-même Fastlane, les dépôts Match, les runners Xcode, les certificats et les scripts d'upload.
Capgo Build pour CI/CD par Capgo
Évitez la maintenance de Fastlane Match, des runners Xcode, des certificats, des profils de provisionnement et des scripts d'upload. Build Capgo exécute des builds natifs iOS signés depuis votre pipeline CI/CD existant :
- Compatible avec votre pipeline: Déclenchez Capgo Build depuis GitHub Actions, GitLab CI, Jenkins ou des scripts locaux après votre build web et
npx cap sync. - Signature via les secrets CI: Conservez vos clés App Store Connect, certificats, profils de provisionnement, mots de passe et team IDs dans vos propres secrets CI.
- Aucune maintenance de runner natif: Capgo Build fournit des environnements de build Apple maintenus, vous évitant de gérer les runners macOS, les images Xcode, Fastlane ou les dépôts Match.
- Artifacts et soumission: Téléchargez les artifacts signés pour la QA ou soumettez vos builds de release via Capgo CLI.
Tarifs
- Les plans Capgo commencent à 12 $/mois
- Inclut les mises à jour OTA et environ 15 builds natifs par mois
- Les minutes de build supplémentaires sont facturées à la minute via des crédits
Configurez Capgo Build dans votre CI/CD
Guide de configuration manuelle
Voici ce que vous devez faire :
Livraison continue pour iOS via Fastlane et GitHub Actions avec match
Prerequisites
Avant de poursuivre le tutoriel…
- Assurez-vous d'avoir Fastlane installé sur votre machine de développement.
- Un abonnement au programme développeur iOS.
- L'envie de lire 😆…
- Une équipe de nombreux devs, sinon nous recommandons d'utiliser fastlane cert pour des workflows plus simples.
Important concernant le prix

https://github.com/features/actions
Le service est « gratuit » jusqu'à la limite, selon la machine choisie.
Nous allons utiliser une machine macOS vous pouvez voir son prix et ses limites sur la capture d'écran (tarifs au moment de la création du tutoriel, ils peuvent évoluer)
🔴 Une fois les prérequis et les tarifs présentés, si vous le souhaitez, continuons…
📣 Dans cet article, nous partons du principe que l'app est créée dans iTunes Connect et que nous possédons les certificats de l'écosystème Apple ; tout sera copié par Fastlane !
Plongeons dans le vif du sujet 🤿
Étapes à suivre dans l'article
- Utiliser App Store Connect API avec Fastlane Match
- Prérequis
- Créer une clé API App Store Connect
- Utiliser une clé API App Store Connect
- Copier les fichiers Fastlane
- Configurer Fastlane match
1. Utiliser API d'App Store Connect avec Fastlane Match
Depuis février 2021, l'authentification à deux facteurs ou la vérification en deux étapes est requise pour tous les utilisateurs se connectant à App Store Connect. Cette couche de sécurité supplémentaire pour votre identifiant Apple garantit que vous êtes la seule personne à pouvoir accéder à votre compte.
From Support Apple
Pour commencer avec match, vous devrez révoquer vos certificats actuels. Mais ne vous inquiétez pas, vous recevrez directement les nouveaux.
Prérequis
Pour pouvoir utiliser API d'App Store Connect, Fastlane a besoin de trois éléments.
- ID de l'émetteur.
- ID de la clé.
- Fichier de clé ou contenu de la clé.
Création d'une clé API App Store Connect
Pour générer des clés, vous devez disposer des droits d'administrateur dans App Store Connect. Si vous n'avez pas cette permission, vous pouvez transmettre cet article à la personne concernée et suivre ces instructions.
1 — Connectez-vous à App Store Connect.
2 — Sélectionnez Utilisateurs et accès.

3 — Sélectionnez l'onglet Intégrations.

4 — Cliquez sur Générer une clé API ou sur le bouton Ajouter (+).

5 — Saisissez un nom pour la clé. Ce nom est uniquement pour votre référence et ne fait pas partie de la clé elle-même.

6 — Sous Access, sélectionnez le rôle de la clé. Les rôles applicables aux clés sont les mêmes que ceux appliqués aux utilisateurs de votre équipe. Consultez les permissions de rôle. Nous recommandons de sélectionner App manager.
7 — Cliquez sur Generate.
L'accès d'une clé API ne peut pas être limité à des apps spécifiques.
Le nom de la nouvelle clé, son ID, un lien de téléchargement et d'autres informations s'affichent sur la page.

Vous pouvez récupérer les trois informations nécessaires ici.
<1> ID de l'issue.
<2> ID de la clé.
<3> Cliquez sur « Download API Key » pour télécharger votre clé privée API. 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 conserve pas de copie de la clé privée. Vous ne pouvez donc la télécharger qu'une seule fois.
🔴 Stockez votre clé privée dans un endroit sûr. Vous ne devez jamais partager vos clés, les stocker dans un dépôt code ou les inclure dans du code côté client.
Utiliser une clé API App Store Connect
Le fichier API Key (le fichier p8 que vous téléchargez), l'ID de la clé et l'ID de l'émetteur sont nécessaires pour créer le token JWT d'autorisation. Il existe plusieurs façons d'injecter ces informations dans Fastlane via la nouvelle action de Fastlane, app_store_connect_api_key. Vous pouvez découvrir d'autres méthodes dans la documentation Fastlane. Je présente cette méthode car je pense que c'est la plus simple pour la plupart des CI actuelles, où vous pouvez configurer des variables d'environnement.
Nous pouvons maintenant gérer Fastlane avec la clé API App Store Connect, super !
2. Copier les fichiers Fastlane
Fastlane est une bibliothèque Ruby créée pour automatiser les tâches courantes du développement mobile. Avec Fastlane, vous pouvez configurer des « lanes » personnalisées qui regroupent une série d'« actions » pour effectuer les tâches que vous feriez normalement via Android Studio. Vous pouvez faire énormément de choses avec Fastlane, mais pour ce tutoriel, nous n'utiliserons que quelques actions de base.
Créez un dossier Fastlane à la racine de votre projet et copiez les fichiers suivants : Fastfile
default_platform(:ios)
DEVELOPER_APP_IDENTIFIER = ENV["DEVELOPER_APP_IDENTIFIER"]
DEVELOPER_APP_ID = ENV["DEVELOPER_APP_ID"]
PROVISIONING_PROFILE_SPECIFIER = ENV["PROVISIONING_PROFILE_SPECIFIER"]
TEMP_KEYCHAIN_USER = ENV["TEMP_KEYCHAIN_USER"]
TEMP_KEYCHAIN_PASSWORD = ENV["TEMP_KEYCHAIN_PASSWORD"]
APPLE_ISSUER_ID = ENV["APPLE_ISSUER_ID"]
APPLE_KEY_ID = ENV["APPLE_KEY_ID"]
APPLE_KEY_CONTENT = ENV["APPLE_KEY_CONTENT"]
GIT_USERNAME = ENV["GIT_USERNAME"]
GIT_TOKEN = ENV["GIT_TOKEN"]
def delete_temp_keychain(name)
delete_keychain(
name: name
) if File.exist? File.expand_path("~/Library/Keychains/#{name}-db")
end
def create_temp_keychain(name, password)
create_keychain(
name: name,
password: password,
unlock: false,
timeout: 0
)
end
def ensure_temp_keychain(name, password)
delete_temp_keychain(name)
create_temp_keychain(name, password)
end
platform :ios do
lane :build do
build_app(
configuration: "Release",
workspace: "./ios/App/App.xcworkspace",
scheme: "App",
export_method: "app-store",
export_options: {
provisioningProfiles: {
DEVELOPER_APP_ID => "#{PROVISIONING_PROFILE_SPECIFIER}"
}
}
)
end
lane :refresh_profiles do
match(
type: "development",
force: true)
match(
type: "adhoc",
force: true)
end
desc "Register new device"
lane :register_new_device do |options|
device_name = prompt(text: "Enter the device name: ")
device_udid = prompt(text: "Enter the device UDID: ")
device_hash = {}
device_hash[device_name] = device_udid
register_devices(
devices: device_hash
)
refresh_profiles
end
lane :closed_beta do
keychain_name = TEMP_KEYCHAIN_USER
keychain_password = TEMP_KEYCHAIN_PASSWORD
ensure_temp_keychain(keychain_name, keychain_password)
api_key = app_store_connect_api_key(
key_id: APPLE_KEY_ID,
issuer_id: APPLE_ISSUER_ID,
key_content: APPLE_KEY_CONTENT,
duration: 1200,
in_house: false
)
match(
type: 'appstore',
git_basic_authorization: Base64.strict_encode64("#{GIT_USERNAME}:#{GIT_TOKEN}"),
readonly: true,
keychain_name: keychain_name,
keychain_password: keychain_password,
api_key: api_key
)
gym(
configuration: "Release",
workspace: "./ios/App/App.xcworkspace",
scheme: "App",
export_method: "app-store",
export_options: {
provisioningProfiles: {
DEVELOPER_APP_ID => "#{PROVISIONING_PROFILE_SPECIFIER}"
}
}
)
pilot(
apple_id: "#{DEVELOPER_APP_ID}",
app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
skip_waiting_for_build_processing: true,
skip_submission: true,
distribute_external: false,
notify_external_testers: false,
ipa: "./App.ipa"
)
delete_temp_keychain(keychain_name)
end
lane :submit_review do
version = ''
Dir.chdir("..") do
file = File.read("package.json")
data = JSON.parse(file)
version = data["version"]
end
deliver(
app_version: version,
submit_for_review: true,
automatic_release: true,
force: true, # Skip HTMl report verification
skip_metadata: false,
skip_screenshots: false,
skip_binary_upload: true
)
end
end
Appfile
app_identifier(ENV["DEVELOPER_APP_IDENTIFIER"])
apple_id(ENV["FASTLANE_APPLE_ID"])
itc_team_id(ENV["APP_STORE_CONNECT_TEAM_ID"])
team_id(ENV["DEVELOPER_PORTAL_TEAM_ID"])
Configurez Fastlane match
Fastlane match est une nouvelle approche pour la signature code d'iOS. Fastlane match permet aux équipes de gérer facilement les certificats et les profils de provisionnement requis pour vos apps iOS.
Créez un nouveau dépôt privé nommé certificates, par exemple sur votre compte personnel ou votre organisation GitHub.
Initialisez Fastlane match pour votre app iOS.
fastlane match init
Sélectionnez ensuite l'option n°1 (Git Storage).
[01:00:00]: fastlane match supports multiple storage modes, please select the one you want to use:1. git2. google_cloud3. s3?
Attribuez l'URL du dépôt fraîchement créé.
[01:00:00]: Please create a new, private git repository to store the certificates and profiles there[01:00:00]: URL of the Git Repo: <YOUR_CERTIFICATES_REPO_URL>
Vous trouverez maintenant dans le dossier Fastlane un fichier nommé Matchfile et
_git_url_doit être défini sur l'URL HTTPS du dépôt de certificats. Vous pouvez aussi utiliser SSH, mais cela nécessite une étape différente à exécuter.
# ios/Matchfilegit_url("https://github.com/gitusername/certificates")storage_mode("git")type("appstore")
Ensuite, nous générons les certificats et saisissons vos identifiants lorsque Fastlane Match vous le demande.
Un prompt vous demandera de saisir une passphrase. Retenez-la bien, car elle sera utilisée plus tard par les GitHub Actions pour décrypter votre dépôt de certificats.
fastlane match appstore
Si tout s'est bien passé, vous devriez voir quelque chose comme ceci :
[01:40:52]: All required keys, certificates and provisioning profiles are installed 🙌
Si vous avez rencontré un problème avec GitHub et les permissions nécessaires, peut-être que cet article vous aidera à générer des tokens d'authentification pour git.
Les certificats et profils de provisionnement générés sont envoyés dans les ressources du dépôt de certificats

Enfin, ouvrez votre project dans Xcode, et mettez à jour le profil de provisionnement pour la configuration de release de votre app.

Quelques points à noter 💡
MATCH
Pour que la CI/CD puisse importer les certificats et les profils de provisionnement, elle doit avoir accès au dépôt de certificats. Pour cela, générez un personal access token (utilisé précédemment) avec les permissions nécessaires pour accéder ou lire les dépôts privés.
Dans GitHub, allez dans Paramètres → Paramètres développeur → Tokens d'accès personnels → cliquez sur Generate New Token → cochez le repo scope → puis cliquez sur Generate token.

Gardez une copie du token d'accès personnel généré. Vous l'utiliserez plus tard pour la variable d'environnement GIT_TOKEN.
Ensuite, remplacez votre fichier match généré dans le dossier Fastlane par Matchfile
CERTIFICATE_STORE_URL = ENV["CERTIFICATE_STORE_URL"]
GIT_USERNAME = ENV["GIT_USERNAME"]
GIT_TOKEN = ENV["GIT_TOKEN"]
FASTLANE_APPLE_ID = ENV["FASTLANE_APPLE_ID"]
git_url(CERTIFICATE_STORE_URL)
storage_mode("git")
type("appstore")
git_basic_authorization(Base64.strict_encode64("#{GIT_USERNAME}:#{GIT_TOKEN}"))
username(FASTLANE_APPLE_ID)
Ceci sera utilisé par les Actions GitHub pour importer les certificats et les profils de provisionnement. La variable sera définie dans les Secrets GitHub, au lieu de les coder en dur dans le fichier.
Traitement du build
Dans les Actions GitHub, la facturation se fait à la minute utilisée pour l'exécution de votre workflow CI/CD. D'après l'expérience, il faut environ 10 à 15 minutes avant qu'un build puisse être traité dans App Store Connect.
Pour les projets privés, le coût estimé par build peut atteindre 0,08 $/min x 15 min = 1,2 $, ou plus, selon la configuration ou les dépendances de votre projet.
Si vous partagez les mêmes préoccupations concernant les tarifs que moi pour les projets privés, vous pouvez garder le skip_waiting_for_build_processing à true.
Quel est le piège ? Vous devez mettre à jour manuellement la conformité de votre application dans App Store Connect après le build pour pouvoir distribuer la version à vos utilisateurs.
Il s'agit simplement d'un paramètre optionnel à mettre à jour si vous souhaitez économiser des minutes de build pour vos projets privés. Pour les projets gratuits, cela ne devrait poser aucun problème. Voir tarifs.
3. Configurer les GitHub Actions
Configurer les secrets GitHub
Vous vous demandez d'où viennent les valeurs de ENV ce n'est plus un secret : elles proviennent des secrets de votre projet. 🤦

1. APP_STORE_CONNECT_TEAM_ID - l'ID de votre équipe App Store Connect si vous faites partie de plusieurs équipes.
2. DEVELOPER_APP_ID - dans App Store Connect, allez sur l'app → Informations sur l'app → Faites défiler jusqu'à la General Information section de votre application et cherchez Apple ID.
3. DEVELOPER_APP_IDENTIFIER - l'identifiant de bundle de votre app.
4. DEVELOPER_PORTAL_TEAM_ID - l'ID de votre équipe Developer Portal si vous faites partie de plusieurs équipes.
5. FASTLANE_APPLE_ID - l'Apple ID ou l'e-mail développeur utilisé pour gérer l'app.
6. GIT_USERNAME & GIT_TOKEN - Votre nom d'utilisateur git et votre personal access token.
7. MATCH_PASSWORD - la passphrase définie lors de l'initialisation de match, qui servira à décrypter les certificats et les profils de provisionnement.
8. PROVISIONING_PROFILE_SPECIFIER - match AppStore <YOUR_APP_BUNDLE_IDENTIFIER>, ex. match AppStore com.domain.blabla.demo.
9. TEMP_KEYCHAIN_USER & TEMP_KEYCHAIN_PASSWORD - assignez un utilisateur et un mot de passe keychain temporaires pour votre workflow.
10. APPLE_KEY_ID — App Store Connect API Key 🔺Key ID.
11. APPLE_ISSUER_ID — Clé API App Store Connect 🔺Issuer ID.
12. APPLE_KEY_CONTENT — Clé API App Store Connect 🔺 Fichier de clé ou contenu de la clé de .p8, vérifiez-la
13. CERTIFICATE_STORE_URL — L'URL du repo de vos clés Match (ex : https://github.com/***/fastlane_match.git)
4. Configurez le fichier de workflow GitHub
Créez un répertoire de workflow GitHub.
cd .github/workflows
À l'intérieur du workflow dossier, créez un fichier nommé build-upload-ios.ymlet ajoutez ce qui suit.
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: 2.7.2
- uses: maierj/fastlane-action@v2.3.0
env:
DEVELOPER_APP_IDENTIFIER: ${{ secrets.DEVELOPER_APP_IDENTIFIER }}
DEVELOPER_APP_ID: ${{ secrets.DEVELOPER_APP_ID }}
PROVISIONING_PROFILE_SPECIFIER: match AppStore ${{ secrets.DEVELOPER_APP_IDENTIFIER }}
TEMP_KEYCHAIN_USER: ${{ secrets.TEMP_KEYCHAIN_USER }}
TEMP_KEYCHAIN_PASSWORD: ${{ secrets.TEMP_KEYCHAIN_PASSWORD }}
APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
CERTIFICATE_STORE_URL: https://github.com/${{ secrets.CERTIFICATE_STORE_REPO }}.git
GIT_USERNAME: ${{ secrets.GIT_USERNAME }}
GIT_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
FASTLANE_APPLE_ID: ${{ secrets.FASTLANE_APPLE_ID }}
MATCH_USERNAME: ${{ secrets.FASTLANE_APPLE_ID }}
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
DEVELOPER_PORTAL_TEAM_ID: ${{ secrets.DEVELOPER_PORTAL_TEAM_ID }}
with:
lane: closed_beta
- name: Upload release bundle
uses: actions/upload-artifact@v2
with:
name: ios-release
path: ./App.ipa
retention-days: 60
Ce workflow doit être déclenché après chaque GitHub tag, si vous devez automatiser les tags, veuillez vous référer à Build et release automatiques avec les actions GitHub en premier.
Ensuite, ce workflow récupérera vos dépendances NodeJS, les installera et compilera votre application JavaScript.
À chaque nouveau commit, une release sera générée dans TestFlight.
Votre application n'a pas besoin d'utiliser Ionic, seule la base Capacitor est obligatoire. Elle peut contenir d'anciens modules Cordova, mais l'utilisation du plugin JS Capacitor est recommandée.
5. Déclencher le workflow
Créer un commit
Effectuez un commit, vous devriez voir le workflow actif dans le dépôt.
Déclencher le workflow
Pousser les nouveaux commits sur la branche main ou development pour déclencher le workflow.

Après quelques minutes, le build devrait être disponible dans votre dashboard App Store Connect.

Peut-on déployer depuis une machine locale ?
Oui, c'est possible et sans effort.
Imaginez que vous ayez un dépôt privé, que vous ayez épuisé les minutes du plan gratuit et que vous ne vouliez pas payer pour de nouvelles releases, ou que vous préfériez soumettre l'application manuellement.
C'est parti
Ok, d'abord nous devons créer dans my_project_path/fastlane le chemin d'un fichier nommé .env, directement au même endroit que le Fastfile, pour pouvoir créer les mêmes secrets propriétés que dans notre _GitHub, comme ci-dessous :
fichier .env pour le déploiement local
Maintenant, vous pouvez vous rendre dans le terminal et lancer la commande Fastlane depuis votre machine :
fastlane closed_beta
❌ Point essentiel sur le .env fichier, car nous préférons ne pas exposer ces données, nous devons donc l'ajouter dans notre .gitignore, quelque chose comme ça : ❌
fastlane/*.env
Cela doit fonctionner de la même manière que via les GitHub Actions sur la machine distante, mais sur notre machine locale. 🍻

Exécution dans le terminal : $ Fastlane closed_beta
Si vous êtes arrivé jusqu'ici, félicitations : vous disposez désormais d'un processus entièrement automatisé pour vos apps iOS avec Fastlane et GitHub Actions.
À chaque nouveau commit, une release sera générée sur la console Google Play, dans le canal beta. J'améliorerai cet article grâce à vos retours. Si vous avez des questions ou des suggestions, n'hésitez pas à me contacter par e-mail. martin@capgo.app
Compiler sur votre appareil
Si vous devez encore compiler sur votre appareil, vous devez les ajouter manuellement au profil de provisionnement.
Connectez votre appareil à votre Mac et ouvrez le menu des appareils
Copiez ensuite votre identifiant
Puis lancez la commande :
fastlane register_new_device
il vous sera demandé de définir un nom d'appareil et l'identifiant :

si vous avez des problèmes
Si vous avez un problème avec un appareil de dev impossible à tester, etc., cela le résout généralement.
Il existe une commande magique qui peut vous sauver :
fastlane match nuke development
fastlane match development
Ensuite : Nettoyez le projet en maintenant Shift(⇧)+Command(⌘)+K ou en sélectionnant Product > Clean (il peut être nommé « Clean Build Folder »)
Ensuite, essayez de relancer l'app sur votre appareil.
Merci
Cet article est basé sur les ressources suivantes :
- Livraison continue pour iOS via Fastlane et les actions GitHub
- Documentation Fastlane
- Ce message GitHub de @mrogunlana
Pour aller plus loin : Automatic Capacitor IOS build with GitHub actions using match
Si vous utilisez Build natif Capacitor iOS automatique avec les actions GitHub via match pour planifier l'automatisation CI/CD, le relier à CI/CD Capgo pour le workflow produit dans le CI/CD de Capgo, Capgo Native Build pour le workflow produit dans les Capgo Native Builds, Intégrations Capgo pour le workflow produit dans les intégrations Capgo, Intégration CI/CD pour les détails d'implémentation de l'intégration CI/CD, et Intégration GitHub Actions pour les détails d'implémentation de l'intégration GitHub Actions.