Salta al contenuto principale
CI/CD

Build automatica di Capacitor iOS con GitHub actions e certificato

Come configurare una pipeline CI/CD per la tua app Ionic su iOS con fastlane e GitHub Actions in 5 min (2024)

Build automatica di Capacitor iOS con GitHub actions e certificato

Configurare la CI/CD per le app Capacitor può essere complesso e richiedere tempo. Ecco cosa devi sapere:

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

Prezzo GitHub Action

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

  1. 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
  2. Copia i file di Fastlane
  3. 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:

  1. ID dell'emittente
  2. ID chiave
  3. 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.

  1. Accedi a App Store Connect.

  2. Seleziona Utenti e accesso.

Accesso utenti in App Store Connect

3 — Seleziona la scheda Integrazioni.

Integrazione API di App Store Connect

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

Creazione chiavi API in App Store Connect

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

Nome della chiave API in App Store Connect

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.

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

Download delle chiavi da App Store Connect

Qui puoi recuperare tutte e tre le informazioni necessarie.
<1> Issue ID. (APPLE_ISSUER_ID secret)
&lt;2&gt; Key ID. (APPLE_KEY_ID secret)
&lt;3&gt; 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 &gt; Account &gt; Apple ID &gt; Team e seleziona il tuo team.

identità di firma Code

Clicca su Gestisci certificati.

Se non hai ancora creato un certificato, puoi crearne uno nuovo.

Clicca su + e selezionare Distribuzione Apple

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.

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 +

Crea un nuovo profilo

E seleziona App Store Connect.

Seleziona App Store Connect

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

Seleziona l'app corretta

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

Seleziona il certificato corretto

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.

Genera il profilo

Puoi scaricare il profilo come .mobileprovision file.

Scarica il profilo

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.

app-store-connect-team-id

Recuperare il BUNDLE_IDENTIFIER

  1. Apri Xcode
  2. Fai doppio clic su App nel project navigator
  3. Poi clicca sulla tab Signing and Capabilities
  4. Copia il valore di Bundle identifier. Questo è il valore da impostare nel BUNDLE_IDENTIFIER secret.
bundle-identifier-xcode

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 &gt; Secret e variabili &gt; Azioni &gt; Nuovo secret del repository

github-secrets

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.

Avviato con il commit

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

Dashboard Testflight

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.

Guide al setup CI/CD

Alternative piattaforme CI/CD

Live Update &amp; Deployment

Grazie

Questo blog si basa sui seguenti articoli:

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.

Live updates per le app Capacitor

Quando un bug nel web-layer è live, rilascia la fix tramite Capgo invece di aspettare giorni l'approvazione degli store. Gli utenti ricevono l'update in background, mentre le modifiche native restano nel normale processo di review.

Ultimi articoli dal blog

Capgo ti offre gli insight migliori che ti servono per creare un'app mobile davvero professionale.