Salta al contenuto principale

CI/CD per app Cordova nel 2026: guida completa alla configurazione

Configura il CI/CD per app Cordova nel 2026: build firmate AAB per Android e IPA per iOS, upload sugli store, opzioni live update e quando passare a Capacitor.

App Apache Cordova che attraversa una pipeline CI/CD verso App Store e Google Play

La CI/CD per un'app Cordova nel 2026 significa compilare e firmare l'AAB Android su un runner Linux, compilare e firmare l'IPA iOS su un runner macOS e caricare entrambi gli artefatti negli store dalla stessa pipeline. I servizi gestiti che i team Cordova usavano per questo sono stati dismessi o stanno chiudendo, quindi la maggior parte dei team esegue ora la CLI Cordova su una CI generica. Questa guida ti fornisce una configurazione funzionante di GitHub Actions, gli stessi passaggi per altre CI e una panoramica onesta sulle live update e sulle opzioni a lungo termine.

Cosa è cambiato per i team Cordova

Tre eventi hanno plasmato la CI/CD di Cordova:

  • PhoneGap Build è stato dismesso il 1° ottobre 2020.
  • Microsoft App Center è stato ritirato il 31 marzo 2025. Build, distribuzione e il servizio CodePush hostizzato sono terminati con esso.
  • Alternative a Ionic Appflow ha interrotto le nuove vendite a febbraio 2025. I clienti esistenti mantengono l'accesso fino al 31 dicembre 2027.

Cordova stesso funziona ancora. Il progetto Apache rilascia cordova-android e cordova-ios releases, e molte app interne ed enterprise girano su di essa. Il punto debole è il layer gestito: archiviazione delle firme, upload sugli store e aggiornamenti over-the-air. Oggi devi assemblare tutto questo con un servizio CI e qualche tool.

Anatomia di una pipeline Cordova

Fase Android iOS
Runner Linux macOS con Xcode 26
Ripristina cordova prepare (piattaforme e plugin da package.json) stesso
Build web il tuo bundler (Vite, webpack, Angular CLI) in www/ stesso
Native Build Gradle tramite cordova build android --release xcodebuild tramite cordova build ios --release --device
Firma keystore di upload (.jks) certificato di distribuzione (.p12) e provisioning profile
Artefatto .aab per Google Play .ipa per TestFlight e l'App Store
Carica Account di servizio Google Play Developer API Chiave API di App Store Connect

Due regole delle piattaforme si applicano a ogni pipeline:

  • Dal 28 aprile 2026, App Store Connect accetta solo build create con Xcode 26 e iOS 26 SDK o versioni successive. Verifica che la tua cordova-ios versione lo supporti.
  • Google Play richiede upload AAB per le nuove app e aumenta ogni anno il livello minimo di target API. Mantieni cordova-android attualmente è il valore predefinito targetSdkVersion follows.

Passo 1: Rendi il progetto riproducibile

La CI può ricostruire solo ciò che è nel repository. Prima di scrivere qualsiasi workflow:

  1. Commit package.json e il lockfile. Cordova memorizza piattaforme e plugin nel cordova sezione di package.json, quindi cordova prepare li ripristina.
  2. Non committare platforms/ oppure plugins/. Vengono generati.
  3. Installa Cordova CLI come dev dependency in modo che ogni macchina usi la stessa versione:
bun add -d cordova
  1. Sposta i valori di firma da config.xml a un build.json che legge i segreti al momento del build (passo successivo).
  2. Fissa la versione di Node.js in .nvmrc oppure package.json engines.

Passo 2: Firma con build.json

Cordova legge le impostazioni di firma da un build.json file. Committa un build.template.json con placeholder, genera il build.json reale in CI dai secrets e non committare mai il file generato:

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

Il ${...} i placeholder non vengono espansi da Cordova. Il workflow seguente scrive i valori reali con envsubst.

Se non hai ancora un keystore Android, creane uno con keytool o basato su browser Generatore di keystore per Androidbasato su browser. Per iOS, il Generatore di certificati iOS crea una richiesta di firma del certificato e .p12 senza un Mac.

Passo 3: un workflow GitHub Actions

Questo workflow compila entrambe le piattaforme in parallelo su un tag di versione e le carica sui track di test interni.

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

Perché alcune righe sono lì:

  • Due cartelle di profili di provisioning. Xcode 16 e versioni successive leggono i profili da ~/Library/Developer/Xcode/UserData/Provisioning Profiles. Le versioni precedenti di Xcode usavano ~/Library/MobileDevice/Provisioning Profiles. Scrivere entrambi evita l'errore “No profiles for ‘com.example.app’ were found”.
  • set-key-partition-list impedisce a macOS di richiedere l'accesso al keychain, il che bloccherebbe un job CI.
  • Versione JDK. Usa il JDK che cordova-android documenti di rilascio. Le versioni recenti vengono compilate con JDK 17.
  • Numeri di build. Incrementa android-versionCode e ios-CFBundleVersion nella config.xml prima della build, ad esempio dal numero di esecuzione CI, altrimenti gli store rifiuteranno l'upload come duplicato.

Puoi sostituire altool upload per fastlane upload_to_testflight e l'azione Play con fastlane supply se il tuo team usa già fastlane.

Passo 4: La stessa pipeline su altri servizi CI

I comandi non cambiano tra le CI. Cambiano solo la selezione del runner e la sintassi dei secret.

CI Runner Android Runner iOS Note
Azioni GitHub ubuntu-latest macos-26 / macos-latest I minuti macOS costano di più rispetto a Linux sui repository privati
GitLab CI qualsiasi runner Linux runner macOS hosted (beta, Premium e Ultimate) o self-hosted immagini come macos-26-xcode-26
Bitbucket Pipelines Immagine Docker Linux solo Mac self-hosted vedi Guida Bitbucket per iOS
Gitea / Forgejo Runner Linux Mac self-hosted in modalità host vedi Guida Gitea per iOS
Bitrise Stack Linux Stack macOS include gli step Cordova (prepare, archive)
Codemagic Linux Istanze Mac mini documenta i build Ionic Cordova in codemagic.yaml
Azure DevOps ubuntu-latest macOS-latest task per installare certificati e profili

Per una panoramica delle funzionalità, leggi Confronto tra piattaforme CI/CD per app Cordova.

Passaggio 5: Live Updates per Cordova

I Live Update ti permettono di rilasciare fix HTML, CSS e JavaScript senza la revisione degli store. App Center CodePush è terminato a marzo 2025, Appflow Live Updates terminerà il 31 dicembre 2027 e i vecchi plugin community di hot code push non sono più mantenuti. Un'opzione ancora mantenuta è Live updates di Capgo con il @capgo/cordova-updater plugin, che usa lo stesso backend, gli stessi canali e lo stesso CLI dell'updater Capacitor.

Requisiti

  • Cordova CLI 12+
  • cordova-android 13+ e/o cordova-ios 7+ (il plugin si basa sui loro https://localhost/ e app://localhost/ schemes)
  • Non usare cordova-plugin-ionic-webview con esso. Ionic WebView bypassa gli scheme handler di Cordova, quindi i bundle scaricati non verrebbero caricati.

Installa il plugin

Crea l'app in Capgo nello stesso modo di Capacitor, quindi installa il plugin con il tuo 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, e AUTO_UPDATE sono variabili di installazione opzionali. Esegui cordova prepare di nuovo ogni volta che le modifichi.

Conferma ogni lancio

Dopo aver deviceready, il plugin è disponibile come cordova.plugins.Updater. Chiama notifyAppReady() a ogni lancio, oppure il plugin considera il nuovo bundle corrotto e esegue il 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 })
  }
})

Carica i bundle da CI

Aggiungi un job che compila il layer web e lo carica, per modifiche solo 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 }}

Le Live updates sostituiscono solo il bundle web. Aggiungere, rimuovere o aggiornare un plugin Cordova richiede comunque una nuova build per lo store. Capgo confronta i plugin nativi registrati per il bundle live con il tuo progetto e segnala i caricamenti incompatibili; consulta compatibilità live update. La configurazione completa è nella Documentazione updater Cordova.

Per quanto riguarda la build, la Build Capgo documentazione copre solo i progetti Capacitor (carica il progetto nativo generato da cap sync). I binari Cordova continuano a essere compilati sulla tua CI come mostrato sopra.

Opzionale: migrazione a Capacitor in seguito

Non devi abbandonare Cordova per avere una pipeline funzionante e live updates. La migrazione è una decisione separata, utile quando:

  • Vuoi build iOS senza mantenere runner macOS. Capgo Build compila le app Capacitor da un job CI Linux.
  • I plugin su cui dipendi non ricevono più aggiornamenti per Cordova, ma hanno equivalenti Capacitor.
  • Vuoi il supporto a Swift Package Manager e le versioni attuali di Android Gradle Plugin senza patchare le piattaforme.

La migrazione mantiene il tuo www code. Aggiungi Capacitor, sposta i plugin (la maggior parte dei plugin Cordova funziona così com'è) e sostituisci quelli che hanno equivalenti Capacitor-native. L'ID app e i canali di Capgo restano invariati; cambia solo il plugin updater da @capgo/cordova-updater a @capgo/capacitor-updater. I passaggi sono in Migrazione da Cordova a Capacitor, e il pagina di soluzione da Cordova a Capacitor che copre come ottenere supporto. Dopo la migrazione, la CI sopra si riduce a un web build, cap sync, e una build request call per piattaforma, come descritto in Confronto tra piattaforme CI/CD per app Capacitor.

Troubleshooting delle build Cordova in CI

Errore Causa e soluzione
Current working directory is not a Cordova-based project config.xml oppure www/ mancante. Esegui la build web prima dei comandi Cordova, oppure crea un file vuoto www/.
No platforms added to this project Le piattaforme non sono elencate in package.json. Esegui cordova platform add in locale una volta e committa package.json.
Could not find an installed version of Gradle Recenti cordova-android usa il wrapper Gradle. Aggiorna la piattaforma invece di installare Gradle globalmente.
Unsupported class file major version Il JDK sul runner non corrisponde a quello cordova-android previsto. Fissalo con setup-java.
No signing certificate "iOS Distribution" found Usa Apple Distribution come identity e verifica che il .p12 contenga la chiave privata.
errSecInternalComponent Keychain bloccata o partition list mancante. Riesegui i comandi di setup della keychain.
Upload rifiutato: SDK troppo vecchio L'immagine del runner usa Xcode più vecchio di 26. Seleziona macos-26 oppure imposta Xcode con xcode-select.
Upload su Play: Version code has already been used Incrementa android-versionCode per ogni upload.

Riassunto

Un pipeline Cordova nel 2026 è un job CI per piattaforma: un runner Linux per l'AAB Android, un runner macOS con Xcode 26 per l'IPA, segreti decodificati in un file generato build.json, e chiavi API per entrambi gli store. Qualsiasi CI mainstream può eseguirlo. Aggiungi @capgo/cordova-updater e a una bundle upload un job per le correzioni solo web, e hai le parti di build, store e over-the-air che Appflow e App Center fornivano in passato. Passare a Capacitor resta un'opzione per il futuro, non un requisito.

Live updates per le app Capacitor

Quando un bug nel web-layer è live, rilascia la fix tramite Capgo invece di aspettare giorni l'approvazione degli store. Gli utenti ricevono l'update in background, mentre le modifiche native restano nel normale processo di review.

Ultimi articoli dal blog

Capgo ti offre gli insight migliori che ti servono per creare un'app mobile davvero professionale.