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 sich für Cordova-Teams geändert hat
Drei Ereignisse haben die Cordova-CI/CD geprägt:
- PhoneGap Build am 1. Oktober 2020 eingestellt.
- Microsoft App Center am 31. März 2025 eingestellt. Die Bereitstellung, Verteilung und der gehostete CodePush-Dienst endeten mit ihm.
- Ionic Appflow hatte im Februar 2025 neue Verkäufe 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 Riss ist die verwaltete Schicht: Signierungsspeicher, Laden von Dateien und über-ein-Netz-Updates. Sie bauen nun diese aus einem CI-Dienst und einigen Werkzeugen zusammen.
Anatomie eines Cordova-Pipelines
| Schritt | Android | iOS |
|---|---|---|
| Runner | Linux | macOS mit Xcode 26 |
| Restore | cordova prepare (Plattformen und Plugins von package.json) |
gleich |
| Web-Build | Ihr Bundler (Vite, webpack, Angular CLI) in www/ |
gleich |
| Native-Build | Gradle über cordova build android --release |
xcodebuild via cordova build ios --release --device |
| Signierung | Hochladen des Keystore (.jks) |
Verteilungszertifikat (.p12) und Provisionierungsprofil |
| Artikel | .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 Plattformregeln gelten für jede 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-iosDie Version unterstützt es. - Google Play verlangt AAB-Uploads für neue Apps und erhöht sein Mindestziel API jährlich. Halten
cordova-androidSchritt 1: Machen Sie das Projekt wiederherstellbartargetSdkVersionfollows.
Schritt 1: Machen Sie das Projekt wiederherstellbar
CI kann nur das neu aufbauen, was im Repository ist. Bevor Sie einen Workflow schreiben:
- Commit
package.jsonSchritt 1: Machen Sie das Projekt wiederherstellbarcordovaTeil derpackage.json, socordova preparewiederherstellt sie. - Vermeiden Sie das Commit
platforms/oderplugins/Sie werden generiert. - Installieren Sie Cordova CLI als Entwicklungsabhängigkeit, damit jede Maschine die gleiche Version verwendet:
bun add -d cordova
- Verschieben Sie die Signierungsdaten aus
config.xmlund in einebuild.jsondie Geheimnisse bei der Buildzeit liest (Schritt 2). - Fixieren Sie die Node.js-Version in
.nvmrcoderpackage.jsonengines.
Schritt 2: Signieren mit build.json
Cordova liest die Signierungsdaten aus einem build.json Datei. Commiten Sie eine build.template.json mit Ersatzzeichen, generieren Sie das echte build.json in CI aus Geheimnissen, und committieren Sie das generierte Datei nie:
{
"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
}
}
}
Das ${...} Ersatzzeichen werden nicht durch Cordova erweitert. Der Workflow unten schreibt die echten Werte mit envsubst.
Wenn Sie noch keinen Android-Keystore haben, erstellen Sie einen mit keytool oder der browserbasierten Android-Keystore-Generator. Für iOS erstellt der iOS-Zertifikatsgenerator eine Zertifikatsanforderung und .p12 ohne einen Mac.
Schritt 3: Ein GitHub Actions-Workflow
Dieses 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
Warum einige Zeilen da sind:
- Zwei Provisionierungsprofil-Ordner. Xcode 16 und später liest Profile aus
~/Library/Developer/Xcode/UserData/Provisioning ProfilesÄltere Xcode verwendeten~/Library/MobileDevice/Provisioning ProfilesBeides schreibt, um „Keine Profile für ‘com.example.app’ gefunden“ zu vermeiden. set-key-partition-listStoppt macOS von der Anforderung von Zugriff auf den Schlüsselkette, was einen CI-Auftrag blockieren würde.- JDK-Version. Verwenden Sie die JDK-Version, die in Ihren
cordova-androidVeröffentlichungsunterlagen angegeben ist. Neuere Versionen bauen mit JDK 17. - Build-Zahlen. Erhöhen
android-versionCodeundios-CFBundleVersioninconfig.xmlvor der Veröffentlichung, zum Beispiel aus der CI-Auftragsnummer oder wenn die Stores die Uploadung als Duplikat ablehnen.
Sie können die altool Upload für fastlanes upload_to_testflight und die Play-Aktion für fastlanes supply wenn Ihr Team bereits fastlane verwendet.
Schritt 4: Die gleiche Pipeline auf anderen CI-Diensten
Die Befehle ändern sich nicht zwischen CIs. Nur die Runner-Auswahl und die Geheimnis-Syntax.
| CI | Android-Runner | iOS-Runner | Hinweise |
|---|---|---|---|
| GitHub Aktionen | ubuntu-latest |
macos-26 / macos-latest |
macOS-Minuten sind teurer als Linux auf privaten Repositories |
| GitLab CI | jeder Linux-Runner | gehostete macOS-Runner (Beta, Premium und Ultimate) oder selbst gehostet | Bilder wie macos-26-xcode-26 |
| Bitbucket Pipelines | Linux-Docker-Bild | nur selbst gehostet auf Mac | siehe Bitbucket iOS-Leitfaden |
| Gitea / Forgejo | Linux-Runner | eigenes gehostetes Mac in Host-Modus | siehe Gitea iOS-Leitfaden |
| Bitrise | Linux-Stacks | macOS-Stacks | versendet Cordova-Schritte (Vorbereitung, Archivierung) |
| Codemagic | Linux | Mac mini-Instanzen | Dokumente von Ionic Cordova Builds 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-Überprüfung 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+ (der Plugin hängt von ihren Standardhttps://localhost/undapp://localhost/und- Schemata
cordova-plugin-ionic-webviewmit ihm. Der Ionic WebView umgeht die Scheme-Handler von Cordova, daher würden heruntergeladene Bundles 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 Ihrem 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, and AUTO_UPDATE sind optional installierbare Variablen. Ausführen cordova prepare sind optional installierbare Variablen. Führen Sie
wiederholt, sobald Sie sie ändern.
After deviceready, das Plugin ist verfügbar als cordova.plugins.Updater. Ruf notifyAppReady() auf jedem Start, oder das Plugin behandelt das neue Bundle als defekt und rollt 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 })
}
})
Hochladen von Bundles aus CI
Hinzufügen einer Aufgabe, die das Weblayer baut und hochlädt, für Web-only-Änderungen:
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 das Web-Bundle. Hinzufügen, Entfernen oder Upgraden eines Cordova-Plugins benötigt immer noch eine neue Store-Build. Capgo vergleicht die native Plugins, die für das Live-Bundle aufgezeichnet wurden, mit Ihrem Projekt und markiert inkompatible Uploads; siehe live update-Kompatibilität. Vollständige Konfiguration ist in den Dokumentationen zum Cordova-Updater.
Auf der Build-Seite ist der Capgo Build Dokumentation deckt nur Capacitor-Projekte ab (sie lädt das native Projekt hoch, das von} cap syncCordova-Binaries bauen weiterhin auf Ihrem CI wie oben gezeigt.
Optional: Migration zu Capacitor später
Sie müssen nicht Cordova verlassen, um eine funktionierende Pipeline und Live-Updates zu erhalten. Die Migration ist eine separate Entscheidung, die sich lohnt, wenn:
- Sie iOS-Builds ohne die Verwaltung von macOS-Runnern wollen. Capgo Build kompiliert Capacitor-Apps aus einem Linux-CI-Auftrag.
- Die Plugins, auf die Sie angewiesen sind, erhalten keine Cordova-Updates mehr, aber haben Capacitor-Äquivalente.
- Sie Swift Package Manager-Unterstützung und aktuelle Android Gradle Plugin-Versionen ohne Plattform-Patching wollen.
Die Migration hält 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-updaterMigration von Cordova zu __CAPGO_KEEP_0__ Live-Updates von Capacitor zu Capacitor, und das Cordova zu Lösung für Capacitor beschreibt die Unterstützung bei der Migration. Nach der Migration reduziert sich die CI oben auf eine Web-Ausgabe, cap sync, und eine build request Aufruf pro Plattform, wie in 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 Ihre Web-Build-Ausführung vor Cordova-Befehlen aus, oder erstellen Sie einen leeren www/. |
No platforms added to this project |
oder (Appflow-Plugins oder) package.json. Ausführen cordova platform add lokal einmal und committieren package.json. |
Could not find an installed version of Gradle |
Neueste 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. Pin es mit setup-java. |
No signing certificate "iOS Distribution" found |
Use Apple Distribution enthält den privaten Schlüssel. .p12 enthält den privaten Schlüssel. |
errSecInternalComponent |
Geschlossener Schlüsselkette oder fehlende Partitionenliste. Die Schlüsselkette-Einstellungen erneut ausführen. |
| Upload abgelehnt: SDK ist zu alt | Runner-Bild verwendet Xcode älter als 26. Wählen Sie macos-26 oder Xcode mit xcode-select. |
Play hochladen: Version code has already been used |
Bump android-versionCode für jeden Upload. |
Zusammenfassung
Eine Cordova-Pipeline im Jahr 2026 ist ein 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 eine generierte 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-Punkte, die Appflow und App Center früher bereitgestellt haben. Die Umstellung auf Capacitor bleibt eine Option für später, kein Erfordernis.