Utilisation des fonctionnalités gratuites des actions Github pour CI / CD sur un projet Flutter

GitHub Actions est un outil pour automatiser les actions de routine avec un référentiel et vous aider à créer un CI / CD pour votre projet.



Les utilisateurs de GitHub disposent de 2000 minutes par mois pour exécuter des actions GitHub sur l'infrastructure de service. Faisons bon usage de ce temps libre.



Je donne des instructions aux développeurs d'applications Flutter: comment exécuter des tests et un analyseur de code pour chaque pull request à l'aide d'actions GitHub, créer un artefact et le déployer pour le tester dans Firebase.







Une personne s'habitue très rapidement aux bonnes choses. Et il s'y habitue tellement qu'il ne pense même pas au fait qu'il n'en a pas toujours été ainsi. Comme le dit la vieille anecdote sur un homme et une chèvre, la réalisation de tous les délices de la vie se produit au moment même où vous êtes privé de ces mêmes délices.



Si votre projet de travail se porte bien avec CI / CD, vous êtes une personne chanceuse.

Peut-être que vous travaillez dans une startup et avez soigneusement configuré tous les pipelines et hooks de vos propres mains.



Il se peut que toute une équipe DevOps s'occupe de votre bien-être: chaque mois, elle vous plait avec de nouvelles intégrations, la fusion du temps de construction sous nos yeux et des techniques avancées pour déployer des assemblages dans tous les endroits imaginables et inconcevables.



Ce n'est pas important. L'essentiel est que vous soyez toujours sûr que vos builds sont viables, et en même temps vous êtes vous-même soulagé de beaucoup de tâches routinières très ennuyeuses, dont la pensée plonge toujours les développeurs dans la mélancolie et le découragement. En passant, je serai heureux si vous écrivez dans les commentaires à quand remonte la dernière fois que vous avez modifié manuellement le statut d'un problème dans Jira?



Quitter votre zone de confort



Où quittent-ils la zone de confort et, surtout, pourquoi? Beaucoup de raisons. Une connaissance m'a demandé de vous aider à rédiger une petite application pour votre propre bar, vous avez enfin trouvé le temps de mettre en œuvre un projet animalier de vos rêves ou avez décidé de libérer une bibliothèque née accidentellement dans le cadre du projet. Enfin, vous et votre collègue venez de décider d'écrire un petit exemple de projet pour l'atelier.



Je parie que dans n'importe lequel des scénarios, votre inspiration à partir de nouvelles tâches intéressantes se heurtera rapidement à la dure réalité du développement logiciel dans un "environnement sans air" (oui, à un moment donné, vous aurez besoin d'un collecteur intelligent comme l'air).



"CI / CD est difficile ..."



Que vous dites-vous habituellement dans de tels moments? «Je ne comprends pas ça! J'écris juste un frontend / téléphone portable et je ne sais rien de votre Jenkins! " Et si je vous disais que vous n'avez pas besoin de savoir quoi que ce soit de ce genre?



Oui, il vous suffit de pouvoir créer votre projet à l'aide des commandes de la console - et c'est tout. Vous pouvez grandement simplifier votre vie, même s'il s'agit d'un petit projet personnel, et non d'un monstre géant multi-modules déjà difficile à digérer un IDE.



Github Actions est si simple que même votre grand-mère le mettrait en place sans trop de difficulté.



Alors, de quoi parle le post?



Si tout est si simple, pourquoi perdre du temps à lire cet opus? Je répondrai avec une liste à puces:



  • Flutter. CI . , Flutter- . ,

  • . Github Actions —  . 2 000 ( ). - , .

  • . Flutter Android iOS , - . , , , .



c CI/CD , . . ($).


Github Actions, !



Github Actions est un service qui vous permet d'automatiser le flux de travail de votre référentiel. Tout ce que vous faites manuellement avec votre projet - autre que l'écriture directe de code - vous pouvez déléguer aux actions Github. Si vous préférez vous familiariser immédiatement avec les sources primaires, consultez la documentation officielle .



Souvent, nous ne savons même pas du tout ce dont nous avons besoin pour automatiser. L'équipe n'a pas le temps de comprendre l'API complexe du service, puis d'écrire et de déboguer la solution à partir de zéro. Marketplace résout ce problème : près de 5000 actions prêtes à l'emploi y sont publiées, qui résolvent de nombreuses tâches typiques (par exemple, l' envoi de notifications sur les événements dans Telegram , l' analyse des sources du projet pour la dette technique ,définir des étiquettes sur PR en fonction des fichiers modifiés ). Mauvaise nouvelle: beaucoup d'entre eux sont des shareware - avec des limites d'utilisation assez strictes.



Le processus de travail



Tout dans Github Actions tourne autour des flux de travail . Chaque flux de travail répond à deux questions: que faire et quand le faire.



Que faire . Il existe d'innombrables options ici: vous pouvez créer, tester et déployer vos builds à l'aide de scripts prêts à l'emploi ou créés par vous-même. En savoir plus sur la configuration du flux de travail



Quand le faire . Vous pouvez déclencher des workflows sur des événements qui se produisent dans le référentiel. Créer une pull request, pousser une balise de validation ou même ajouter une nouvelle étoile à votre projet. Liste complète des hooks



Si le workflow doit être exécuté non pas sur un événement, mais à un certain moment ou à une certaine fréquence, la syntaxe cron POSIX est à votre disposition .En savoir plus sur les événements réguliers



Le référentiel peut avoir autant de flux de travail différents que vous le souhaitez en même temps. Chaque flux de travail est décrit dans un fichier YAML distinct, dont chacun doit être stocké dans le répertoire .github / workflows à la racine de votre référentiel. En savoir plus sur la syntaxe des workflows



Environnement d'exécution



Github Actions propose deux options pour exécuter vos workflows:



  • Github-hosted runners — , . Windows, Linux macOS. , Codemagic, ( ). , , ;

  • Self-hosted runners — , . Github , .



Dans mon article, je me concentrerai sur la première option. Nous suivons le chemin le plus simple possible, non?



Configuration du flux de travail de base pour Flutter



Avant de commencer à configurer le flux de travail, nous devons nous mettre d'accord sur deux choses.



Premièrement, le rôle principal du workflow sera de compliquer la décomposition de la base de code. Le code qui ne se construit pas, qui contient des problèmes potentiels ou qui rompt les tests ne devrait pas entrer dans le courant dominant.



Deuxièmement: il peut y avoir des subtilités dans ma configuration qui ne seront pas pertinentes pour votre projet. Je vais essayer de les expliquer. Cependant, si vous utilisez cet article comme guide, empruntez soigneusement.



Enfin, décidons ce que notre flux de travail doit faire. Nous avons besoin d'un plan pour nous aider à avancer dans la bonne direction.



Étape par étape pour terminer l'assemblage



Le plan ci-dessus peut être utilisé comme liste de contrôle lors de la configuration de votre propre flux de travail. Nous devons:



  1. donnez au flux de travail un nom significatif;
  2. indiquer à quel événement notre workflow commencera;
  3. décider de la machine avec quelle configuration elle démarrera;
  4. Décidez des étapes de notre flux de travail:


  • vérifier le projet,
  • installer Java;
  • installer Flutter (comme vous vous en souvenez, chaque fois que nous avons une instance propre à notre disposition),
  • télécharger des packages de projets,
  • démarrer un analyseur statique,
  • exécution de tests,
  • l'assemblage de construction lui-même,
  • déployez la build à un endroit où les testeurs peuvent l'obtenir.


Maintenant, notre travail a pris une forme tangible. Passons à la mise en œuvre.



À quoi ressemblera notre flux de travail à la toute fin
— . , , .



name: Flutter PR

on:
 pull_request:
   branches:
     - "dev/sprint-**"
   paths-ignore:
     - "docs/**"
     - "openapi/**"
     - ".vscode/**"

jobs:
 build:
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@v1
     - uses: actions/setup-java@v1
       with:
         java-version: "12.x"

     - uses: subosito/flutter-action@v1
       with:
         channel: "stable"

     - run: sh ./scripts/flutter_pub_get.sh

     - run: sh ./scripts/flutter_analyze.sh

     - run: flutter test

     - run: flutter build apk --release

     - uses: actions/upload-artifact@v1
       with:
         name: APK for QA
         path: build/app/outputs/apk/dev/debug/apk_name.apk

     - name: Upload artifact to Firebase App Distribution
        uses: wzieba/Firebase-Distribution-Github-Action@v1
        with:
          appId: ${{ secrets.FIREBASE_ANDROID_PROD_APP_ID }}
          token: ${{ secrets.FIREBASE_TOKEN }}
          groups: testers
          file: build/app/outputs/apk/dev/debug/apk_name.apk
          debug: true




Nom



De toute évidence, nous devons nommer notre flux de travail afin que le nom reflète son essence aussi précisément que possible. Le nom ( docs ) est la première chose que nous voyons dans la console Actions lorsque le workflow est exécuté. Pourquoi j'ai nommé mon flux de travail de cette façon, vous le découvrirez dans un instant.







name: Flutter PR


Événement déclencheur



Le bloc "on" ( docs ) nous permet de spécifier un ou plusieurs événements, lors de l'enregistrement desquels nous voulons démarrer notre workflow. De plus, certains événements peuvent être affinés. 



Quel événement choisir? Afin de ne pas manquer une ventilation, vous pouvez spécifier au moins tous les événements existants. Ensuite, l'assemblage se déroulera presque continuellement, mais voulons-nous cela? Non, car dans ce cas, la limite de notre plan tarifaire gratuit se terminera fantastiquement rapidement. Nous chercherons la solution optimale.



Supposons que notre projet adhère aux accords selon lesquels le code ne peut pas être poussé directement dans la branche principale du projet - uniquement via la création d'une pull request. Il est logique que notre workflow réponde à la création d'une pull request et construise un projet à partir d'une base de code modifiée:



on: pull_request


$ Cela suffit pour travailler, mais la solution n'est pas encore très optimale. La compilation sera déclenchée à chaque pull request créé. Ceci est redondant, car nous ne sommes intéressés que par les pull requests dirigées vers la branche principale du projet. La syntaxe des actions Github nous permet de spécifier les noms (ou masques) des branches qui nous intéressent.



on:
 pull_request:
   branches:
     - "dev/sprint-**"


$ Et encore une fois, nous cherchons des moyens d'optimiser le processus. Il existe des fichiers qui, même en théorie, ne peuvent pas nuire à votre projet: la documentation du projet, Swagger, le style de code général et les paramètres IDE. Heureusement, nous avons la possibilité d'ignorer ces fichiers par le masque de chemin. En conséquence, le bloc «on» ressemblera à ceci:



on:
 pull_request:
   branches:
     - "dev/sprint-**"
   paths-ignore:
     - "docs/**"
     - "drz-swagger/**"
     - ".vscode/**"


Important : ne faites une pull request que si vous êtes prêt à la fusionner. Chaque poussée suivante vers une demande d'extraction déjà créée redémarrera le flux de travail.

Configuration du travail







Enfin, nous sommes prêts à configurer le travail ( docs ). Il est maintenant temps de clarifier le rôle du travail dans le flux de travail.



Chaque flux de travail doit inclure au moins un travail. C'est un travail qui contient une description étape par étape des étapes que nous effectuons avec notre projet. Le nombre de travaux dans un flux de travail n'est pas limité, ainsi que le nombre d'étapes dans un travail. Par défaut, tous les travaux sont exécutés en parallèle, sauf si la dépendance d'un travail sur les résultats d'un autre est spécifiée. Notre projet aura le seul travail qui sera responsable de la construction du projet.



Mise en place de l'environnement



Chaque fois que le flux de travail s'exécute sur une instance de machine virtuelle propre. La seule chose que nous pouvons choisir est le système d'exploitation qui sera installé sur cette machine. Que choisir?



Il est tentant de choisir macOS, car nous prévoyons de construire une application Flutter pour les plateformes cibles: Android et iOS. Mauvaises nouvelles. Une minute d'utilisation d'une instance avec macOS équivaut à dix (10 !!!) minutes d'utilisation d'une instance avec Ubuntu. Dans une instance avec Windows, dans notre cas, cela ne sert à rien, car il ne sera toujours pas possible d'assembler un assembly iOS là-bas, et son temps d'utilisation est deux fois plus cher qu'une instance avec Ubuntu. En savoir plus sur la facturation



$Comment pouvons-nous nous assurer que nos 2000 minutes gratuites ne se transforment pas en 200? Il n'y a pas de bonne solution. J'ai décidé de ne pas créer de build sur iOS lors de la création d'une pull request. Cela affectera potentiellement la stabilité de la version iOS. Il existe également une option de compromis: créer une version iOS sur macOS uniquement lors de la modification de pubspec.yaml ou de tout fichier du répertoire / ios , dans d'autres cas, ne créer qu'une version Android sur une instance avec Ubuntu. Cela peut être fait par analogie avec la façon dont nous configurons les fichiers ignorés pour le bloc «on» .



jobs:
 build:
   runs-on: ubuntu-latest


Vous pouvez voir les spécifications techniques , ainsi qu'une liste des logiciels installés «prêts à l'emploi» . Flutter et Java, malheureusement, ne sont pas inclus dans cette liste. Ils devront être installés manuellement chaque fois que le workflow est exécuté.



Ne soyez pas pressé de vous fâcher. Des actions prêtes viendront à notre secours, que nous pouvons utiliser dans les étapes de notre travail. Nous en utiliserons deux:



  • actions / setup-java - l'action officielle de configuration de l'environnement Java;

  • subosito / flutter-action est une action non officielle de téléchargement et d'installation du SDK Flutter. Il a bien fait ses preuves: il vous permet de faire tout ce dont vous avez besoin - par exemple, spécifier le canal de framework souhaité ou passer à une version spécifique du SDK.



steps:
      - uses: actions/setup-java@v1
        with:
          java-version: "12.x"

      - uses: subosito/flutter-action@v1
        with:
          channel: "stable"


Cloner un référentiel



Nous avons une instance propre d'une machine louée à Github pendant quelques minutes. À l'étape précédente, nous avons installé tous les logiciels nécessaires dessus. Nous devons maintenant cloner le référentiel source de notre projet. Pour ce faire, nous utiliserons un outil prêt à l'emploi:



  • actions / checkout est l'action officielle pour cloner un référentiel avec une tonne de paramètres dont nous n'aurons pas besoin dans la plupart des cas. Puisque le flux de travail s'exécute directement sur le référentiel que nous clonons, nous n'avons pas besoin de le spécifier explicitement.



- uses: actions/checkout@v1


Chargement des dépendances



Jusqu'à présent, nous n'avons pas mis en œuvre d'étapes de nos propres mains, mais uniquement utilisé ce que j'offre des actions toutes faites. Nous passons maintenant à la mise en œuvre de la phase de construction active de notre projet, il est donc temps d'écrire vous-même la mise en œuvre de l'étape.



Avant de construire, nous devons télécharger tous les packages répertoriés dans le bloc des dépendances de notre fichier pubspec.yaml, ainsi que toutes leurs dépendances transitives. Pour ce faire, le SDK Flutter propose une commande simple prête à l'emploi flutter pub get. La mise en œuvre de l'étape peut consister à appeler une commande de terminal. Dans ce cas, l'étape suivante ne sera appelée qu'à la fin de cette commande.



- run: flutter pub get


Si votre projet a une structure complexe et contient un certain nombre de packages de fléchettes connectés localement, vous serez confronté à un problème. Il est flutter pub getimpossible de construire un projet sans un appel explicite pour chacun de ces packages. Dans mon projet, ces packages sont collectés dans le dossier / core situé dans le répertoire racine. Vous trouverez ci-dessous un script qui résout ce problème. Il est décrit dans le fichier flutter_pub_get.sh dans le dossier / scripts du même répertoire racine.



flutter pub get
cd core
for dir in */ ; do

    echo ${dir}
    cd ${dir}
    pwd
    flutter pub get
    cd ..
    pwd
    if [ "$#" -gt 0 ]; then shift; fi
    # shift
done


Puisque l'implémentation de step peut être n'importe quelle commande de terminal, rien ne nous empêche d'exécuter notre script shell.



- run: sh ./scripts/flutter_pub_get.sh


Analyse de code statique



Flutter nous invite à utiliser une commande intégrée flutter analyzepour exécuter un analyseur statique. Cela aidera à identifier les problèmes potentiels avec notre base de code à un stade précoce: avant qu'un bogue n'atteigne la production, ou que notre code ne se transforme en un désordre illisible et non pris en charge.



Nous aurions pu profiter de la fonctionnalité prête à l'emploi, mais hélas, le comportement d'équipe par défaut flutter analyzeprésente un défaut qui ruine notre flux de travail au mauvais moment. 



Les problèmes détectés par l'analyseur sont classés en trois niveaux de gravité: info, avertissement, erreur. Dans ce numéroil est décrit que même si lors de l'analyse seuls des problèmes de classe info sont trouvés (et qu'il ne vaut pas toujours la peine de passer du temps à les résoudre ici et maintenant), la commande renvoie le code "1", à la suite de quoi votre assembly plantera.



Je suggère d'utiliser le script suivant comme solution temporaire. À partir de maintenant, l'assemblage ne plantera que s'il y a des problèmes avec le niveau d' erreur :



OUTPUT="$(flutter analyze)"
echo "$OUTPUT"
echo
if grep -q "error •" echo "$OUTPUT"; then
    echo "flutter analyze found errors"
    exit 1
else
    echo "flutter analyze didn't find any errors"
    exit 0
fi


Nous exécutons le script shell à l'étape suivante de notre workflow:



- run: sh ./scripts/flutter_analyze.sh


Exécution de tests



Si vous avez des tests dans votre projet, vous êtes sur la bonne voie! Pour que les tests fonctionnent, il ne suffit pas de les écrire - ils doivent être exécutés régulièrement afin de corriger les failles d'implémentation à temps ou de les mettre à jour si nécessaire. Par conséquent, à l'étape suivante, nous mettrons en œuvre



- run: flutter test


Attention: les classes de test vides ne contenant aucun test implémenté planteront l'ensemble du workflow. Il n'y a qu'une seule solution: ne déclarez pas de classes de test tant que vous n'êtes pas prêt à implémenter au moins un test en son sein.



Construire et signer



Tous les travaux préparatoires sont terminés. Nous avons vérifié que le code ne contient probablement pas de problèmes évidents. Nous passons maintenant à l'étape la plus importante - la production de l'artefact. En d'autres termes, nous allons créer l'APK.



L'assemblage lui-même est extrêmement simple à mettre en œuvre. Nous avons à notre disposition la commande de terminal flutter build, qui est extrêmement configurable et vous permet de créer un artefact pour une saveur spécifique, le fichier principal, ABI. Nous ne couvrons pas ces nuances dans l'article, utilisez donc des indicateurs de commande supplémentaires si nécessaire.



- run: flutter build apk --release


Notre objectif est de faire signer un assembly avec une clé de version. Et à ce stade, nous devrons résoudre le problème de sécurité, car nous devons stocker le keystore de version quelque part, ainsi que tous ses alias et mots de passe.



Github vous permet de stocker en toute sécurité des valeurs de chaîne dans un référentiel Secrets dédié . Les données disponibles ici sont stockées dans le référentiel approprié et peuvent être lues par programme à partir de n'importe quelle étape de votre flux de travail. Dans le même temps, les valeurs ne peuvent pas être vues via l'interface Web Github. Seule la suppression ou l'écrasement est autorisée.







Cela semble être une bonne solution pour les alias et les mots de passe, surtout si vous êtes votre propre service de sécurité, mais qu'en est-il du fichier * .jks lui-même? Le pousser vers le référentiel ne semble pas être une bonne idée, même si votre référentiel est privé. Malheureusement, Github ne fournit aucun moyen sécurisé de stocker des fichiers, vous devez donc éviter.



Ce serait bien de représenter notre fichier keystore sous forme de chaîne. Et c'est réel - il vous suffit de l'encoder en base64. Pour ce faire, ouvrez un terminal dans le répertoire contenant notre fichier * .jks et exécutez la commande suivante. Ensuite, un fichier texte sera créé à partir duquel vous pourrez copier la représentation base64 de notre keystore, puis ... l'enregistrer dans Github Secrets.



openssl base64 < key_store_filename.jks | tr -d '\n' | tee keystore.jks.base64.txt


Maintenant que nous avons tous les composants nécessaires à une signature d'assemblage réussie en place, nous allons procéder à la configuration de l'étape. Dans le bloc env, nous déclarons toutes les variables d'environnement pour cette étape particulière. Nous prendrons les valeurs de ces variables dans Secrets.



- run: flutter build apk --release
        env:
          STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
          KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
          KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
          STORE_FILE: ${{ secrets.STORE_FILE }}


Dans notre hôte Android, nous devons décrire la configuration de l'assembly de telle sorte que nous ayons la possibilité de signer le fichier * .apk dans CI sans perdre la possibilité de créer l'assembly signé localement. Le fichier keystoreConfig.gradle est responsable de ce moment .



Si le fichier keystore_release.properties est trouvé, on sait que la construction se produit localement, ce qui signifie que vous pouvez initialiser toutes les propriétés keystoreConfig en les lisant simplement à partir du fichier. Sinon, l'assemblage a lieu dans CI, ce qui signifie que la seule source de données sensibles est Github Secrets.



ext {
   def releaseKeystorePropsFile = rootProject.file("keystore/keystore_release.properties")
   if (releaseKeystorePropsFile.exists()) {
       println "Start extract release keystore config from keystore_release.properties"
       def keystoreProps = new Properties()
       keystoreProps.load(new FileInputStream(releaseKeystorePropsFile))
       keystoreConfig = [
               storePassword: keystoreProps['storePassword'],
               keyPassword  : keystoreProps['keyPassword'],
               keyAlias     : keystoreProps['keyAlias'],
               storeFile    : keystoreProps['storeFile']
       ]
   } else {
       println "Start extract release keystore config from global vars"
       keystoreConfig = [
               storePassword: "$System.env.STORE_PASSWORD",
               keyPassword  : "$System.env.KEY_PASSWORD",
               keyAlias     : "$System.env.KEY_ALIAS",
               storeFile    : "$System.env.STORE_FILE"
       ]
   }
   println "Extracted keystore config: $keystoreConfig"
}


Et voici à quoi ressemble le fichier keystore_release.properties :



storePassword={___}
keyPassword={___}
keyAlias={___}
storeFile=../keystore/keystore.jks


La dernière étape du fichier build.gradle de notre hôte Android consiste à appliquer le fichier keystoreConfig à notre configuration de signature de build de version:



android {
   signingConfigs {
       release {
           apply from: '../keystore/keystoreConfig.gradle'

           keyAlias keystoreConfig.keyAlias
           keyPassword keystoreConfig.keyPassword
           storeFile file(keystoreConfig.storeFile)
           storePassword keystoreConfig.storePassword
       }
   }
}


L'assemblage signé est déjà entre nos mains! Mais comment l'étendre à vos collègues pour les tests?



Déchargement



Github Actions vous permet de configurer le téléchargement d'artefacts vers presque tous les outils connus pour la distribution d'assemblys, mais nous n'envisagerons que deux options:



  • Stockage Github - le moyen le plus simple de télécharger des assemblys sur votre propre stockage Github, qui fonctionne hors de la boîte, mais présente certaines limitations;

  • Firebase App Distribution est un service de l'écosystème Firebase qui a remplacé la version bêta par Crashlytics. L'intégration est un peu plus difficile à configurer, mais le service lui-même est beaucoup plus pratique à utiliser.





Github Storage

Github Storage s'intègre facilement grâce à l'action officielle. Il vous suffit de spécifier le nom de l'assembly tel que vos collègues le verront dans l'interface Web, ainsi que le chemin du fichier * .apk compilé dans CI.



- uses: actions/upload-artifact@v1
        with:
          name: APK for QA
          path: build/app/outputs/apk/dev/debug/apk_name.apk


Le problème principal est l'espace de stockage limité. Sur le plan gratuit, vous ne disposez que de 500 Mo. Le plus étrange, c'est que je n'ai trouvé aucun moyen d'effacer manuellement tout le stockage en une seule fois via l'interface Web, alors je me suis sorti de la situation en ... écrivant un flux de travail séparé chargé uniquement de nettoyer le stockage des artefacts moussus.



Le workflow s'exécute tous les jours à 1 h du matin et supprime tous les artefacts de plus d'une semaine:



name: Github Storage clear

on:
  schedule:
    - cron: '0 1 * * *'

jobs:
  remove-old-artifacts:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: Remove old artifacts
        uses: c-hive/gha-remove-artifacts@v1
        with:
          age: '1 week'


Firebase App Distribution

Comme pour Firebase App Distribution, j'ai utilisé l'action prête à l'emploi wzieba / Firebase-Distribution-Github-Action pour l'intégrer



- name: Upload artifact to Firebase App Distribution
        uses: wzieba/Firebase-Distribution-Github-Action@v1
        with:
          appId: ${{ secrets.FIREBASE_ANDROID_PROD_APP_ID }}
          token: ${{ secrets.FIREBASE_TOKEN }}
          groups: testers
          file: build/app/outputs/apk/dev/debug/apk_name.apk
          debug: true


Pour que l'action fonctionne correctement, elle doit passer des paramètres:



  • appId - identificateur d'application, qui peut être trouvé dans les paramètres du projet Firebase;







  • token - un jeton pour l'authentification à votre projet FIrebase, qui est requis pour charger l'assembly dans le service. Vous pouvez obtenir un jeton uniquement via la CLI Firebase, pour laquelle vous pouvez en savoir plus dans la documentation officielle ;

  • file - chemin vers le fichier * .apk compilé sur CI;

  • groups - ce paramètre est facultatif, mais vous permet de spécifier l'alias du groupe de testeurs vers lequel l'assembly téléchargé sera automatiquement partagé.



Lancement et observation



Notre flux de travail le plus simple est prêt! Il ne nous reste plus qu'à déclencher l'événement déclencheur et à observer la progression du flux de travail.



Conseils et mots d'adieu



Vous pouvez désormais profiter de tous les avantages d'un simple mécanisme CI / CD sur votre projet Flutter, quelle que soit sa taille, son intensité de développement ou votre portefeuille.



Enfin, voici quelques conseils et observations que j'ai formulés en travaillant sur ce flux de travail:



  • workflow . workflow , , . - . , - workflow , .

  • step’ shell-. workflow . . .

  • Run Duration workflow. workflow , . workflow , step’. . Flutter SDK . — 5-6 .



Il y a encore des tonnes d'améliorations et d'améliorations potentielles à venir. Écrivez dans les commentaires vos idées pour améliorer le flux de travail. Que vous manque-t-il personnellement? Peut-être que la mise en œuvre des idées les plus intéressantes des lecteurs constituera la base du prochain article sur le sujet.



Tous les scripts et flux de travail se trouvent dans le référentiel avec l'application de test .



Merci de votre attention.



PS Notre équipe Surf publie de nombreuses bibliothèques utiles pour Flutter. Nous les téléchargeons dans le référentiel SurfGear .



All Articles