[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-cicd-per-flutter-con-github-actions-automatizzare-build-e-deploy":3,"comments-article-cicd-per-flutter-con-github-actions-automatizzare-build-e-deploy":21},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"video_url":10,"status":11,"published_at":12,"meta_title":13,"meta_description":14,"category":15,"author":19},30,"CI\u002FCD per Flutter con GitHub Actions: automatizzare build e deploy","cicd-per-flutter-con-github-actions-automatizzare-build-e-deploy","Impara a configurare una pipeline di integrazione e distribuzione continua per le tue app Flutter usando GitHub Actions: dai test automatici alla generazione di APK e IPA firmati.","## Perché una pipeline CI\u002FCD per Flutter\n\nQuando un progetto Flutter cresce, eseguire manualmente test, analisi statica e build diventa lento e soggetto a errori. Una pipeline di **Continuous Integration \u002F Continuous Delivery** (CI\u002FCD) automatizza queste operazioni ad ogni push o pull request, garantendo che il codice sia sempre analizzato, testato e pronto per la distribuzione.\n\nIn questo articolo vedremo come costruire una pipeline completa con **GitHub Actions**, uno strumento gratuito (nei limiti del piano) e integrato direttamente nei repository GitHub.\n\n## Struttura di un workflow\n\nI workflow di GitHub Actions vivono nella cartella `.github\u002Fworkflows\u002F` sotto forma di file YAML. Ogni workflow è composto da:\n\n- **trigger** (`on`): quando eseguire la pipeline (push, pull_request, tag, ecc.)\n- **jobs**: gruppi di step eseguiti su una macchina virtuale (runner)\n- **steps**: le singole azioni (checkout, setup, comandi shell)\n\n## Analisi statica e test automatici\n\nPartiamo dal job più importante: garantire la qualità del codice. Creiamo il file `.github\u002Fworkflows\u002Fci.yml`:\n\n```yaml\nname: CI\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n  analyze-and-test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n\n      - uses: subosito\u002Fflutter-action@v2\n        with:\n          flutter-version: '3.24.0'\n          channel: 'stable'\n          cache: true\n\n      - name: Installa dipendenze\n        run: flutter pub get\n\n      - name: Verifica formattazione\n        run: dart format --set-exit-if-changed .\n\n      - name: Analisi statica\n        run: flutter analyze\n\n      - name: Esegui i test\n        run: flutter test --coverage\n\n      - name: Carica coverage\n        uses: codecov\u002Fcodecov-action@v4\n        with:\n          files: coverage\u002Flcov.info\n```\n\nAlcuni dettagli utili:\n\n- `subosito\u002Fflutter-action` è l'action de facto standard per installare Flutter; l'opzione `cache: true` velocizza notevolmente le esecuzioni successive.\n- `dart format --set-exit-if-changed` fa fallire il job se il codice non è formattato correttamente.\n- Il flag `--coverage` genera il file `lcov.info` che possiamo caricare su servizi come Codecov.\n\n## Build dell'APK e dell'App Bundle Android\n\nUna volta superati i controlli, possiamo automatizzare la generazione degli artefatti. Aggiungiamo un job che si attiva solo quando pubblichiamo un tag di versione:\n\n```yaml\n  build-android:\n    needs: analyze-and-test\n    if: startsWith(github.ref, 'refs\u002Ftags\u002Fv')\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n\n      - uses: subosito\u002Fflutter-action@v2\n        with:\n          flutter-version: '3.24.0'\n          channel: 'stable'\n          cache: true\n\n      - name: Decodifica keystore\n        run: echo \"${{ secrets.KEYSTORE_BASE64 }}\" | base64 --decode > android\u002Fapp\u002Fupload-keystore.jks\n\n      - name: Crea key.properties\n        run: |\n          echo \"storePassword=${{ secrets.STORE_PASSWORD }}\" >> android\u002Fkey.properties\n          echo \"keyPassword=${{ secrets.KEY_PASSWORD }}\" >> android\u002Fkey.properties\n          echo \"keyAlias=${{ secrets.KEY_ALIAS }}\" >> android\u002Fkey.properties\n          echo \"storeFile=upload-keystore.jks\" >> android\u002Fkey.properties\n\n      - name: Build App Bundle\n        run: flutter build appbundle --release\n\n      - name: Carica artefatto\n        uses: actions\u002Fupload-artifact@v4\n        with:\n          name: release-aab\n          path: build\u002Fapp\u002Foutputs\u002Fbundle\u002Frelease\u002Fapp-release.aab\n```\n\nLa chiave di firma **non deve mai** essere committata nel repository. La soluzione è codificarla in Base64 e salvarla come **secret** di GitHub (`Settings > Secrets and variables > Actions`):\n\n```bash\nbase64 -i upload-keystore.jks | pbcopy   # macOS\nbase64 -w 0 upload-keystore.jks           # Linux\n```\n\n## Build iOS su runner macOS\n\nLa compilazione iOS richiede un runner `macos-latest`. La firma del codice è più complessa perché servono certificati e provisioning profile. Ecco un esempio semplificato per una build non firmata (utile per i test), spesso combinata con strumenti come **fastlane** per la firma completa:\n\n```yaml\n  build-ios:\n    needs: analyze-and-test\n    if: startsWith(github.ref, 'refs\u002Ftags\u002Fv')\n    runs-on: macos-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: subosito\u002Fflutter-action@v2\n        with:\n          flutter-version: '3.24.0'\n          channel: 'stable'\n          cache: true\n      - run: flutter pub get\n      - name: Build iOS (no codesign)\n        run: flutter build ios --release --no-codesign\n```\n\n> **Attenzione ai minuti:** i runner macOS consumano crediti a un fattore moltiplicativo più alto rispetto a quelli Linux. Riserva la build iOS ai soli tag di release.\n\n## Best practice per pipeline affidabili\n\n- **Fissa la versione di Flutter**: evita `channel: stable` senza `flutter-version`, altrimenti aggiornamenti del canale potrebbero rompere la build.\n- **Usa la cache**: `cache: true` sull'action Flutter e la cache di `pub` riducono drasticamente i tempi.\n- **Separa i job**: analisi\u002Ftest da un lato, build dall'altro, sfruttando `needs` per creare dipendenze.\n- **Proteggi i segreti**: keystore, password e API key sempre nei GitHub Secrets, mai in chiaro.\n- **Limita i trigger costosi**: le build native solo su tag o branch di release.\n\n## Distribuzione automatica\n\nPer chiudere il cerchio puoi collegare la pipeline a servizi di distribuzione:\n\n- **Firebase App Distribution** per i tester interni tramite l'action ufficiale.\n- **Google Play** con `r0adkll\u002Fupload-google-play` per il caricamento automatico dell'AAB.\n- **TestFlight \u002F App Store** tramite fastlane e le action Apple.\n\n## Conclusioni\n\nUna pipeline CI\u002FCD ben strutturata trasforma il rilascio da un'operazione manuale rischiosa a un processo affidabile e ripetibile. Con GitHub Actions puoi partire da un semplice job di analisi e test, per poi aggiungere gradualmente build multipiattaforma e distribuzione automatica, mantenendo il codice sempre pronto per la produzione.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002F34039bd5-ac0f-4940-ac9f-c96ad39c0d0b.jpg",null,"published","2026-07-04T04:00:44+00:00","CI\u002FCD Flutter con GitHub Actions: guida pratica","Guida pratica per configurare una pipeline CI\u002FCD per Flutter con GitHub Actions: analisi, test, build Android\u002FiOS firmate e deploy automatico.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1785219603535]