SuperAPI AI Directory

github-actions-ios

Deployment & operations

View repository

Updated 10-16 11:55

About this skill

GitHub Actions — iOS (TestFlight / App Store)

CI genérico: github-actions. Aqui: code sign, archive e App Store Connect. UI: swiftui-development. Testes: swift-testing. Android: github-actions-android.

Detecte nativo (Xcode/fastlane) vs Expo (eas.json). Runners macOS são caros — jobs curtos e cache.

Regras inegociáveis

  • Sem .p12, .mobileprovision ou .p8 no git. Secrets: API Key e (se Match) credenciais do repo de certs.
  • Preferência: App Store Connect API Key (AUTHKEY_P8, ASC_KEY_ID, ASC_ISSUER_ID) — não Apple ID + senha/app-specific no YAML.
  • TestFlight antes de App Store. Prod (deliver / submit review) com environment: production + reviewer.
  • Scheme e CODE_SIGN_STYLE alinhados ao perfil Distribution (App Store), não Development no job de upload.
  • macos-latest ou a imagem que pinna o Xcode do xcode-version do projeto.

CI (nativo)

jobs:
  test:
    runs-on: macos-latest
    permissions: { contents: read }
    timeout-minutes: 45
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: ~/Library/Developer/Xcode/DerivedData
          key: dd-${{ hashFiles('**/*.xcodeproj/**', '**/Package.resolved', '**/Podfile.lock') }}
      - run: xcodebuild test -scheme App -destination 'platform=iOS Simulator,name=iPhone 16' -quiet
  • Unitários / Swift Testing no Simulator. XCUITest só no caminho crítico ou workflow_dispatch — flaky e lento (swift-testing).
  • SPM: cache SourcePackages se o setup já não cobrir. CocoaPods: pod install + cache Pods se o repo usa Pods.
  • xcode-select -s quando a imagem tiver vários Xcodes.

Assinatura

Método Quando
API Key + Fastlane Match Time; certs num repo/S3 privado
Import keychain Cert + profile em secrets (base64) — último recurso
Xcode Cloud Se o produto já estiver lá — não force GHA

Match:

  • MATCH_PASSWORD, MATCH_GIT_URL (ou S3), APP_STORE_CONNECT_API_KEY_*.
  • match appstore no job de release; readonly: true no CI para não rotacionar cert a cada run.
  • create-keychain / setup_ci do Fastlane no runner (keychain temporário).

Nunca CODE_SIGNING_ALLOWED=NO no archive de loja.

Archive e upload

deploy-testflight:
  needs: test
  if: github.ref == 'refs/heads/main' && github.event_name == 'push'
  runs-on: macos-latest
  environment: testflight
  timeout-minutes: 90
  steps:
    - uses: actions/checkout@v4
    # match + gym + pilot (ou xcodebuild archive + altool/notary)
  • Fastlane: gym (archive) → pilot / upload_to_testflight. Skip waiting for processing se o time já tiver hook.
  • Sem Fastlane: xcodebuild -archivePath + xcodebuild -exportArchive + xcrun altool / notarytool / iTMSTransporter — o que o repo já usa.
  • Export options: method: app-store, team ID correto.
  • Artifact: IPA em upload-artifact retenção curta.

App Store (review)

  • Job separado, environment: production, não em todo merge.
  • Metadata/deliver só se o time versionar screenshots/notes; senão upload binário + review manual no Console.
  • Build number (CFBundleVersion) sempre sobe (agvtool, Fastlane increment_build_number, ou GITHUB_RUN_NUMBER documentado).

Expo / React Native

  • EXPO_TOKEN; eas build --platform ios + eas submit --platform ios.
  • Credenciais iOS no EAS (não duplicar Match + EAS no mesmo app sem dono).
  • Profile production → TestFlight primeiro.

Custo e flakiness

  • timeout-minutes em todo job macOS.
  • concurrency no workflow de deploy (um archive por vez).
  • Não rode matrix de 4 Simulators no PR.

Anti-padrões

  • Apple ID e senha no fastlane env
  • Certificado Development no submit
  • xcodebuild sem -destination / scheme errado
  • Submit App Store em todo push
  • Commit de AuthKey_*.p8
  • UI tests como gate único do merge (sem unit)

Integração com outras skills

  • Pipeline: github-actions
  • App: swiftui-development
  • Testes: swift-testing
  • Android: github-actions-android
  • Widgets no mesmo IPA: widgetkit (mesmo archive)
  • Go-live: production-readiness

Critérios de conclusão

  • Testes de unit no Simulator no PR
  • Archive Distribution assinado via API Key / Match (secrets)
  • Upload TestFlight (prod protegido)
  • Build number crescente
  • Sem certs no git; timeout no job macOS