Configurare la CI/CD per le app Capacitor può essere complesso e richiedere tempo. Ecco cosa devi sapere:
Consigliato per le nuove build: usa Capgo Build
Ora consigliamo di usare Capgo Build con Capgo CLI per i build Capacitor nativi. Questa guida su Fastlane è pensata per i team che gestiscono pipeline GitHub Actions esistenti, ma per i nuovi build iOS si consiglia di usare Capgo CLI per evitare di dover gestire manualmente Fastlane, runner Xcode, certificati e script di upload.
Capgo Build per CI/CD con Capgo
Dimentica la manutenzione di Fastlane, runner Xcode, certificati, provisioning profile e script di upload. Build Capgo esegue build iOS nativi firmati dalla tua pipeline CI/CD esistente:
- Si integra con la tua pipeline: Avvia Capgo Build tramite GitHub Actions, GitLab CI, Jenkins o script locali dopo la web build e
npx cap sync. - Firma tramite segreti CI: Mantieni le chiavi di App Store Connect, certificati, provisioning profile, password e team ID nei tuoi segreti CI.
- Nessuna gestione runner native: Capgo Build fornisce ambienti di build Apple gestiti, così non dovrai occuparti di runner macOS, immagini Xcode o lane di Fastlane.
- Artifact e sottomissione: Scarica gli artifact firmati per la QA o invia le release build tramite Capgo CLI.
Prezzi
- I piani Capgo partono da $12/mese
- Include aggiornamenti OTA e circa 15 Native Build al mese
- I minuti extra di build sono fatturati al minuto tramite crediti
Configura Capgo Build in CI/CD
Guida alla configurazione manuale
Ecco cosa devi fare:
Continuous Delivery per iOS con Fastlane, GitHub Actions e certificati
Prerequisiti
Prima di procedere con il tutorial:
- Assicurati di avere Fastlane installato sulla tua macchina di sviluppo.
- Assicurati di far parte del programma per sviluppatori iOS.
Informazioni importanti sul prezzo

https://github.com/features/actions
Il servizio è 'gratuito fino al limite, in base alla macchina scelta.
We are going to use a macOS macchina, puoi vedere lo screenshot con i relativi prezzi e limiti (i prezzi si intendono quelli al momento del tutorial e potrebbero variare in futuro)
Una volta chiariti requisiti e costi, procediamo.
Nota: in questo post assumo che l'app sia già stata creata su App Store Connect. Fastlane copierà automaticamente le informazioni necessarie!
Cosa imparerai in questo tutorial
Passaggi da seguire nel post
- Usare API di App Store Connect con Fastlane
- Requisiti:
- Creazione di una API Key per App Store Connect
- Utilizzo di una chiave API di App Store Connect
- Requisiti:
- Copia i file di Fastlane
- Configura le GitHub Actions
1. Usare API di App Store Connect con Fastlane
A partire da febbraio 2021, l'autenticazione a due fattori o la verifica in due passaggi è obbligatoria per tutti gli utenti che effettuano l'accesso ad App Store Connect. Questo livello di sicurezza extra per il tuo Apple ID garantisce che solo tu possa accedere al tuo account.
Da Supporto Apple
Requisiti
Per consentire a Fastlane di utilizzare API di App Store Connect per caricare la tua app, devi fornire quanto segue tre elementi:
- ID dell'emittente
- ID chiave
- File della chiave o contenuto della chiave
Come ottenere una chiave API di App Store Connect
Per generare le chiavi, devi avere i permessi di Admin in App Store Connect. Se non hai tale permesso, puoi indirizzare la persona responsabile a questo articolo.
-
Accedi a App Store Connect.
-
Seleziona Utenti e accesso.

3 — Seleziona la scheda Integrazioni.

- Clicca su Generate API Key o sul pulsante Add (+).

- Inserisci un nome per la chiave. Il nome serve solo come riferimento e non fa parte della chiave stessa.

Alla voce Access, seleziona il ruolo per la chiave. I ruoli validi per le chiavi sono gli stessi degli utenti del tuo team. Consulta permessi dei ruoli. Ti consigliamo di selezionare App Manager.
- Clicca su Generate.
L'accesso di una chiave API non può essere limitato a singole app.
Nella pagina compaiono il nome della nuova chiave, il key ID, il link per il download e altre informazioni.

Qui puoi recuperare tutte e tre le informazioni necessarie.
<1> Issue ID. (APPLE_ISSUER_ID secret)
<2> Key ID. (APPLE_KEY_ID secret)
<3> Clicca su “Download API Key” per scaricare la tua API private key. Il link per il download compare solo se la private key non è ancora stata scaricata. Apple non conserva una copia della private key. Quindi puoi scaricarla una sola volta.
🔴 Conserva la tua private key in un luogo sicuro. Non condividere mai le chiavi, non salvarle in un repository code e non includerle nel code lato client.
Usare una API Key di App Store Connect
Il file API Key (il file p8 che scarichi), la key ID e l'issuer ID sono necessari per creare il token JWT per l'autorizzazione. Ci sono diversi modi per passare queste informazioni a Fastlane. Io ho scelto di usare la nuova action di Fastlane app_store_connect_api_key. Puoi scoprire altri modi nella documentazione di Fastlane. Ti mostro questo metodo perché credo sia il modo più semplice per lavorare con la maggior parte delle CI, dove puoi impostare variabili d'ambiente.
Converti il file p8 scaricato in Base64 e salvalo come secret ("APPLE_KEY_CONTENT).
base64 -i APPLE_KEY_CONTENT.p8 | pbcopy
Ora possiamo gestire App Store Connect con Fastlane usando la API key, ottimo!
2. Certificati
Apri Xcode e vai su Impostazioni > Account > Apple ID > Team e seleziona il tuo team.

Clicca su Gestisci certificati.
Se non hai ancora creato un certificato, puoi crearne uno nuovo.
Clicca su + e selezionare Distribuzione Apple

Poi devi andare su Keychain per scaricare il certificato come .p12 file.
Per farlo, devi andare su keychain e passare a login keychain, quindi vai sulla scheda I miei certificati.

Quindi puoi selezionare il certificato che desideri scaricare. (Cerca in base alla data del certificato)
Infine, fai clic destro sulla chiave privata del certificato e seleziona Esporta.
Scegli il formato del file Scambio informazioni personali (.p12).
Questo scaricherà il certificato come un .p12 file.
Apri il file in un terminale e usa il seguente comando per convertirlo in Base64:
base64 -i BUILD_CERTIFICATE.p12 | pbcopy
Questo diventerà il tuo BUILD_CERTIFICATE_BASE64 segreto. Inoltre, quando richiesto, inserisci la password del certificato. Questa password sarà la tua P12_PASSWORD secret.
3. Provisioning profiles
Apri Apple Developer e seleziona il team corretto.
Poi crea un nuovo profilo cliccando su +

E seleziona App Store Connect.

Poi devi selezionare l'app corretta; fai attenzione a non usare i wildcard, altrimenti la firma fallirà.

Seleziona il certificato creato in precedenza (controlla la data di scadenza, deve essere lo stesso giorno e mese di oggi) e clicca su Continua.

Infine inserisci il nome del profilo e clicca su Genera.
Il nome verrà utilizzato per identificare il profilo in Fastlane, sotto il valore
APPLE_PROFILE_NAME.

Puoi scaricare il profilo come .mobileprovision file.

Converti il profilo in Base64 e salvalo come secret (BUILD_PROVISION_PROFILE_BASE64).
base64 -i BUILD_PROVISION_PROFILE.mobileprovision | pbcopy
4. Copia i file di Fastlane
Fastlane è una libreria Ruby creata per automatizzare i comuni task di sviluppo mobile. Con Fastlane puoi configurare "lanes" personalizzate che raggruppano una serie di "actions" per eseguire operazioni che normalmente faresti su Android Studio. Puoi fare moltissimo con Fastlane, ma per questo tutorial useremo solo alcune azioni core.
Crea la cartella Fastlane nella root del tuo progetto Capacitor/Ionic e aggiungi il Fastfile lì:
- Cartella:
<project-root>/fastlane/ - File:
<project-root>/fastlane/Fastfile
Si trova allo stesso livello di package.json, capacitor.config.*, e il ios/ cartella. Non crearlo all'interno di 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. Configurazione dei secrets
GitHub Actions utilizza i repository secrets che configurerai nel passaggio successivo. Ti serve solo un file .env locale se vuoi eseguire o testare Fastlane dalla tua macchina.
Per i test locali, crea <project-root>/fastlane/.env accanto a Fastfile. Non fare il commit di questo file. Aggiungi fastlane/.env al tuo .gitignore prima (o verifica che sia già ignorato). Ecco un esempio:
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=
Recuperare l'APP_STORE_CONNECT_TEAM_ID
Vai su Developer Center e scorri verso il basso fino a Membership details sezione.
Il Team ID è il valore da impostare nel APP_STORE_CONNECT_TEAM_ID secret.
Recuperare il BUNDLE_IDENTIFIER
- Apri Xcode
- Fai doppio clic su
Appnel project navigator - Poi clicca sulla tab
Signing and Capabilities - Copia il valore di
Bundle identifier. Questo è il valore da impostare nelBUNDLE_IDENTIFIERsecret.
6. Elaborazione Build
Nelle GitHub Actions, la fatturazione avviene in base ai minuti utilizzati per eseguire il tuo workflow CI/CD. Per esperienza, occorrono circa 10–15 minuti prima che una build venga elaborata in App Store Connect.
Per i progetti privati, il costo stimato per build può arrivare a $0.08/min x 15 min = $1.2, o anche di più, a seconda della configurazione e delle dipendenze del progetto.
Se vuoi monitorare i costi per i progetti privati, puoi impostare skip_waiting_for_build_processing a true. Questo ti farà risparmiare minuti di build, evitando di attendere il completamento dell'elaborazione su App Store Connect.
Tuttavia, c'è un compromesso: dovrai aggiornare manualmente le informazioni sulla conformità della tua app in App Store Connect prima di distribuire la build agli utenti.
Questa ottimizzazione è utile soprattutto per i progetti privati dove i minuti di build hanno un costo. Per i progetti pubblici o gratuiti, i minuti di build sono gratuiti, quindi non è necessario attivare questa impostazione. Consulta la pagina dei prezzi di GitHub pagina dei prezzi per maggiori dettagli.
7. Configura le GitHub Actions
Configura i secret di GitHub
Please copy the secrets from the .env file e incollali nei secret del repository di GitHub.
Vai su Impostazioni > Secret e variabili > Azioni > Nuovo secret del repository
2. BUILD_CERTIFICATE_BASE64 - Certificato codificato in Base64.
3. BUILD_PROVISION_PROFILE_BASE64 - Provisioning profile codificato in Base64.
4. BUNDLE_IDENTIFIER - Il bundle identifier della tua app.
5. APPLE_KEY_ID — API Key di App Store Connect 🔺Key ID.
6. APPLE_ISSUER_ID — API Key di App Store Connect 🔺Issuer ID.
7. APPLE_KEY_CONTENT — Chiave API di App Store Connect 🔺 Contenuto della chiave: .p8, verificala
8. Configura il file di workflow GitHub
Crea una directory GitHub workflow.
cd .github/workflows
All'interno della workflow cartella, crea un file chiamato build-upload-ios.ymle aggiungi quanto segue.
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
Questo workflow dovrebbe essere attivato dopo ogni GitHub tag, se hai bisogno di automatizzare i tag, consulta Build e release automatiche con le action GitHub prima.
Successivamente, questo workflow scaricherà le dipendenze NodeJS, le installerà e farà il build della tua app JavaScript.
Ogni volta che invii un nuovo commit, verrà generata una release in TestFlight.
La tua App non deve usare Ionic, è obbligatorio solo il base di Capacitor; può avere vecchi moduli Cordova, ma è preferibile usare il plugin JS di Capacitor.
8. Avvia il workflow
Crea un commit
Esegui un commit, dovresti vedere il workflow attivo nel repository.
Avvia il workflow
Pusha i nuovi commit sul branch main o development per attivare la workflow.

Dopo pochi minuti, il build dovrebbe essere disponibile nella dashboard di App Store Connect.

9. Posso fare il deploy dalla mia macchina locale?
Sì, è possibile e non richiede alcuno sforzo.
Puoi usare Xcode per buildare e firmare la tua app, come sempre.
Articoli correlati
Guide al setup CI/CD
- Automatic Capacitor Android Build con GitHub Actions - Setup completo CI/CD Android
- Automatic Build e Release con GitHub Actions - Tutorial completo sulla pipeline CI/CD
- Gestisci build Dev e Prod con GitHub Actions - Gestione degli ambienti
- Build iOS Capacitor automatica con Match - Alternativa con Fastlane Match
Alternative piattaforme CI/CD
- Build con GitLab CI - Alternativa GitLab
- Build con CodeMagic - Guida al setup di CodeMagic
Live Update & Deployment
- Documentazione Capgo Live Updates - Aggiungi aggiornamenti OTA alla tua app
- Integrazione CI/CD con Capgo - Integra i live updates nella tua pipeline
Grazie
Questo blog si basa sui seguenti articoli:
- Continuous delivery per iOS con Fastlane e le action GitHub
- Documentazione Fastlane
- Questo messaggio GitHub di @mrogunlana
- Questa documentazione GitHub
Continua da Automatic Capacitor iOS build con le action GitHub e certificato
Se stai usando Build automatica di Capacitor iOS con GitHub actions e certificato per pianificare l'automazione CI/CD e connetterla a CI/CD con Capgo per il workflow del prodotto in Capgo CI/CD, Capgo Native Build per il workflow di prodotto in Capgo Native Builds, Integrazioni Capgo per il workflow di prodotto in Integrazioni Capgo, Integrazione CI/CD per i dettagli implementativi in CI/CD Integration, e Integrazione GitHub Actions per i dettagli implementativi in GitHub Actions Integration.