Menyiapkan CI/CD untuk aplikasi Capacitor bisa jadi rumit dan memakan waktu. Berikut yang perlu Anda ketahui:
Direkomendasikan untuk Build Baru: Gunakan Capgo Build
Sekarang kami merekomendasikan penggunaan Capgo Build dengan Capgo CLI untuk build native Capacitor. Panduan Fastlane ini dipertahankan untuk tim yang mengelola pipeline GitHub Actions yang sudah ada, tetapi build iOS baru sebaiknya menggunakan Capgo CLI supaya Anda tidak perlu mengurus Fastlane, Xcode runner, sertifikat, dan skrip upload sendiri.
Capgo Build untuk CI/CD oleh Capgo
Tak perlu lagi maintenance Fastlane, Xcode runner, sertifikat, provisioning profile, dan skrip upload. Capgo Build menjalankan signed native iOS build dari pipeline CI/CD Anda yang sudah ada:
- Kompatibel dengan pipeline Anda: Trigger Capgo Build dari GitHub Actions, GitLab CI, Jenkins, atau script lokal setelah web build Anda dan
npx cap sync. - Signing via CI secrets: Simpan App Store Connect key, sertifikat, provisioning profile, password, dan team ID di CI secrets Anda sendiri.
- Tanpa maintenance native runner: Capgo Build menyediakan environment build Apple yang terkelola, jadi Anda tidak perlu mengelola macOS runner, Xcode image, atau Fastlane lane.
- Artifact dan submission: Download signed artifacts untuk QA atau submit release build melalui Capgo CLI.
Harga
- Paket Capgo mulai dari $12/bulan
- Termasuk OTA updates dan sekitar 15 build native per bulan
- Menit build ekstra ditagih per menit lewat credit
Panduan Setup Manual
Berikut langkah-langkah yang perlu Anda lakukan:
Continuous Delivery untuk iOS menggunakan Fastlane, GitHub Actions, dan sertifikat
Prerequisites
Sebelum melanjutkan tutorial ini:
- Pastikan Fastlane sudah terpasang terinstal di mesin development Anda.
- Pastikan Anda sudah terdaftar sebagai anggota iOS Developer Program.
Informasi penting tentang harga

https://github.com/features/actions
Layanan ini ‘gratis’ sampai batasnya, tergantung mesin yang dipilih.
Kita akan menggunakan macOS mesin, Anda bisa melihat harga dan batasnya di screenshot (harga saat tutorial dibuat, bisa berubah di masa mendatang)
Setelah memahami persyaratan dan harga, mari kita lanjut.
Catatan: Dalam postingan ini, saya berasumsi Anda sudah membuat aplikasi di App Store Connect. Informasi penting akan disalin secara otomatis oleh Fastlane!
Apa yang akan Anda pelajari di tutorial ini
Langkah-langkah dalam postingan ini
- Menggunakan API App Store Connect dengan Fastlane
- Persyaratan:
- Membuat App Store Connect API Key
- Menggunakan App Store Connect API Key
- Persyaratan:
- Salin file Fastlane
- Konfigurasi GitHub Actions
1. Menggunakan API App Store Connect dengan Fastlane
Mulai Februari 2021, autentikasi dua faktor atau verifikasi dua langkah wajib bagi semua pengguna untuk login ke App Store Connect. Lapisan keamanan tambahan untuk Apple ID ini memastikan hanya Anda yang dapat mengakses akun tersebut.
Dari Dukungan Apple
Persyaratan
Agar Fastlane dapat menggunakan App Store Connect API untuk upload aplikasi Anda, Anda perlu menyiapkan tiga hal berikut:
- Issuer ID
- Key ID
- File Key atau isi Key
Cara mendapatkan App Store Connect API Key
Untuk membuat key, Anda harus memiliki izin Admin di App Store Connect. Jika tidak punya izin tersebut, Anda bisa mengarahkan orang yang berwenang ke artikel ini.
-
Login ke App Store Connect.
-
Pilih Pengguna dan Akses.

3 — Pilih tab Integration.

- Klik Generate API Key atau tombol Add (+).

- Masukkan nama untuk key ini. Nama ini hanya untuk referensi Anda dan bukan bagian dari key itu sendiri.

6 — Di bagian Access, pilih role untuk key tersebut. Role yang berlaku untuk key sama dengan role yang berlaku untuk user di tim Anda. Lihat role permissions. Kami menyarankan untuk memilih Manajer aplikasi.
- Klik Generate.
Akses kunci API tidak dapat dibatasi ke aplikasi tertentu.
Nama kunci baru, ID kunci, link download, dan info lainnya akan muncul di halaman.

Anda bisa mendapatkan ketiga informasi penting di sini.
<1> ID Issue. (APPLE_ISSUER_ID secret)
<2> Key ID. (APPLE_KEY_ID secret)
<3> Klik “Download API Key” untuk download private key API Anda. Link download hanya muncul jika private key belum pernah di-download. Apple tidak menyimpan salinan private key tersebut. Jadi, Anda hanya bisa men-download-nya satu kali.
🔴 Simpan private key Anda di tempat yang aman. Jangan pernah membagikan kunci Anda, menyimpan kunci di repositori code, atau menyertakan kunci dalam code client-side.
Menggunakan App Store Connect API Key
File kunci API (file p8 yang Anda unduh), key ID, dan issuer ID diperlukan untuk membuat JWT token otorisasi. Ada beberapa cara untuk memasukkan informasi ini ke Fastlane. Saya memilih menggunakan action baru dari Fastlane app_store_connect_api_key. Anda bisa mempelajari cara lainnya di dokumentasi Fastlane. Saya menunjukkan metode ini karena menurut saya ini cara termudah untuk bekerja dengan kebanyakan CI, di mana Anda bisa mengatur environment variables.
Silakan konversi file p8 yang Anda unduh ke Base64 dan simpan sebagai secret ("APPLE_KEY_CONTENT).
base64 -i APPLE_KEY_CONTENT.p8 | pbcopy
Sekarang kita bisa mengelola App Store Connect dengan Fastlane menggunakan kunci API, mantap!
2. Sertifikat
Buka Xcode dan buka Pengaturan > Akun > Apple ID > Tim dan pilih tim Anda.

Klik pada Kelola sertifikat.
Jika Anda belum membuat sertifikat, Anda bisa membuat sertifikat baru.
Klik pada + dan pilih Distribusi Apple

Kemudian Anda perlu membuka keychain untuk mengunduh sertifikat sebagai a .p12 Anda.
Untuk melakukannya, Anda perlu membuka keychain dan beralih ke login keychain, lalu pilih tab Sertifikat Saya.

Setelah itu, pilih sertifikat yang ingin diunduh. (Cek berdasarkan tanggal sertifikat)
Lalu klik kanan pada private key di sertifikat tersebut dan pilih Ekspor.
Pilih format file Pertukaran Informasi Pribadi (.p12).
Ini akan mengunduh sertifikat sebagai .p12 Anda.
Silakan buka file tersebut di terminal dan gunakan perintah berikut untuk mengubahnya ke Base64:
base64 -i BUILD_CERTIFICATE.p12 | pbcopy
Ini akan menjadi BUILD_CERTIFICATE_BASE64 secret. Selain itu, jika diminta, masukkan juga password sertifikatnya. Password ini akan menjadi P12_PASSWORD secret Anda.
3. Provisioning profiles
Buka Apple Developer dan pilih tim yang sesuai.
Lalu buat profil baru dengan klik +

Dan pilih App Store Connect.

Kemudian Anda perlu memilih aplikasi yang tepat, berhati-hatilah karena Anda tidak bisa menggunakan wildcard atau proses signing akan gagal.

Pilih sertifikat yang tepat yang sudah Anda buat sebelumnya (cek tanggal kedaluwarsanya, harus sesuai dengan hari dan bulan ini) lalu klik Lanjutkan.

Terakhir, masukkan nama profil lalu klik pada Generate.
Nama ini akan digunakan untuk mengidentifikasi profil di Fastlane, di bawah nilai
APPLE_PROFILE_NAME.

Anda dapat mengunduh profil sebagai .mobileprovision Anda.

Harap konversi profil ke Base64 dan simpan sebagai secret (BUILD_PROVISION_PROFILE_BASE64).
base64 -i BUILD_PROVISION_PROFILE.mobileprovision | pbcopy
4. Salin file Fastlane
Fastlane adalah library Ruby yang dibuat untuk mengotomatisasi tugas pengembangan mobile yang umum. Dengan Fastlane, Anda bisa mengonfigurasi “lanes” kustom yang membundel serangkaian “actions” untuk menjalankan tugas yang biasanya dilakukan di Android Studio. Anda bisa melakukan banyak hal dengan Fastlane, namun untuk tutorial ini, kita hanya akan menggunakan beberapa core actions saja.
Buat folder Fastlane di root proyek Capacitor/Ionic Anda dan tambahkan Fastfile di sana:
- Folder:
<project-root>/fastlane/ - File:
<project-root>/fastlane/Fastfile
Ini berada di level yang sama dengan package.json, capacitor.config.*, dan ios/ folder. Jangan buat di dalam 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. Mengatur secrets
GitHub Actions menggunakan repository secrets yang Anda konfigurasi di langkah berikutnya. Anda hanya butuh file .env lokal jika ingin menjalankan atau mengetes Fastlane dari mesin sendiri.
Untuk testing lokal, buat <project-root>/fastlane/.env di sebelah Fastfile. Jangan commit file ini. Tambahkan fastlane/.env ke dalam .gitignore Anda terlebih dahulu (atau pastikan sudah di-ignore). Berikut contohnya:
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=
Cara mendapatkan APP_STORE_CONNECT_TEAM_ID
Buka Pusat Developer dan scroll ke bawah ke Membership details section.
Lalu Team ID adalah nilai yang perlu diatur di APP_STORE_CONNECT_TEAM_ID secret.
Mendapatkan BUNDLE_IDENTIFIER
- Buka Xcode
- Klik dua kali pada
Appdi project navigator - Kemudian klik tab
Signing and Capabilities - Salin nilai dari
Bundle identifier. Ini adalah nilai yang perlu Anda atur diBUNDLE_IDENTIFIERsecret.
6. Pemrosesan Build
Di GitHub Actions, biaya dihitung berdasarkan menit yang Anda gunakan untuk menjalankan workflow CI/CD. Berdasarkan pengalaman saya, butuh sekitar 10–15 menit sebelum build dapat diproses di App Store Connect.
Untuk proyek privat, estimasi biaya per build bisa mencapai $0,08/menit x 15 menit = $1,2, atau lebih, tergantung pada konfigurasi dan dependensi proyek Anda.
Jika Anda khawatir dengan biaya proyek privat, Anda bisa mengatur skip_waiting_for_build_processing ke true. Ini akan menghemat build minutes karena tidak perlu menunggu App Store Connect selesai memproses build.
Namun, ada konsekuensinya — Anda harus memperbarui informasi kepatuhan aplikasi secara manual di App Store Connect sebelum mendistribusikan build ke pengguna.
Optimasi ini terutama berguna untuk proyek privat di mana build minutes berbayar. Untuk proyek publik/gratis, build minutes tersedia gratis sehingga tidak perlu mengaktifkan pengaturan ini. Lihat GitHub di halaman pricing untuk detail lebih lanjut.
7. Setup GitHub Actions
Konfigurasikan secret GitHub
Silakan salin secrets dari .env file dan tempelkan ke repository secrets GitHub.
Buka Pengaturan > Secrets dan variabel > Aksi > Secret repositori baru
2. BUILD_CERTIFICATE_BASE64 - Sertifikat dalam format Base64.
3. BUILD_PROVISION_PROFILE_BASE64 - Provisioning profile dalam format Base64.
4. BUNDLE_IDENTIFIER - Bundle identifier aplikasi Anda.
5. APPLE_KEY_ID — App Store Connect API Key 🔺Key ID.
6. APPLE_ISSUER_ID — App Store Connect API Key 🔺Issuer ID.
7. APPLE_KEY_CONTENT — App Store Connect API Key 🔺 Isi key dari .p8, cek di sini
8. Konfigurasi file workflow GitHub
Buat direktori workflow GitHub.
cd .github/workflows
Di dalam folder workflow , buat file bernama build-upload-ios.ymldan tambahkan kode berikut.
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
Workflow ini akan terpicu setelah setiap GitHub tag, jika Anda perlu mengotomatiskan tag, silakan lihat Build dan release otomatis dengan GitHub actions pertama.
Kemudian workflow ini akan mengambil deps NodeJS Anda, menginstalnya, dan mem-build aplikasi JavaScript Anda.
Setiap kali Anda mengirim commit baru, sebuah release akan di-build di TestFlight.
App Anda tidak wajib menggunakan Ionic, hanya base Capacitor yang wajib. Bisa menggunakan modul Cordova lama, tapi Capacitor JS plugin lebih disarankan.
8. Trigger workflow
Buat commit
Lakukan commit, Anda akan melihat workflow yang aktif di repositori.
Trigger workflow
Push commit baru ke branch main atau development untuk trigger workflow.

Setelah beberapa menit, build seharusnya sudah tersedia di dashboard App Store Connect Anda.

9. Bisa deploy dari mesin lokal?
Ya, bisa, dan sangat mudah.
Anda tetap bisa menggunakan Xcode untuk build dan sign aplikasi Anda.
Artikel Terkait
Panduan Setup CI/CD
- Automatic Capacitor Android Build dengan GitHub Actions - Setup CI/CD Android yang lengkap
- Automatic Build dan Release dengan GitHub Actions - Tutorial lengkap pipeline CI/CD
- Kelola Build Dev dan Prod dengan GitHub Actions - Manajemen environment
- Automatic Capacitor iOS Build dengan Match - Alternatif menggunakan Fastlane Match
Platform CI/CD Alternatif
- Build dengan GitLab CI - Alternatif GitLab
- Build dengan CodeMagic - Panduan setup CodeMagic
Live Updates & Deployment
- Dokumentasi Capgo Live Updates - Tambahkan update OTA ke aplikasi Anda
- Integrasi CI/CD dengan Capgo - Integrasikan live updates ke pipeline Anda
Terima kasih
Blog ini berdasarkan artikel berikut:
- Continuous delivery untuk iOS menggunakan Fastlane dan GitHub actions
- Dokumentasi Fastlane
- Pesan GitHub ini dari @mrogunlana
- Dokumentasi GitHub ini
Lanjutkan dari Automatic Capacitor IOS build dengan GitHub actions dengan sertifikat
Jika Anda menggunakan Build iOS Capacitor otomatis dengan GitHub actions dan sertifikat untuk merencanakan otomatisasi CI/CD, hubungkan dengan CI/CD Capgo untuk workflow produk di Capgo CI/CD, Capgo Native Build untuk workflow produk di Capgo Native Builds, Integrasi Capgo untuk alur kerja produk di Integrasi Capgo, Integrasi CI/CD untuk detail implementasi di Integrasi CI/CD, dan Integrasi GitHub Actions untuk detail implementasi di Integrasi GitHub Actions.