Guida

Configurare da zero la CI/CD iOS su GitHub Actions

Questa è l’intera pipeline per un’app iOS su GitHub Actions, nell’ordine in cui la costruisci. Prima compilazione e test. Poi la firma. Poi archivio e upload. Ogni passo è piccolo e lo YAML è pronto da copiare. Funziona sui runner ospitati da GitHub e su un Mac dedicato. L’unica riga che cambia è runs-on.

1. La struttura

name: ios
on:
  pull_request:
  push:
    branches: [main]
concurrency:
  group: ios-${{ github.ref }}
  cancel-in-progress: true
jobs:
  build:
    runs-on: macos-latest      # or [self-hosted, macOS, your-label]
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4

2. Scegli Xcode

Le immagini ospitate includono diverse versioni di Xcode. Scegline una in modo esplicito, così un aggiornamento dell’immagine non cambia la build a tua insaputa:

      - run: sudo xcode-select -s /Applications/Xcode_26.6.app
      - run: xcodebuild -version

Su un Mac dedicato la versione si fissa una volta sulla macchina, e questo step sparisce.

3. Dipendenze

      - uses: actions/cache@v4
        with:
          path: |
            ~/Library/Caches/org.swift.swiftpm
            Pods
          key: ${{ runner.os }}-deps-${{ hashFiles('**/Package.resolved', '**/Podfile.lock') }}
      - run: pod install --repo-update   # CocoaPods projects only

4. Build e test su un simulatore

      - run: |
          xcodebuild test \
            -scheme MyApp \
            -destination 'platform=iOS Simulator,name=iPhone 17' \
            -resultBundlePath TestResults \
            | xcpretty
      - uses: actions/upload-artifact@v4
        if: failure()
        with: { name: test-results, path: TestResults }

Per le pull request fermati qui. Tutto ciò che segue è lavoro di rilascio e va solo su main.

5. Firma del codice senza un login Mac condiviso

Usa una API key di App Store Connect invece di un Apple ID. Salva l’ID della chiave, l’issuer ID e il contenuto del file .p8 come secret del repository. Poi lascia che xcodebuild firmi con profili gestiti nel cloud:

      - run: echo "${{ secrets.ASC_KEY_P8 }}" > AuthKey.p8
      - run: |
          xcodebuild archive \
            -scheme MyApp -configuration Release \
            -archivePath build/MyApp.xcarchive \
            -allowProvisioningUpdates \
            -authenticationKeyPath "$PWD/AuthKey.p8" \
            -authenticationKeyID "${{ secrets.ASC_KEY_ID }}" \
            -authenticationKeyIssuerID "${{ secrets.ASC_ISSUER_ID }}"

6. Esporta e carica su TestFlight

      - run: |
          xcodebuild -exportArchive \
            -archivePath build/MyApp.xcarchive \
            -exportPath build/export \
            -exportOptionsPlist ExportOptions.plist \
            -allowProvisioningUpdates \
            -authenticationKeyPath "$PWD/AuthKey.p8" \
            -authenticationKeyID "${{ secrets.ASC_KEY_ID }}" \
            -authenticationKeyIssuerID "${{ secrets.ASC_ISSUER_ID }}"
      - run: |
          xcrun altool --upload-app -f build/export/MyApp.ipa -t ios \
            --apiKey "${{ secrets.ASC_KEY_ID }}" --apiIssuer "${{ secrets.ASC_ISSUER_ID }}"

Molti team mettono i passi 5 e 6 dentro fastlane. I comandi sotto sono gli stessi.

7. Dove finiscono i minuti, e la scelta del runner

Su un runner ospitato, i passi 2 e 3 si ripetono a ogni job e si pagano circa da $0.062 a $0.102 al minuto. Su un Mac dedicato avvengono una volta e le cache restano calde. Per questo i team che superano circa 2,242 minuti al mese spostano l’intera pipeline su una macchina a prezzo fisso. Cambiano solo la riga runs-on. La guida alla pipeline su hardware dedicato copre quella parte.

Domande frequenti

Mi serve un Mac per la CI iOS su GitHub Actions?

+

Sì. Compilare e firmare app iOS richiede Xcode, che gira solo su macOS. Il job di build ha quindi bisogno di un runner macOS, ospitato da GitHub o un Mac che controlli tu.

Come firmo un’app iOS in CI senza il mio Apple ID?

+

Crea una API key di App Store Connect. Salva il suo ID, l’issuer ID e il contenuto del .p8 come secret, e passali a xcodebuild con -allowProvisioningUpdates. Sul runner non servono né un Apple ID né la password del portachiavi.

I test devono girare su ogni pull request?

+

Compila e testa su ogni pull request con un solo simulatore. Archivio, firma e upload su TestFlight tienili solo su main. Sono gli step lenti e costosi.

Cosa cambia quando sposto questa pipeline su un Mac dedicato?

+

La riga runs-on. Scelta di Xcode e cache delle dipendenze non servono più, perché la macchina le conserva tra un job e l’altro. E davanti alla build non c’è nessuna coda.

Guide correlate