CI/CD for a Cordova app in 2026 means building and signing the Android AAB on a Linux runner, building and signing the iOS IPA on a macOS runner, and uploading both to the stores from the same pipeline. The managed services Cordova teams used for this are gone or closing, so most teams now run the Cordova CLI on a general-purpose CI. This guide gives you a working GitHub Actions setup, the same steps for other CIs, and an honest look at live updates and long-term options.
Apa yang berubah untuk tim Cordova
Tiga event yang membentuk Cordova CI/CD:
- PhoneGap Build Dihentikan pada Oktober 1, 2020.
- Microsoft App Center Dihentikan pada Maret 31, 2025. Pembangunan, distribusi, dan layanan CodePush yang dihosting berakhir bersamaan dengan itu.
- Ionic Appflow Menghentikan penjualan baru pada Februari 2025. Pelanggan yang ada tetap memiliki akses hingga Desember 31, 2027.
Cordova sendiri masih berfungsi. Projek Apache mengirimkan cordova-android dan cordova-ios releases, and plenty of internal and enterprise apps run on it. The gap is the managed layer: signing storage, store uploads, and over-the-air updates. You now assemble those from a CI service plus a few tools.
Anatominya Pipa Cordova
| Langkah | Android | IOS |
|---|---|---|
| Runner | Linux | macOS dengan Xcode 26 |
| Restore | cordova prepare (platform dan plugin dari package.json) |
sama |
| Build web | bundler Anda (Vite, webpack, Angular CLI) www/ |
sama |
| melalui Gradle | Gradle melalui cordova build android --release |
xcodebuild melalui cordova build ios --release --device |
| Menggunakan | unggah keystore (.jks) |
Sertifikat distribusi (.p12) dan profil pengaturan |
| Artifact | .aab untuk Google Play |
.ipa untuk TestFlight dan App Store |
| Unggah | Pengembang Google Play API (akun layanan) | Kunci App Store Connect API |
Dua aturan platform berlaku untuk setiap pipeline:
- Sejak tanggal 28 April 2026, App Store Connect hanya menerima bangun dengan Xcode 26 dan iOS 26 SDK atau lebih baru. Pastikan versi Anda mendukungnya.
cordova-iosDukungan versi ini. - Google Play requires AAB uploads for new apps, and raises its minimum target API level every year. Keep
cordova-androidsaat ini sehingga defaultnyatargetSdkVersionfollows.
Langkah 1: Buat Projek yang Dapat Direproduksi
CI hanya dapat membangun apa yang ada di repository. Sebelum menulis apa pun di workflow:
- bagian
package.jsondan file lock. Cordova menyimpan platform dan plugin dicordovabagian daripackage.json, socordova preparemengembalikannya. - Jangan mengirimkan perubahan
platforms/atauplugins/. Mereka dihasilkan. - Pasang Cordova CLI sebagai dependensi pengembang agar setiap mesin menggunakan versi yang sama:
bun add -d cordova
- Pindahkan nilai tanda tangan keluar dari
config.xmldan ke dalambuild.jsonyang membaca rahasia pada saat pembangunan (langkah berikutnya). - Tetapkan versi Node.js di
.nvmrcataupackage.jsonengines.
Langkah 2: Tanda tangan dengan build.json
Cordova membaca pengaturan tanda tangan dari file build.json Simpan perubahan build.template.json dengan tempat pengganti, buatlah yang sebenarnya build.json dari rahasia CI, dan jangan pernah komit file yang dihasilkan:
{
"android": {
"release": {
"keystore": "release.jks",
"storePassword": "${KEYSTORE_STORE_PASSWORD}",
"alias": "upload",
"password": "${KEYSTORE_KEY_PASSWORD}",
"packageType": "bundle"
}
},
"ios": {
"release": {
"codeSignIdentity": "Apple Distribution",
"developmentTeam": "ABCDE12345",
"packageType": "app-store",
"provisioningProfile": "com.example.app AppStore",
"automaticProvisioning": false
}
}
}
Yang ${...} tempat pengganti tidak diperluas oleh Cordova. Alur kerja di bawah ini menulis nilai yang sebenarnya dengan envsubst.
Jika Anda belum memiliki keystore Android, buatlah satu dengan keytool atau generator keystore Android berbasis browser generator keystore iOSmembuat permintaan tanda tangan sertifikat dan tanpa menggunakan Mac. Langkah 3: Alur kerja __CAPGO_KEEP_0__ Actions .p12 tanpa Mac.
Langkah 3: Alur Tindakan GitHub
Alur ini membangun kedua platform secara paralel pada tag versi dan mengunggahnya ke jalur pengujian internal.
# .github/workflows/cordova-release.yml
name: Cordova release
on:
push:
tags: ['v*']
jobs:
android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
- run: bun install --frozen-lockfile
- run: bun run build # outputs to www/
- run: bunx cordova prepare android
- name: Signing files
env:
KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }}
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
run: |
echo "$KEYSTORE_BASE64" | base64 --decode > release.jks
envsubst < build.template.json > build.json
- run: bunx cordova build android --release --buildConfig=build.json
- uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
packageName: com.example.app
releaseFiles: platforms/android/app/build/outputs/bundle/release/app-release.aab
track: internal
status: completed
ios:
runs-on: macos-26
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run build
- run: bunx cordova prepare ios
- name: Install certificate and profile
env:
P12_BASE64: ${{ secrets.IOS_P12_BASE64 }}
P12_PASSWORD: ${{ secrets.IOS_P12_PASSWORD }}
PROFILE_BASE64: ${{ secrets.IOS_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
echo "$P12_BASE64" | base64 --decode > dist.p12
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security set-keychain-settings -lut 21600 build.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security import dist.p12 -k build.keychain -P "$P12_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" build.keychain
security list-keychains -d user -s build.keychain login.keychain
for dir in "$HOME/Library/MobileDevice/Provisioning Profiles" \
"$HOME/Library/Developer/Xcode/UserData/Provisioning Profiles"; do
mkdir -p "$dir"
echo "$PROFILE_BASE64" | base64 --decode > "$dir/app.mobileprovision"
done
cp build.template.json build.json # iOS values hold no secrets
- run: bunx cordova build ios --release --device --buildConfig=build.json
- name: Upload to TestFlight
env:
API_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
API_ISSUER: ${{ secrets.APPLE_ISSUER_ID }}
API_KEY_BASE64: ${{ secrets.APPLE_KEY_CONTENT }}
run: |
mkdir -p ~/.appstoreconnect/private_keys
echo "$API_KEY_BASE64" | base64 --decode > ~/.appstoreconnect/private_keys/AuthKey_${API_KEY_ID}.p8
IPA=$(find platforms/ios/build -name '*.ipa' | head -n 1)
xcrun altool --upload-app -f "$IPA" -t ios --apiKey "$API_KEY_ID" --apiIssuer "$API_ISSUER"
- name: Clean up keychain
if: always()
run: security delete-keychain build.keychain || true
Mengapa beberapa baris ada:
- Dua folder profil pengaturan. Xcode 16 dan lebih lanjut membaca profil dari
~/Library/Developer/Xcode/UserData/Provisioning ProfilesXcode yang lebih tua menggunakan~/Library/MobileDevice/Provisioning ProfilesMenggunakan kedua cara menghindari pesan ‘Tidak ada profil untuk ‘com.example.app’ ditemukan’. set-key-partition-listMenghentikan macOS dari meminta akses ke keychain, yang akan membuat pekerjaan CI terjebak.- Versi JDK. Pakai JDK yang
cordova-androidDokumen rilis terbaru membangun dengan JDK 17. - Nomor bangun. Bump
android-versionCodedanios-CFBundleVersiondiconfig.xmlsebelum proses build, misalnya dari nomor run CI, atau toko-toko menolak mengunggah sebagai duplikat.
Kamu bisa mengganti altool unggah untuk fastlane upload_to_testflight dan aksi Play untuk fastlane supply jika tim Anda sudah menggunakan fastlane.
Langkah 4: Pipa yang sama di layanan CI lainnya
Perintah tidak berubah antar CI. Hanya pemilihan runner dan sintaks rahasia yang berubah.
| CI | runner Android | runner iOS | Catatan |
|---|---|---|---|
| GitHub Aksi | ubuntu-latest |
macos-26 / macos-latest |
Menit macOS lebih mahal daripada Linux di repositori pribadi |
| GitLab CI | apapun Linux runner | hosted macOS runner (beta, Premium dan Ultimate) atau self-hosted | gambar seperti macos-26-xcode-26 |
| Pipelines Bitbucket | Gambar Linux Docker | self-hosted Mac hanya | lihat Petunjuk iOS Bitbucket |
| Gitea / Forgejo | Pengguna Linux | Mac sendiri dalam mode host | lihat Petunjuk iOS Gitea |
| Bitrise | Stacks Linux | Stacks macOS | Mengirimkan Langkah Cordova (persiapkan, arsip) |
| Codemagic | Linux | Instans Mac mini | documentasi Pembangunan Ionic Cordova di codemagic.yaml |
| Azure DevOps | ubuntu-latest |
macOS-latest |
tugas untuk menginstal sertifikat dan profil |
Untuk melihat secara fitur demi fitur, baca Menggambarkan Platform CI/CD untuk Aplikasi Cordova.
Langkah 5: Live updates untuk Cordova
Live updates let you ship HTML, CSS, and JavaScript fixes without a store review. App Center CodePush ended in March 2025, Appflow Live Updates end on December 31, 2027, and the old community hot code push plugins are unmaintained. A maintained option is Live updates memungkinkan Anda mengirimkan perbaikan HTML, CSS, dan JavaScript tanpa tinjauan toko. App Center CodePush berakhir pada Maret 2025, Appflow Live Updates berakhir pada 31 Desember 2027, dan plugin hot push komunitas lama Capgo tidak lagi dipelihara. Pilihan yang dipelihara adalah dengan Capgo @capgo/cordova-updater plugin yang menggunakan backend, saluran, dan CLI yang sama seperti pembaruan Capacitor.
Requirements
- Cordova CLI 12+
cordova-android13+ dan/ataucordova-ios7+ (plugin ini bergantung pada pengaturan default)https://localhost/danapp://localhost/scheme- Tidak gunakan
cordova-plugin-ionic-webviewdengan itu. Ionic WebView menghindari penggunaan handler scheme Cordova, sehingga bundle yang diunduh tidak akan terbuka.
Pasang plugin
Buat aplikasi di Capgo dengan cara yang sama seperti untuk Capacitor, kemudian pasang plugin dengan ID aplikasi Capgo:
cordova plugin add @capgo/cordova-updater \
--variable APP_ID=com.example.app \
--variable DEFAULT_CHANNEL=production
cordova prepare android ios
DEFAULT_CHANNEL, UPDATE_URL, dan AUTO_UPDATE adalah variabel instalasi opsional. Jalankan cordova prepare lagi setiap kali Anda mengubahnya.
Konfirmasi setiap peluncuran
After devicereadytersedia sebagai plugin cordova.plugins.Updater. Call notifyAppReady() Tambahkan pekerjaan yang membangun layer web dan mengunggahnya, untuk perubahan web saja:
document.addEventListener('deviceready', async () => {
const { Updater } = cordova.plugins
await Updater.notifyAppReady()
const latest = await Updater.getLatest()
if (latest.url && !latest.error) {
const bundle = await Updater.download({
url: latest.url,
version: latest.version,
checksum: latest.checksum,
})
await Updater.next({ id: bundle.id })
}
})
Muat turun paket dari CI
Tambahkan pekerjaan yang membangun layer web dan mengunggahnya, untuk perubahan web saja:
live-update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run build
- run: bunx @capgo/cli@latest bundle upload --channel=production
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
Live updates only replace the web bundle. Adding, removing, or upgrading a Cordova plugin still needs a new store build. Capgo compares the native plugins recorded for the live bundle with your project and flags incompatible uploads; see Kompatibilitas live updatePada sisi build, ada __CAPGO_KEEP_0__ Build.
Pada sisi pembangunan, Capgo documentasi hanya mencakup Capacitor proyek saja (mengunggah proyek native yang dihasilkan oleh cap sync. Binari Cordova tetap membangun di CI Anda seperti yang ditunjukkan di atas.
Optional: Migrasi ke Capacitor kemudian
Anda tidak perlu meninggalkan Cordova untuk mendapatkan pipeline yang berfungsi dan pembaruan hidup. Migrasi adalah keputusan terpisah, layak dilakukan ketika:
- Anda ingin membuat build iOS tanpa menjaga runners macOS. Capgo Build mengompilasi Capacitor aplikasi dari pekerjaan CI Linux.
- Plugin yang Anda gunakan berhenti menerima update Cordova, tetapi memiliki Capacitor yang setara.
- Anda ingin mendukung Swift Package Manager dan versi Android Gradle Plugin saat ini tanpa mempatch platform.
Migrasi menjaga aplikasi Anda www code. You add Capacitor, move plugins over (most Cordova plugins work as is), and replace a few that have Capacitor-native equivalents. Your Capgo app ID and channels stay the same; only the updater plugin changes from @capgo/cordova-updater to @capgo/capacitor-updaterMigrasi dari Cordova ke __CAPGO_KEEP_0__ Migrating from Cordova to Capacitordan Cordova ke halaman solusi Capacitor menutupi mendapatkan bantuan dengan hal tersebut. Setelah migrasi, CI di atas berkurang menjadi build web, cap syncdan satu build request dipanggil per platform, seperti yang dijelaskan di Menggunakan CI/CD untuk aplikasi Capacitor.
Memecahkan masalah build Cordova di CI
| Error | Penyebab dan solusi |
|---|---|
Current working directory is not a Cordova-based project |
config.xml atau www/ Tidak ada. Jalankan build web Anda sebelum menjalankan perintah Cordova, atau buat direktori kosong www/. |
No platforms added to this project |
Platform-platform tidak terdaftar di package.json. Jalankan cordova platform add secara lokal sekali dan komit package.json. |
Could not find an installed version of Gradle |
Terbaru cordova-android Menggunakan wrapper Gradle. Perbarui platform daripada menginstal Gradle secara global. |
Unsupported class file major version |
JDK pada runner tidak sesuai dengan yang cordova-android Diharapkan. Pin dengan setup-java. |
No signing certificate "iOS Distribution" found |
Use Apple Distribution sebagai identitas, dan periksa bahwa .p12 Penolakan unggah: __CAPGO_KEEP_0__ terlalu tua |
errSecInternalComponent |
Gambar runner menggunakan Xcode lebih tua dari 26. Pilih |
| Upload ditolak: SDK terlalu tua | Gambar Runner menggunakan Xcode yang lebih tua dari 26. Pilih macos-26 atau atur Xcode dengan xcode-select. |
Upload Play: Version code has already been used |
Bump android-versionCode untuk setiap upload. |
Ringkasan
Suatu alur Cordova pada tahun 2026 adalah pekerjaan CI per platform: seorang pelari Linux untuk AAB Android, seorang pelari macOS dengan Xcode 26 untuk IPA, rahasia yang diurai menjadi kunci yang dihasilkan build.json, dan API untuk kedua toko. Apapun CI mainstream dapat menjalankannya. Tambahkan @capgo/cordova-updater dan satu bundle upload job for web-only fixes, and you have the build, store, and over-the-air pieces Appflow and App Center used to provide. Moving to Capacitor stays an option for later, not a requirement.