Aller au contenu principal

CI/CD pour les apps Cordova en 2026 : guide de configuration complet

Mettre en place la CI/CD pour les apps Cordova en 2026 : builds Android AAB et iOS IPA signés, upload vers les stores, options live update, et quand passer à Capacitor.

Une application Apache Cordova dans un pipeline CI/CD jusqu’à l’App Store et Google Play

En 2026, le CI/CD pour une application Cordova consiste à compiler et signer l’AAB Android sur un runner Linux, à compiler et signer l’IPA iOS sur un runner macOS, puis à envoyer les deux vers les stores depuis le même pipeline. Les services managés utilisés par les équipes Cordova pour cela ont disparu ou ferment, la plupart des équipes font donc désormais tourner le CLI Cordova sur un CI généraliste. Ce guide vous propose une configuration GitHub Actions qui fonctionne, les mêmes étapes pour d’autres CI, et un regard honnête sur les live updates et les options à long terme.

Ce qui a changé pour les équipes Cordova

Trois événements ont façonné le CI/CD Cordova :

  • PhoneGap Build a été arrêté le 1er octobre 2020.
  • Microsoft App Center retiré le 31 mars 2025. Le build, la distribution et le service CodePush hébergé ont pris fin avec lui.
  • Ionic Appflow a cessé les nouvelles ventes en février 2025. Les clients existants conservent l’accès jusqu’au 31 décembre 2027.

Cordova lui-même fonctionne toujours. Le projet Apache publie cordova-android et cordova-ios de releases, et de nombreuses applications internes et d’entreprise s’appuient dessus. Le manque se situe au niveau de la couche managée : stockage des signatures, uploads vers les stores et mises à jour OTA. Vous devez aujourd’hui assembler ces éléments à partir d’un service CI et de quelques outils.

Anatomie d’un pipeline Cordova

Étape Android iOS
Runner Linux macOS avec Xcode 26
Restaurer cordova prepare (plateformes et plugins depuis package.json) même
Build web votre bundler (Vite, webpack, Angular CLI) dans www/ même
Build natif Gradle via cordova build android --release xcodebuild via cordova build ios --release --device
Signature keystore d'upload (.jks) certificat de distribution (.p12) et profil de provisionnement
Artefact .aab pour Google Play .ipa pour TestFlight et l'App Store
Envoyer Google Play Developer API (compte de service) Clé API App Store Connect

Deux règles de plateforme s’appliquent à chaque pipeline :

  • Depuis le 28 avril 2026, App Store Connect n’accepte que les builds réalisés avec Xcode 26 et l’iOS 26 SDK ou ultérieur. Vérifiez que votre cordova-ios version le prend en charge.
  • Google Play exige les uploads AAB pour les nouvelles applications et augmente chaque année le niveau minimal de API cible. Gardez cordova-android à jour pour que sa valeur par targetSdkVersion défaut suive.

Étape 1 : Rendre le projet reproductible

La CI ne peut reconstruire que ce qui est dans le dépôt. Avant d’écrire un workflow :

  1. Commit package.json et le lockfile. Cordova stocke les plateformes et les plugins dans le cordova section de package.json, donc cordova prepare les restaure.
  2. Ne committez pas platforms/ ou plugins/. Ils sont générés.
  3. Installez le CLI Cordova en dépendance de développement pour que chaque machine utilise la même version :
bun add -d cordova
  1. Déplacez les valeurs de signature hors de config.xml et dans un build.json qui lit les secrets au moment du build (étape suivante).
  2. Épinglez la version de Node.js dans .nvmrc ou package.json engines.

Étape 2 : Signature avec build.json

Cordova lit les paramètres de signature depuis un build.json fichier. Commitez un build.template.json avec des placeholders, générez le fichier réel build.json en CI à partir de secrets, et ne commitez jamais le fichier généré :

{
  "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
    }
  }
}

Le ${...} Les placeholders ne sont pas remplacés par Cordova. Le workflow ci-dessous écrit les valeurs réelles avec envsubst.

Si vous n'avez pas encore de keystore Android, créez-en un avec keytool ou le navigateur générateur de keystore Android en ligne. Pour iOS, le Générateur de certificats iOS crée une demande de signature de certificat et .p12 without a Mac.

Étape 3 : un workflow GitHub Actions

Ce workflow compile les deux plateformes en parallèle sur un tag de version et les envoie vers les pistes de test internes.

# .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

Pourquoi certaines lignes sont présentes :

  • Deux dossiers de profils de provisionnement. Xcode 16 and later read profiles from ~/Library/Developer/Xcode/UserData/Provisioning Profiles. Les versions antérieures de Xcode utilisaient ~/Library/MobileDevice/Provisioning Profiles. Écrire les deux évite l’erreur « No profiles for ‘com.example.app’ were found »
  • set-key-partition-list empêche macOS de demander l’accès au keychain, ce qui bloquerait un job CI.
  • Version du JDK. Utilisez le JDK que votre cordova-android release documente. Les releases récentes se compilent avec JDK 17.
  • Numéros de build. Incrémenter android-versionCode et ios-CFBundleVersion dans config.xml avant le build, par exemple à partir du numéro de run de la CI, sinon les stores rejettent l'upload comme doublon.

Vous pouvez remplacer l' altool upload par celui de fastlane upload_to_testflight et l'action Play par fastlane supply si votre équipe utilise déjà fastlane.

Étape 4 : Le même pipeline sur d'autres services de CI

Les commandes ne changent pas d'une CI à l'autre. Seuls le choix du runner et la syntaxe des secrets varient.

CI Runner Android runner iOS Notes
GitHub Actions GitHub ubuntu-latest macos-26 / macos-latest Les minutes macOS coûtent plus cher que Linux sur les repos privés
GitLab CI n'importe quel runner Linux runners macOS hébergés (bêta, Premium et Ultimate) ou auto-hébergés des images telles que macos-26-xcode-26
Bitbucket Pipelines image Docker Linux Mac auto-hébergé uniquement voir Guide iOS Bitbucket
Gitea / Forgejo Runner Linux Mac auto-hébergé en mode hôte voir Guide iOS Gitea
Bitrise Stacks Linux Stacks macOS fournit les étapes Cordova (prepare, archive)
Codemagic Linux instances Mac mini documente les builds Ionic Cordova dans codemagic.yaml
Azure DevOps ubuntu-latest macOS-latest tâches pour installer les certificats et les profils

Pour une vue par fonctionnalité, lisez Comparaison des plateformes CI/CD pour les apps Cordova.

Étape 5 : live updates pour Cordova

Les live updates vous permettent de livrer des correctifs HTML, CSS et JavaScript sans revue sur les stores. App Center CodePush a pris fin en mars 2025, Appflow Live Updates prend fin le 31 décembre 2027, et les anciens plugins communautaires de hot code push ne sont plus maintenus. Une option maintenue est les live updates Capgo avec le @capgo/cordova-updater plugin, qui utilise le même backend, les mêmes canaux et le même CLI que l'updater Capacitor.

Prérequis

  • Cordova CLI 12+
  • cordova-android 13+ et/ou cordova-ios 7+ (le plugin s'appuie sur leurs https://localhost/ et app://localhost/ schémas)
  • Ne pas utiliser cordova-plugin-ionic-webview avec. Ionic WebView contourne les gestionnaires de schemes de Cordova, donc les bundles téléchargés ne se chargeraient pas.

Installer le plugin

Créez l'app dans Capgo de la même manière que pour Capacitor, puis installez le plugin avec votre ID d'app 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, et AUTO_UPDATE are optional install variables. Run cordova prepare à nouveau dès que vous les modifiez.

Confirmez chaque lancement

Après deviceready, le plugin est disponible en tant que cordova.plugins.Updater. Appelez notifyAppReady() à chaque lancement, sinon le plugin considère le nouveau bundle comme corrompu et effectue un rollback :

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 })
  }
})

Envoyer des bundles depuis la CI

Ajoutez un job qui compile la couche web et l'envoie, pour les modifications uniquement web :

  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 }}

Les live updates ne remplacent que le bundle web. L'ajout, la suppression ou la mise à niveau d'un plugin Cordova nécessite toujours un nouveau build store. Capgo compare les plugins natifs enregistrés pour le bundle live avec votre projet et signale les uploads incompatibles ; voir compatibilité live update. La configuration complète se trouve dans le Docs de l'updater Cordova.

On the build side, the Build Capgo la documentation ne couvre que les projets Capacitor (elle envoie le projet natif produit par cap sync). Les binaires Cordova continuent d'être compilés sur votre CI comme indiqué ci-dessus.

Facultatif : migrer vers Capacitor plus tard

Vous n'avez pas besoin de quitter Cordova pour obtenir un pipeline fonctionnel et des live updates. La migration est une décision distincte, qui en vaut la peine quand :

  • Vous voulez des builds iOS sans maintenir de runners macOS. Capgo Build compile des apps Capacitor depuis un job CI Linux.
  • Les plugins dont vous dépendez ne reçoivent plus de mises à jour Cordova, mais ont des équivalents Capacitor.
  • Vous voulez le support de Swift Package Manager et les versions actuelles d'Android Gradle Plugin sans patcher les plateformes.

La migration conserve votre www code. Vous ajoutez Capacitor, faites passer les plugins (la plupart des plugins Cordova fonctionnent tels quels) et remplacez ceux qui ont des équivalents natifs Capacitor. Votre ID d'app Capgo et vos canaux restent les mêmes ; seul le plugin updater change, passant de @capgo/cordova-updater vers @capgo/capacitor-updater. Les étapes sont dans Migrer de Cordova vers Capacitor, et le Page de solution : de Cordova à Capacitor couvre l’obtention d’aide à ce sujet. Après la migration, le CI ci-dessus se réduit à un build web, cap sync, et un build request appel par plateforme, comme décrit dans Comparaison des plateformes CI/CD pour les apps Capacitor.

Dépannage des builds Cordova en CI

Erreur Cause et solution
Current working directory is not a Cordova-based project config.xml ou www/ manquant. Exécutez votre build web avant les commandes Cordova, ou créez un fichier vide www/.
No platforms added to this project Les plateformes ne sont pas listées dans package.json. Exécutez cordova platform add localement une fois, puis commitez package.json.
Could not find an installed version of Gradle Récent cordova-android utilise le wrapper Gradle. Mettez à jour la plateforme plutôt que d'installer Gradle globalement.
Unsupported class file major version Le JDK sur le runner ne correspond pas à celui cordova-android attend. Fixez-l’avec setup-java.
No signing certificate "iOS Distribution" found Utiliser Apple Distribution comme identité, et vérifiez que le .p12 contient la clé privée.
errSecInternalComponent Keychain verrouillé ou liste de partitions manquante. Relancez les commandes de configuration du keychain.
Upload rejeté : SDK est trop ancien Runner image uses Xcode older than 26. Select macos-26 ou définissez Xcode avec xcode-select.
Upload Play : Version code has already been used Incrémenter android-versionCode pour chaque upload.

Résumé

Un pipeline Cordova en 2026, c’est un job CI par plateforme : un runner Linux pour l’AAB Android, un runner macOS avec Xcode 26 pour l’IPA, des secrets décodés dans un fichier généré build.json, et des clés API pour les deux stores. N’importe quel CI mainstream peut l’exécuter. Ajoutez @capgo/cordova-updater et une bundle upload un job pour les correctifs web uniquement, et vous disposez des éléments de build, de store et de mise à jour OTA que Appflow et App Center fournissaient auparavant. Passer à Capacitor reste une option pour plus tard, pas une obligation.

Live updates pour les apps Capacitor

Lorsqu'un bug de la couche web est en ligne, déployez le correctif via Capgo au lieu d'attendre des jours l'approbation des stores. Les utilisateurs reçoivent la mise à jour en arrière-plan, tandis que les changements natifs suivent le circuit de validation habituel.

Les derniers articles du blog

Capgo vous offre les meilleures informations pour créer une application mobile vraiment professionnelle.