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.
Was hat sich für die Cordova-Teams geändert
Drei Ereignisse haben die Cordova-CI/CD geprägt:
- PhoneGap Build ist am 1. Oktober 2020 eingestellt worden.
- Microsoft App Center ist am 31. März 2025 eingestellt worden. Die Erstellung, Verteilung und der gehostete CodePush-Dienst endeten mit ihm.
- Ionic Appflow Die neuen Verkäufe wurden im Februar 2025 eingestellt. Bestehende Kunden behalten bis zum 31. Dezember 2027 Zugriff.
Cordova selbst funktioniert noch. Das Apache-Projekt liefert cordova-android und cordova-ios Veröffentlichungen, und viele interne und unternehmensweite Apps laufen darauf. Der Haken ist der verwaltete Layer: Signierungsspeicher, Laden von Uploads und über-ein-Netz-Updates. Sie assemblieren diese nun aus einem CI-Dienst plus einigen Werkzeugen.
Anatomie eines Cordova-Pipelines
| Bühne | Android | iOS |
|---|---|---|
| Runner | Linux | macOS mit Xcode 26 |
| Restore | cordova prepare (Plattformen und Plugins von package.json) |
demselben |
| Web-Build | Ihrer Bundler (Vite, webpack, Angular CLI) in www/ |
demselben |
| Native-Build | über cordova build android --release |
xcodebuild über cordova build ios --release --device |
| Signieren | Hochladen von Keystore (.jks) |
Distributionszertifikat (.p12und Provisionierungsprofil |
| Kunstwerk | .aab für Google Play |
.ipa für TestFlight und den App Store |
| Hochladen | Google Play-Entwickler API (Dienstkontoinformationen) | App Store Connect API-Schlüssel |
Zwei Plattformenregeln gelten für jeden Pipeline:
- Seit dem 28. April 2026 akzeptiert App Store Connect nur Builds, die mit Xcode 26 und iOS 26 SDK oder später erstellt wurden. Überprüfen Sie, ob Ihre
cordova-iosVersion es unterstützt. - Google Play erfordert AAB-Hochladungen für neue Apps und erhöht sein Mindestziel API-Niveau jährlich. Halten Sie es aktuell, damit es standardmäßig
cordova-android) und Provisionierungsprofil für iOStargetSdkVersionfolgt.
Schritt 1: Mach das Projekt wiederholbar
CI kann nur das Wiederaufbauen, was im Repository ist. Bevor man einen Workflow schreibt:
- Commit
package.jsonund das Lockfile. Cordova speichert Plattformen und Plugins imcordovaAbschnitt vonpackage.json, alsocordova preparewiederherstellt sie. - Commit nicht oder
platforms/orplugins/Sie werden generiert. - Installiere Cordova CLI als Entwicklungsabhängigkeit, damit jeder Computer die gleiche Version verwendet.
bun add -d cordova
- Entferne die Signierwerte aus
config.xmlund in einebuild.jsondie Geheimnisse bei der Buildzeit liest (nächster Schritt). - Pins die Node.js-Version in
.nvmrcoderpackage.jsonengines.
Schritt 2: Signieren mit build.json
Schritt 2: Signieren mit build.json build.json file. Commit a build.template.json Cordova liest Signierereinstellungen aus einem build.json in CI aus Geheimnissen, und komme nie dazu, das generierte File zu committen:
{
"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
}
}
}
The ${...} Die Platzhalter werden nicht durch Cordova erweitert. Der untenstehende Workflow schreibt die echten Werte mit envsubst.
If Sie noch keinen Android-Keystore haben, erstellen Sie einen mit keytool oder die browserbasierte Android-Keystore-Generator. Für iOS verwendet man den iOS-Zertifikatsgenerator , der ein Zertifikatsantragsformular erstellt und .p12 ohne einen Mac.
Schritt 3: Ein GitHub Actions-Aufgabenworkflow
Dieser Workflow baut beide Plattformen parallel auf einer Versionsnummer auf und lädt sie in die internen Testtracks hoch.
# .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
Weshalb einige Zeilen da sind:
- Zwei Provisioning-Profile-Ordner. Xcode 16 und später liest Profile aus
~/Library/Developer/Xcode/UserData/Provisioning Profiles. Ältere Xcode-Versionen~/Library/MobileDevice/Provisioning Profiles. Beide Schreiben vermeidet "Keine Profile für 'com.example.app' gefunden". set-key-partition-listVerhindert macOS-Anfragen zum Zugriff auf den Schlüsselkartencontainer, was einen CI-Auftrag blockieren würde.- . JDK-Version. Verwenden Sie den JDK, den Sie
cordova-androidVeröffentlichungsunterlagen. Neueste Versionen werden mit JDK 17 erstellt. - . Erhöhen . und
android-versionCode. inios-CFBundleVersioninconfig.xmlvor dem Build, zum Beispiel aus der CI-Ausführungsnummer, oder die Stores lehnen den Upload als Duplikat ab.
. Sie können die altool Upload für fastlane’s upload_to_testflight und die Play-Aktion für fastlane supply falls Ihr Team bereits fastlane verwendet.
Schritt 4: Das gleiche Pipeline auf anderen CI-Diensten
Die Befehle ändern sich nicht zwischen CIs. Nur die Runner-Auswahl und die Geheimnis-Syntax ändern sich.
| CI | Android-Runner | iOS-Runner | Hinweise |
|---|---|---|---|
| GitHub Aktionen | ubuntu-latest |
macos-26 / macos-latest |
macOS-Minuten kosten mehr als Linux auf privaten Repositories |
| GitLab CI | jeder Linux Runner | hostete macOS Runner (Beta, Premium und Ultimate) oder selbst gehostet | Bilder wie macos-26-xcode-26 |
| Bitbucket Pipelines | Linux Docker-Bild | selbst gehostet, nur Mac | siehe Bitbucket iOS-Leitfaden |
| Gitea / Forgejo | Linux Runner | selbst gehostet, Mac in Host-Modus | siehe Gitea iOS Anleitung |
| Bitrise | Linux-Stacks | macOS-Stacks | versendet Cordova-Schritte (Vorbereitung, Archivierung) |
| Codemagic | Linux | Mac mini-Instanzen | dokumentiert Ionic Cordova-Builds in codemagic.yaml |
| Azure DevOps | ubuntu-latest |
macOS-latest |
Aufgaben zum Installieren von Zertifikaten und Profilen |
Für eine features-basierte Ansicht, lesen Sie Vergleich von CI/CD-Plattformen für Cordova-Anwendungen.
Schritt 5: Live-Updates für Cordova
Live-Updates ermöglichen Ihnen, HTML-, CSS- und JavaScript-Fixes ohne eine App-Store-Bewertung zu liefern. App Center CodePush endete im März 2025, Appflow Live Updates enden am 31. Dezember 2027, und die alten Community-Hot-code-Push-Plugins sind nicht mehr unterstützt. Eine unterstützte Option ist Capgo-Live-Updates mit dem @capgo/cordova-updater Plugin, das denselben Backend, Kanälen und CLI wie der Capacitor-Updater verwendet.
Anforderungen
- Cordova CLI 12+
cordova-android13+ und/odercordova-ios7+ (das Plugin hängt von ihren Standard-https://localhost/undapp://localhost/Schlüsseln ab)- Do not use
cordova-plugin-ionic-webviewEs wird mit Ionic WebView umgangen, sodass heruntergeladene Pakete nicht geladen werden.
Installieren Sie das Plugin
Erstellen Sie die App in Capgo auf die gleiche Weise wie für Capacitor, dann installieren Sie das Plugin mit Ihrer Capgo-App-ID:
cordova plugin add @capgo/cordova-updater \
--variable APP_ID=com.example.app \
--variable DEFAULT_CHANNEL=production
cordova prepare android ios
DEFAULT_CHANNEL, UPDATE_URL, und AUTO_UPDATE sind optional installierte Variablen. Führen Sie cordova prepare erneut durch, sobald Sie sie ändern.
Bestätigen Sie jede Startsequenz
Nachdem deviceready, ist das Plugin als cordova.plugins.Updater. Call notifyAppReady() auf jeden Start auf, oder das Plugin behandelt das neue Paket als defekt und rollt es zurück:
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 })
}
})
Bundle-Uploads von CI
Ein Job hinzufügen, der die Web-Schicht baut und hochlädt, für Web-Änderungen nur:
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 ersetzen nur die Web-Bundle. Die Hinzufügung, Entfernung oder Upgrade eines Cordova-Plugins erfordert immer noch eine neue Store-Build. Capgo vergleicht die für das Live-Bundle aufgezeichneten nativen Plugins mit Ihrem Projekt und markiert inkompatible Uploads; siehe live update-KompatibilitätVollständige Einrichtung ist in der Cordova-Updater-Dokumentation.
Auf der Build-Seite Capgo Build Die Dokumentation umfasst nur Capacitor-Projekte (sie lädt das native Projekt hoch, das von) cap syncnur __CAPGO_KEEP_0__-Projekte ab (sie lädt das native Projekt ab, das von
Optional: Migration nach Capacitor später
Sie müssen Cordova nicht verlassen, um eine funktionierende Pipeline und Live-Updates zu erhalten. Die Migration ist eine separate Entscheidung, die sich lohnt, wenn:
- Sie möchten iOS-Builds ohne die Verwaltung von macOS-Runnern. Capgo Der Build kompiliert Capacitor-Apps aus einem Linux-CI-Auftrag.
- Plugins, auf die Sie angewiesen sind, erhielten keine Cordova-Updates, aber haben Capacitor-Äquivalente.
- Sie möchten Unterstützung für Swift Package Manager und aktuelle Android Gradle Plugin-Versionen ohne Plattform-Patching.
Die Migration hält Ihre www code. Sie fügen Capacitor hinzu, bewegen Plugins über (die meisten Cordova-Plugins funktionieren so weiter), und ersetzen einige, die Capacitor-native Äquivalente haben. Ihre Capgo-App-ID und Kanäle bleiben gleich; nur der Updater-Plugin ändert sich von @capgo/cordova-updater bis @capgo/capacitor-updaterDie Schritte sind in Migrating from Cordova to Capacitor, und die Cordova zu Capacitor-Lösung beschreibt, wie Sie Hilfe bei ihr erhalten. Nach der Migration schrumpft der CI oben auf einen Web-Build cap sync, und ein build request auf jeder Plattform, wie im Vergleich von CI/CD-Plattformen für Capacitor-Anwendungen.
Troubleshooting von Cordova-Builds in CI
| Fehler | Ursache und Lösung |
|---|---|
Current working directory is not a Cordova-based project |
config.xml oder www/ fehlen. Führen Sie vor Cordova-Befehlen Ihre Web-Build-Ausführung durch, oder erstellen Sie einen leeren www/. |
No platforms added to this project |
Plattformen werden nicht aufgelistet in package.json. Run cordova platform add Lokal einmal und committen package.json. |
Could not find an installed version of Gradle |
Recent cordova-android verwendet den Gradle Wrapper. Aktualisieren Sie die Plattform anstatt Gradle global zu installieren. |
Unsupported class file major version |
JDK auf dem Runner entspricht nicht dem auf der Seite cordova-android erwartet. Pinnt es mit setup-java. |
No signing certificate "iOS Distribution" found |
Use Apple Distribution den privaten Schlüssel enthält. .p12 enthält den privaten Schlüssel. |
errSecInternalComponent |
Geschlossener Schlüsselkette oder fehlende Partitionenliste. Keychain-Einrichtungskommandos erneut ausführen. |
| Upload abgelehnt: SDK ist zu alt | Runner-Bild verwendet Xcode älter als 26. Wählen Sie macos-26 Play-Hochladen: xcode-select. |
Hochstufen Version code has already been used |
Bump android-versionCode für jedes Hochladen. |
Zusammenfassung
Eine Cordova-Pipeline im Jahr 2026 ist eine CI-Job pro Plattform: ein Linux-Runner für das Android AAB, ein macOS-Runner mit Xcode 26 für das IPA, geheime Codes in einen generierten build.json, und API-Schlüssel für beide Stores. Jeder mainstream CI kann ihn ausführen. Fügen Sie @capgo/cordova-updater und einen bundle upload Job für web-only-Fixes hinzu, und Sie haben die Build-, Store- und Over-the-Air-Pieces, die Appflow und App Center früher bereitgestellt haben. Die Umstellung auf Capacitor bleibt eine Option für später, kein Erfordernis.