Panduan

Menyiapkan CI/CD iOS di GitHub Actions dari nol

Ini seluruh pipeline untuk aplikasi iOS di GitHub Actions, sesuai urutan Anda membangunnya. Kompilasi dan test dulu. Lalu signing. Lalu archive dan upload. Setiap langkahnya kecil dan YAML-nya siap disalin. Pipeline ini berjalan di runner hosted GitHub maupun di Mac khusus. Satu-satunya baris yang berubah adalah runs-on.

1. Kerangkanya

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. Pilih Xcode

Image hosted membawa beberapa versi Xcode. Pilih satu secara eksplisit, agar update image tidak mengubah build Anda diam-diam:

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

Di Mac khusus, versinya dikunci sekali di mesin dan langkah ini tidak diperlukan lagi.

3. Dependensi

      - 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 dan test di simulator

      - 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 }

Untuk pull request, berhenti di sini. Semua di bawah ini adalah pekerjaan rilis dan cukup dijalankan di main.

5. Code signing tanpa login Mac bersama

Pakai API key App Store Connect, bukan Apple ID. Simpan key ID, issuer ID, dan isi file .p8 sebagai secret repository, lalu biarkan xcodebuild melakukan signing dengan profile yang dikelola 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. Export dan upload ke 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 }}"

Banyak tim membungkus langkah 5 dan 6 dengan fastlane. Perintah yang berjalan di baliknya tetap sama.

7. Ke mana menit habis, dan pilihan runner

Di runner hosted, langkah 2 dan 3 terulang di setiap job dan ditagih sekitar $0.062 sampai $0.102 per menit. Di Mac khusus, keduanya terjadi sekali dan cache tetap hangat. Karena itu tim yang melewati sekitar 2,242 menit sebulan memindahkan seluruh pipeline ke mesin berharga tetap. Mereka hanya mengubah baris runs-on. Panduan pipeline di hardware khusus membahas sisi itu.

Pertanyaan yang sering diajukan

Apakah saya butuh Mac untuk menjalankan CI iOS di GitHub Actions?

+

Ya. Build dan signing aplikasi iOS butuh Xcode, dan Xcode hanya berjalan di macOS. Jadi job build butuh runner macOS, entah yang di-hosting GitHub atau Mac yang Anda kendalikan.

Bagaimana cara signing aplikasi iOS di CI tanpa Apple ID saya?

+

Buat API key App Store Connect, simpan ID, issuer ID, dan isi file .p8 sebagai secret, lalu teruskan ke xcodebuild dengan -allowProvisioningUpdates. Runner tidak butuh Apple ID atau password keychain.

Haruskah test berjalan di setiap pull request?

+

Build dan test di setiap pull request dengan satu simulator. Archive, signing, dan upload ke TestFlight cukup di main. Langkah-langkah itu yang lambat dan mahal.

Apa yang berubah saat saya memindahkan pipeline ini ke Mac khusus?

+

Baris runs-on. Pemilihan Xcode dan cache dependensi tidak diperlukan lagi karena mesin menyimpannya di antara job, dan tidak ada antrean di depan build.

Panduan terkait