Lebih lanjut ke konten utama

CI/CD untuk Capacitor: Kesalahan Umum dan Perbaikan

The CI/CD pitfalls that break Capacitor builds: iOS signing, macOS runners, Xcode 26, stale cap sync, version codes, store rejections, and fixes for each.

Martin Donadieu

Martin Donadieu

Penulis

Valeria

Pengulas

Jordan

Pengarang

CI/CD untuk Capacitor: Kesalahan Umum dan Perbaikan

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
Live updates untuk aplikasi Capacitor

Ketika bug layer web masih aktif, kirimkan perbaikan melalui Capgo daripada menunggu hari-hari untuk persetujuan toko aplikasi. Pengguna mendapatkan update di latar belakang sementara perubahan native tetap dalam jalur review normal.

Bantuan manusia dari Martin

Mulai Sekarang

Terbaru dari Blog Kami

Capgo memberikan Anda wawasan terbaik yang Anda butuhkan untuk menciptakan aplikasi mobile profesional yang sebenarnya.