Sebagian besar kesalahan CI/CD untuk Capacitor disebabkan oleh daftar singkat: tanda tangan iOS code yang hilang, alat macOS yang tidak lengkap atau ketinggalan zaman, pembangunan web yang tidak pernah masuk ke proyek native, nomor pembangunan yang digunakan kembali, dan persyaratan toko yang gagal hanya pada saat unggah.
Jika Anda sedang mengatur pipeline dari awal, baca Setting up CI/CD untuk Capacitor apps pertama, kemudian gunakan daftar ini untuk memperkuatnya.
Stage 1: Membangun layer web
Pitfall: aplikasi native mengirimkan pembangunan web yang lama
Gejala: Sukses CI, aplikasi terinstal, tapi menampilkan UI kemarin.
Penyebab: cap sync mengambil apa saja yang ada di webDir Saat itu. Jika pipeline dijalankan cap sync sebelum build web, atau build web menulis ke folder yang berbeda dari webDir di capacitor.config.tsprojek native menjadi ketinggalan file.
Solusi: selalu jalankan langkah-langkah dalam urutan ini, dan gagal jika folder keluaran kosong.
bun install --frozen-lockfile
bun run build
test -f dist/index.html || { echo "web build missing"; exit 1; }
bunx cap sync
Pastikan webDir sesuai dengan output bundler Anda (dist untuk Vite, www untuk Angular dengan Ionic, build untuk beberapa pengaturan React).
Pitfall: URL server pengembang ditinggalkan di konfigurasi
Gejala: hasil rilis menampilkan layar kosong atau mencoba memuat http://192.168.x.x:5173.
Penyebab: server.url dalam capacitor.config.ts ditetapkan untuk reload hidup dan dikomit.
Fix: tidak pernah komit server.url. Baca dari variabel lingkungan yang dibaca oleh CI:
import type { CapacitorConfig } from '@capacitor/cli'
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'Example',
webDir: 'dist',
...(process.env.LIVE_RELOAD_URL && {
server: { url: process.env.LIVE_RELOAD_URL, cleartext: true },
}),
}
export default config
Pitfall: variabel lingkungan dibakar pada waktu yang salah
Gejala: Produksi aplikasi berbicara dengan API pengujian.
Penyebab: Vite, webpack, dan Angular mengatur variabel lingkungan secara langsung pada saat build. Nilai yang ada ketika bun run build ran adalah satu di dalam binary, dan di setiap live update yang dibangun dari pekerjaan yang sama.
Fix: Atur variabel-variabel spesifik lingkungan sebelum melakukan build web, per pekerjaan, dan buat bundle terpisah untuk tahap pengujian dan produksi. Jangan mencoba menggantinya setelahnya. cap sync.
Pitfall: perbedaan file lock
Gejala: Versi plugin di CI tidak sama dengan yang ada di mesin Anda, dan kompilasi asli gagal karena simbol yang hilang.
Fix: commit file lock dan instal dengan bun install --frozen-lockfile (atau npm ci). Pin @capacitor/core, @capacitor/ios, @capacitor/android, dan @capacitor/cli ke versi yang sama. Versi yang tidak sesuai sering menyebabkan kesalahan asli; lihat Fix Capacitor versi kesalahan yang tidak sesuai.
Langkah 2: Alat toolchain asli
Pitfall: versi Node, JDK, atau Xcode yang salah
Gejala: Unsupported class file major version, The engine "node" is incompatible, atau kesalahan Xcode tentang SDK fitur.
Penyebab: runner yang dihosting mengubah gambar, dan Capacitor 8 memiliki minimum yang ketat.
| Alat | Capacitor 8 requirement |
|---|---|
| Node.js | 22 atau lebih baru |
| JDK | 21 |
| Xcode | 26 atau lebih baru |
| Target pengembangan iOS | 15.0 |
Android minSdkVersion / targetSdkVersion |
24 / 36 |
Fix: pastikan setiap versi secara eksplisit di pipeline daripada mengandalkan latest:
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '26'
Pitfall: membangun terhadap Xcode Apple yang tidak lagi menerima
Gejala: kesalahan unggah dengan pesan bahwa aplikasi dibangun dengan SDK yang tidak didukung.
Cause: sejak 28 April 2026, App Store Connect memerlukan Xcode 26 dan iOS 26 SDK. Mesin Mac yang self-host dan gambar runner yang lebih tua masih menggunakan Xcode 16.
Fix: pilih macos-26 gambar atau instal Xcode 26 pada runner Anda. Detail dalam Persyaratan Xcode 26 Apple untuk Capacitor aplikasi.
Kesalahan: kebingungan CocoaPods dan SPM
Gejala: xcodebuild: error: 'App.xcworkspace' does not exist, atau pod tidak ditemukan.
Cause: projek Capacitor baru 8 menggunakan Manajer Paket Swift dan dibangun ios/App/App.xcodeproj. Projek yang lebih tua menggunakan CocoaPods dan membangun ios/App/App.xcworkspace setelah pod install. Pipelines yang dicopy dari tutorial yang lebih tua mengasumsikan workspace.
Fix: periksa mana yang digunakan oleh projek Anda dan bangun file yang tepat. Jika Anda sedang melakukan migrasi, lihat Bagaimana cara migrasi aplikasi Capacitor Anda ke SPM.
Pitfall: Plugin Android membangun break setelah upgrade Gradle
Gejala: Namespace not specified, package attribute is deprecated, atau kesalahan dari plugin’s build.gradle setelah memperbarui Android Studio.
Fix: tahan Android Gradle Plugin di android/build.gradle, upgrade di cabang, dan update plugin terlebih dahulu. Kesalahan spesifik dibahas dalam Perbaiki kesalahan pembangunan plugin Capacitor dengan AGP 9.
Langkah 3: Code signing
Kebijakan: Tanda tangan iOS hanya berfungsi di Mac Anda
Gejala: No signing certificate "iOS Distribution" found, No profiles for 'com.example.app' were found, atau errSecInternalComponent.
Pemicu: Kunci Mac Anda menyimpan sertifikat dan Xcode mengunduh profil untuk Anda. Runner CI tidak memiliki kunci tersebut, dan kunci Mac Anda terkunci dalam sesi non-interaktif.
Perbaiki: Import sertifikat ke kunci sementara yang tidak terkunci dan instal profil di mana Xcode 16 dan versi yang lebih baru mencari:
security create-keychain -p "$KEYCHAIN_PASSWORD" ci.keychain
security set-keychain-settings -lut 21600 ci.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" ci.keychain
security import dist.p12 -k ci.keychain -P "$P12_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" ci.keychain
security list-keychains -d user -s ci.keychain login.keychain
PROFILES="$HOME/Library/Developer/Xcode/UserData/Provisioning Profiles"
mkdir -p "$PROFILES"
cp app.mobileprovision "$PROFILES/"
Pilih nama identitas Apple Distribution, bukan versi lama iOS Distributionfastlane’s setup_ci plus match automates this. Capgo Build takes the certificate and profile as environment variables and does the keychain work on its own machines, so the Linux job never touches security.
Bahaya: sertifikat yang telah kedaluwarsa atau dibatalkan
Symptom: suatu aliran yang berfungsi selama setahun gagal secara mendadak.
Cause: Apple distribution certificates and provisioning profiles expire after a year. A teammate creating a new certificate in Xcode can also invalidate the profile your CI uses.
Fix: Tetapkan tanggal kedaluwarsa di kalender tim Anda, gunakan satu sertifikat distribusi bersama untuk CI, dan periksa sebelum membangun. bunx @capgo/cli@latest build prescan --platform ios memeriksa kedaluwarsa sertifikat, kata sandi, dan pairing profil sebelum apa pun diunggah.
Kebijakan: Logins ID Apple dan Prompt Kedua Faktor
Gejala: fastlane mengalami keterlambatan menunggu kode code 6 digit.
Pembetulan: gunakan kunci App Store Connect API (".p8, key ID, issuer ID) instead of an Apple ID and password. It does not require two-factor authentication and can be scoped to App Manager. If authentication still fails with a correct key, check the runner clock: the token is signed with the local time, and Apple rejects tokens with a skewed timestamp.
Kebijakan: rahasia base64 yang tidak dapat diuraikan
Gejala: MAC verification failed, invalid keystore formatPenyebab: base64: invalid input.
Cause: dihasilkan dengan OpenSSL 3 default yang tidak dapat dibaca oleh macOS. .p12 Dibuat dengan OpenSSL 3 default yang tidak dapat dibaca oleh macOS.
Pembetulan: kodekan pada satu baris, dan gunakan -legacy ketika membuat sebuah .p12 dengan OpenSSL 3:
base64 -i dist.p12 | tr -d '\n' > dist.p12.b64
openssl pkcs12 -export -legacy -inkey key.pem -in cert.pem -out dist.p12
Pitfall: keystore Android hilang
Gejala: anda tidak dapat menandatangani pembaruan karena tidak ada yang memiliki keystore.
Fix: dengan Play App Signing, keystore adalah kunci unggah, dan dukungan Play Console dapat mendaftarkan satu baru. Simpan keystore di rahasia CI Anda dan di cadangan offline. Jangan biarkan hidup hanya di satu laptop. The generator keystore Android membuat satu baru jika Anda baru saja memulai.
Stage 4: Desain Pipa
Pitfall: bangun native pada setiap permintaan pull
Gejala: Periksa waktu PR yang lambat dan tagihan macOS yang besar.
Penyebab: Build iOS di pengguna macOS yang dihosting adalah yang paling mahal dalam kebanyakan rencana CI, dan sebagian besar komit hanya menyentuh JavaScript.
Pembetulan: Jalankan lint, tes, dan build web di setiap PR. Jalankan build native di tag tag rilis atau merge untuk mainUntuk pratinjau PR, kirimkan bundle web ke saluran Capgo daripada membangun biner, seperti yang dijelaskan dalam Menggunakan platform CI/CD untuk aplikasi Capacitor.
Kebijakan: membangun iOS dan Android secara berurutan
Pembetulan: Pakai matrix agar kedua platform membangun secara paralel, dan atur fail-fast: false agar masalah tanda tangan iOS tidak membatalkan build Android yang baik.
strategy:
fail-fast: false
matrix:
platform: [ios, android]
Pitfall: tidak ada caching, atau cache yang salah
Pertanda: setiap build mengunduh dependensi Gradle dan CocoaPods dari awal, atau build tahap produksi mengirim konfigurasi produksi dari cache yang ketinggalan zaman.
Pembetulan: cache ~/.gradle/caches, ~/.gradle/wrapper, dan ios/App/Pods dipisahkan berdasarkan lockfiles. Bagi cache berdasarkan lingkungan. Dengan Capgo Build, cache build per aplikasi dapat dipisahkan dengan --cache-key prod dan --cache-key staging, atau dilewati dengan --no-cache untuk mendapatkan build yang bersih.
Pitfall: jalur monorepo
Pertanda: could not find capacitor.config atau plugin yang hilang dari proyek native.
Fix: jalankan perintah Capacitor dari paket aplikasi, dan arahkan alat ke __CAPGO_KEEP_1__ node_modulesThe Capgo CLI menerima --path and --node-modules untuk hal ini.
Langkah 5: Pengiriman ke toko
Pitfall: nomor build yang digunakan kembali
Gejala: “Versi bundel harus lebih tinggi dari versi yang telah diunggah sebelumnya” di iOS, atau “Versi code telah digunakan sebelumnya” di Google Play.”
Fix: generate nomor tersebut di CI. Dengan fastlane, baca versi terbaru TestFlight dan tambahkan satu. Dengan Capgo Build, ini adalah default: mengambil nomor versi terbaru dari App Store Connect atau versi tertinggi versionCode from Google Play dan meningkatkan itu.
Pitfall: bangunan terjebak di TestFlight
Gejala: upload berhasil tetapi tester tidak pernah melihat bangunan.
Penyebab: jawaban kelayakan ekspor hilang.
Perbaikan: deklarasikan sekali di ios/App/App/Info.plist jika Anda hanya menggunakan enkripsi standar:
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
Pitfall: penolakan manifesto privasi
Gejala: email dari Apple tentang alasan yang diperlukan yang hilang API deklarasi (ITMS-91053).
Perbaiki: Tambahkan PrivacyInfo.xcprivacy ke app target dan perbarui plugin yang membawa sendiri. Lihat Petunjuk Privasi untuk Aplikasi Capacitor.
Google Play memerlukan AAB (
Perbaiki: Google Play memerlukan AAB ("bundleReleasetidak merupakan APK. bundleRelease tetap berhasil tanpa release konfigurasi signing dan menghasilkan AAB tidak terdaftar yang ditolak oleh Play, jadi konfigurasi signingConfigs.release in android/app/build.gradle Pertama. iOS memerlukan ekspor ke App Store, bukan IPA pengembangan atau ad hoc. Periksa metode ekspor di langkah pembangunan Anda.
Langkah 6: Perbaruan Langsung
Pitfall: mengirimkan live update yang memerlukan bangunan native baru
Gejala: setelah perbaruan over-the-air, aplikasi bermasalah saat memanggil metode plugin yang tidak ada di binary yang terinstal.
Penyebab: bundle web bergantung pada versi plugin yang lebih baru daripada yang dikompilasi ke dalam aplikasi di perangkat pengguna.
Solusi: biarkan pipeline memutuskan. build needed keluar 0 ketika dependensi native sesuai dengan apa yang ada di channel dan 1 ketika binary baru diperlukan:
if bunx @capgo/cli@latest build needed com.example.app --channel production; then
bunx @capgo/cli@latest bundle upload com.example.app --channel production
else
bunx cap sync
bunx @capgo/cli@latest build request com.example.app --platform ios
bunx @capgo/cli@latest build request com.example.app --platform android
fi
Juga paksa jalur native ketika file di ios/, android/, atau capacitor.config.* berubah. Pola lengkap ada di Pilih otomatis live update atau build native, dan aturan kompatibilitas ada di kompatibilitas native.
Perbaikan yang menghilangkan banyak kelemahan
Jika Anda hanya mengubah satu hal, pindahkan kompilasi dan tanda tangan iOS keluar dari runner CI Anda. Pengaturan Keychain, pembaruan Xcode, biaya macOS, dan instalasi profil semua hilang dari pipeline Anda ketika pekerjaan Linux menyerahkan proyek yang disiapkan ke Capgo Build:
bun install --frozen-lockfile && bun run build
bunx cap sync ios
bunx @capgo/cli@latest build request com.example.app --platform ios --build-mode release
The pitfalls in stages 1, 5, and 6 still apply, because they are about your project, not the runner. For more on debugging failing jobs, see Mengatasi gagal build di Capacitor pipeline CI/CD.
Referensi Cepat
| Error | Referensi cepat | Section |
|---|---|---|
| Antarmuka Lama di Bangunan Baru | cap sync sebelum build web |
Tahap 1 |
No profiles for ... were found |
Profesi tidak terpasang atau tidak sesuai | Tahap 3 |
errSecInternalComponent |
Kunci rantai terkunci | Tahap 3 |
MAC verification failed |
Kata sandi salah atau OpenSSL 3 .p12 |
Tahap 3 |
Unsupported class file major version |
JDK salah | Tahap 2 |
| SDK terlalu tua pada unggah | Xcode lebih tua dari 26 | Langkah 2 |
| Versi bundel harus lebih tinggi | Nomor build digunakan kembali | Langkah 5 |
| Versi code sudah digunakan sebelumnya | Reused versionCode |
Langkah 5 |
| Kecelakaan setelah live update | Pengubahan asli diteruskan melalui udara | Langkah 6 |