Votre APK qui va bientĂŽt finir sur Firebase
Votre APK qui va bientĂŽt finir sur Firebase

Cet article fait partie d’une sĂ©rie de 4.
L’objectif est de dĂ©crire comment faire pour optimiser un maximum le dĂ©ploiement d’une application Android en automatisant les Ă©tapes đŸ€–.

1 – 📩 Builder et signer son application Android
2 – 🚀 Automatiser les builds avec Fastlane
3 (1) – đŸ”„ DĂ©ployer son application sur Firebase
3 (2) – 🛳 DĂ©ployer son application sur le Play Store
4 – đŸ€– Utiliser Gitlab pour dĂ©ployer son application lors d’un tag de release sur git.

Dans la troisiĂšme partie de cette sĂ©rie, nous allons voir comment utiliser fastlane pour dĂ©ployer notre application sur Firebase đŸ”„ et la rendre dispo Ă  nos testeurs.

Cet article est looooong, alors prĂ©parez vos cafĂ©s et thĂ©s, on en a pour un moment ☕


⏰ Un petit rĂ©cap ?

Dans les 2 précédents articles, nous avons vu comment

Soit 50% de notre automatisation en 2 Ă©tapes

  • Build 📩
  • DĂ©ploiement 📹

Aujourd’hui, on va donc s’attaquer Ă  la deuxiĂšme Ă©tape: le dĂ©ploiement 📹 !

Vous le savez bien, la distribution d’une application en bĂȘta-test est une Ă©tape importante dans la vie d’un projet.
En effet, elle permet aux testeurs/clients/po de l’utiliser et de faire des retours aux Ă©quipes.

Dans le monde Android, il existe plusieurs de moyens de faire ça:

  • Un store privĂ© (on va considĂ©rer que Firebase rentre dans cette catĂ©gorie)
  • Le Play Store
  • Via email (oui oui, j’vous jure certains envoient les APK)
  • Avec dĂ©pĂŽt sur un FTP (ou Drive, WeTransfer on peut tout imaginer)
  • … je suis certain que j’en loupe

Ce qu’on va faire c’est se concentrer sur l’utilisation de Firebase đŸ”„.

Nous allons donc voir, ensemble, comment déployer notre application avec Firebase App Distribution.


đŸ”„ Configuration de Firebase

La premiĂšre Ă©tape de notre parcours, c’est de configurer Firebase pour utiliser son service avec notre application.

Pour faire cela, nous allons réaliser 3 choses

  1. En premier lieu, la crĂ©ation de l’application dans Firebase (pour activer les bons services)
  2. Ensuite, l’ajout des diffĂ©rentes empreintes de certificat de notre application (voir l’article sur la signature des applications)
  3. Pour finir, rĂ©aliser un premier dĂ©ploiement sur l’interface.

Si vous avez déjà une application dans firebase, vous pouvez passer cette étape en cliquant ici

🚒 CrĂ©ation de l’application dans Firebase

Pour créer notre application dans Firebase, cela se fait en 2 phases:

  • La crĂ©ation du projet
  • Dans ce projet, la crĂ©ation de l’application (1 projet peut avoir plusieurs apps)

☄ CrĂ©ation du projet

Bouton ajouter un projet sur Firebase

Rendez-vous sur votre console firebase et ajoutez un projet

Rentrez un nom de projet, puis activez (ou pas) Google Analytics (et créez un compte ou pas en fonction de).

Laissez Firebase đŸ”„ travailler, et vous voilĂ  sur le dashboard de votre projet.

đŸ“Č CrĂ©ation de l’application

Dashboard Firebase, ajouter une application


La premiĂšre Ă©tape Ă  faire dans notre projet Firebase đŸ”„ est d’ajouter notre application Android.

Pour cela, on va cliquer sur l’icĂŽne Android.

Commencons par Enregistrer notre application.

Suivez les différentes demandes de Firebase pour créer votre projet.

Pour ce qui est du certificat de signature de débogage, si vous vous souvenez bien, on en parle dans la partie 1 builder et signer son application en release.

Par défaut, ce certificat de signature de débogage, est situé dans ~/.android/debug.keystore

Pour obtenir la clé SHA-1, utilisez la commande suivante:

keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android 
Retour de la commande keytool sur le certificat de debug
Le résultat du keytool list

Copiez collez la ligne SHA-1 dans le champ de Firebase et cliquez sur Enregister l’application.

👆 Les empreintes de certificats

Téléchargement du google-services.json


ArrivĂ©s lĂ , il vous propose de tĂ©lĂ©charger le fichier google-services.json et de l’ajouter Ă  votre projet.

Vous pouvez le faire et terminer le tuto avec l’Ajout du SDK Firebase et le premier lancement.

Ils utilisent Android Studio avec un thÚme clair, je soupsone que ça soit le marketing qui ait donné les images à intégrer.

Configurer notre application sur Firebase

Revenons à notre dashboard de projet, désormais vous avez votre application qui est listée.

Cliquez sur la roue dentée de configuration

Ajouter des empreintes de certificat

Vous devez ĂȘtre redirigĂ©s vers la page de configuration du projet.

En bas de page vous verrez qu’il y a une option pour rajouter d’autres empreintes de certificat.

Vous allez me dire Ă  quoi cela sert ? Et bien Ă  plusieurs choses.
Si votre application utilise Firebase pour certains services

  • Authentification
  • Crashlytics
  • Analytics
  • Autres

Firebase đŸ”„ va se baser sur ces clĂ©s de certificats pour autoriser ou non l’accĂšs Ă  l’API.

A vous la 403 si jamais votre clĂ© de debug ne figure pas dans la liste…
Mais aussi si votre clĂ© de release n’y figure pas !! đŸ’€đŸ˜±

2 choses Ă  faire donc:

  • Si vous ĂȘtes plusieurs sur le projet, ajoutez toutes les clĂ©s de debug des dĂ©veloppeurs
  • Ajoutez la clĂ© de certificat de release

Pour cela, utilisez la mĂȘme commande qu’au-dessus mais sur votre certificat de release, en utilisant bien

  • L’alias utilisĂ©
  • Le mot de passe d’alias
  • Le mot de passe du store

NDLR si vous avez suivi la premiĂšre partie de ces articles, toutes ces infos sont dans le fichier key.properties

keytool -list -v -keystore STORE_FILE -alias KEY_ALIAS -storepass STORE_PASSWORD -keypass KEY_PASSWORD 

Et ajoutez la SHA-1 qui sort en réponse à cette commande.

Une fois que cela est fait, tĂ©lĂ©chargez et mettez Ă  jour votre google-services.json (mĂȘme si pas grand-chose n’a dĂ» changer).

Vous voilĂ  prĂȘt pour un premier dĂ©ploiement ! 🎉

🧳 Un premier dĂ©ploiement

Pour activer l’App distribution dans Firebase, rendez-vous dans le menu gauche QualitĂ© puis App Distribution.

De lĂ  validez les conditions et cliquez sur commencer.

Nous voilĂ  prĂȘts Ă  dĂ©ployer !

📩 Une version = Un APK

Pour commencer, on remarque que (Ă  date) Firebase App Distribution fonctionne avec des APK.

Dans le monde Android aujourd’hui, on fonctionne plus avec des App Bundle. Un format plus adaptĂ© Ă  la rĂ©duction de taille des APK tĂ©lĂ©chargĂ©s par nos utilisateurs.

Oui mais pour que cela fonctionne, en fait, le Play Store va gĂ©nĂ©rer autant d’APK que de possibilitĂ©s (langues, rĂ©solution, architecture, etc…).

Firebase n’a ni le temps, ni le besoin de faire ce genre de choses.
En effet, c’est consommateur de ressources et en plus on cible de la bĂȘta-test, alors ils peuvent bien se taper un APK de 150Mo non ?

1ere remarque: Nous devrons builder nos APK avec gradle assemble et pas bundle

🎳 Les groupes de test

Pour faire installer notre application et la partager à nos testeurs, il existe 2 possibilités

  • Le groupe de test
  • Le lien d’invitation

Commençons par le groupe de test.

Le groupe de test est un moyen simple d’ajouter des personnes Ă  vos tests, crĂ©ez un groupe, nommez le et enregistez.

NDLR: Je vous déconseille de mettre des testeurs hors groupe.

De lĂ  vous pouvez ajouter des emails dans ce groupe, ces personnes seront informĂ©es qu’ils sont invitĂ©s Ă  participer aux tests et pourront tĂ©lĂ©charger l’app d’installation de firebase pour tĂ©lĂ©charger nos versions.

Groupe de testeurs sur firebase
Les testeurs dans leurs groupes

NDLR: Vous pouvez avoir plusieurs groupes, pour donner accÚs à certaines fonctionnalités ou pas (ou par exemple avoir un Alpha test, un Beta test, ou gérer vos flavors)

NDLR: Une fois qu’un testeur est ajoutĂ©, il a automatiquement accĂšs Ă  la derniĂšre bĂȘta disponnible pour son groupe

Un point intĂ©ressant dans la crĂ©ation de groupes, c’est que vous pouvez le laisser vide et le remplir plus tard.

En effet, parlons maintenant du lien d’invitation, vous pouvez gĂ©nĂ©rer un lien que vous partagez autour de vous, et pour toutes les personnes qui vont rejoindre via ce lien, les affecter dans un groupe particulier.

On pourrait imaginer un groupe Testeurs externes uniquement par invitation d’un lien et un groupe Testeurs internes directement en email entrĂ©s dans la console.

D’ailleurs, vous pouvez voir qu’on peut restreindre au domaine mail (ce qu’il y a aprĂšs l’@). Pratique si on ne veut pas que son application fuite, mais qu’on veut quand mĂȘme pouvoir partager un lien !

2eme remarque: Pour ajouter des testeurs, on les ajoute dans un groupe, il faut retenir le nom du groupe

📝 Les notes de version

Lorsque vous déployez un APK sur Firebase, vous pouvez ajouter 2 choses

  • Des testeurs (ou groupes de testeurs)
  • Des notes de changement de version

Ce que l’on peut constater, c’est qu’entre 2 versions, on peut changer les testeurs, et on peut visuellement voire ce qui change.

NDLR Quand on va uploader un APK, on peut spĂ©cifier ces 2 choses, mais ce n’est pas obligatoire

Alors pourquoi est-ce que j’insiste sur le sujet ?

Les notes de version, c’est quelque chose de vraiment important.

Quand vous achetez un produit, n’ĂȘtes-vous pas intĂ©ressĂ©s d’ĂȘtre informĂ©s si la recette a changĂ© ?!

Lorsqu’on sera en prod, les utilisateurs auront accĂšs Ă  ce changelog.
Cela sera mĂȘme Ă©crit en gros et vert dans un encart sur le fiche du store !

De lĂ , vous aurez 2 options,

  • ĂȘtre prĂ©cis (ce qui demandera du temps et un effort)
  • ou bien ĂȘtre vague (et mettre le mĂȘme changelog Ă  chaque fois)
playstore complete changelog from googleplaystore  changelog from google
2 exemples de changelogs sur 2 applications différentes

En conclusion, avec tous ces éléments, on arrive à notre

3Ăšme remarque: quand on dĂ©ploie une application, c’est mieux de fournir un changelog

Pour rĂ©sumer, ce qu’on peut dire sur un dĂ©ploiement avec Firebase App Distribution

  • Nous devrons builder nos APK avec gradle assemble et pas bundle
  • Pour ajouter des testeurs, on les ajoute dans un groupe
  • Quand on dĂ©ploie une application, c’est mieux de fournir un changelog

Voyons maintenant comment modifier nos lanes pour réaliser tout cela.


Canon pirate. Image de déploiement de l'application comme un boulet de canon

🔀 DĂ©ployer avec Fastlane

Je vous propose la chose suivante :

Pour déployer notre APK nous allons écrire 3 lanes différentes

  • PremiĂšrement, une pour gĂ©nĂ©rer l’APK 📩
  • Ensuite, une autre pour gĂ©nĂ©rer un changelog 📝
  • Enfin, une derniĂšre pour envoyer le rĂ©sultat sur Firebase 🚀

📩 GĂ©nĂ©ration de l’APK

Commençons par gĂ©nĂ©rer l’APK.

Si vous avez suivi la partie 2 et l’automatisation des builds avec Fastlane, vous avez dĂ©jĂ  une lane pour gĂ©nĂ©rer votre APK.

Le principe reste simple, on va partir du postulat que nous n’avons qu’une flavor Ă  gĂ©rer.

desc "Build our App in Release"
lane :build_release do
    UI.message("Let's build our app in Release")
    gradle(task: 'assemble', build_type: 'Release')
    UI.success("✅ Release is packaged.")
end

Cette lane finie, l’apk se trouvera Ă  l’endroit classique app/build/outputs/apk/release/app-release.apk

Sous reserve d’une seule flavor, une seule release et que le module s’appelle app

📝 GĂ©nĂ©ration du changelog

Générer le changelog est une tùche plutÎt chiante.

Souvent rĂ©alisĂ©e Ă  la main, nous prendrons le temps de parler de l’automatisation de cette tĂąche dans un article dĂ©diĂ©.

Pour notre sujet ici, nous allons considérer la chose suivante

  • Vous crĂ©ez un dossier changelogs Ă  la racine de votre projet
  • Pour chaque version code de votre app vous crĂ©ez un fichier XXXX.txt
  • Les notes de versions de chaque version seront dans ce fichier

Exemple

  • Projet
    • app
      • build.gradle
      • autres fichiers
    • fastlane
      • Fastfile
      • Appfile
    • changelogs
      • 1.txt
      • 2.txt
      • 3.txt
      • 345.txt

Dans cet exemple, nous disposons d’un changelog pour les versions suivantes : 1, 2, 3, 345

Le contenu de ce fichier reste libre, faites comme vous le sentez, mais nous allons lire ce fichier pour pouvoir l’envoyer Ă  Firebase đŸ”„

🔱 RĂ©cupĂ©rer le version_code

La premiÚre étape pour nous est de récupérer le numéro de version actuel (pour savoir quel fichier lire).

Ecrivons donc une fonction pour récupérer le version_code actuel.

Je ne vais pas forcément rentrer dans le détail, on a plusieurs options ici

  • Lire le build.gradle (oui, mais si c’est une constante ?)
  • Stocker le version_code dans gradle.properties
  • Lire et parser les infos depuis l’AndroidManifest.xml gĂ©nĂ©rĂ©
  • Dumper les valeurs depuis l’apk gĂ©nĂ©rĂ©

Bref, un paquet de possibilités qui se valent, partons de la version 2 qui sera la plus simple à expliquer ici !

PremiĂšrement, on va ajouter une variable version_code= la version dans notre fichier gradle.properties Ă  la racine du projet

org.gradle.jvmargs=-Xmx1536m
kotlin.code.style=official
android.useAndroidX=true
android.enableJetifier=true

# App version
version_code=107

Ensuite, on va modifier notre fichier app/build.gradle pour utiliser cette variable dans notre build

android {
    ...
    defaultConfig {
        ...
        versionCode project.property('version_code')        
    }
}

De cette maniĂšre, on aura le bon version_code dans la gĂ©nĂ©ration de l’APK, mais surtout, un .properties c’est simple Ă  parser et lire.

On passe donc enfin à la 3Úme étape, le parsing du fichier pour récupérer cette valeur via Fastlane.

desc "Get the current version code of the app by reading gradle.properties"
lane :get_version_code do
    version_code = -1
    File.open('../gradle.properties', 'r') do |properties_file|
        properties_file.read.each_line do |line|
            line.strip!
            i = line.index('=')
            vc = line.index('version_code')
            if (i && vc)
                version_code = line[i + 1..-1].strip
            end
        end
    end
    version_code
end

Sans vouloir rentrer dans le dĂ©tail, ce qu’on fait est assez simple.

  1. On ouvre le fichier gradle.properties Ă  la racine du projet
  2. Pour chaque ligne
  3. On sanitize la ligne
  4. Checker si c’est une ligne qui contient une clĂ©/valeur (=)
  5. VĂ©rifier si c’est la ligne qui contient la valeur version_code
  6. Si oui pour les 2 tests, on retourne ce qui se trouve derriĂšre le = Ă  cette ligne
  7. Si non, on retourne -1

Encore une fois, je ne dis pas qu’il faut faire comme ça, mais c’est la solution prise pour l’article

🗂 Lire le changelog

Il ne nous reste qu’Ă  lire le changelog dans un fichier spĂ©cifiĂ©

desc "Read the specified changelog from a version code"
lane :get_changelog do |options|
    version_code = options[:version_code]
    changelog = ""
    File.open("./changelogs/#{version_code}.txt", 'r') do |changelog_file|
        changelog_file.read.each_line do |line|
            changelog += line
        end
    end
    changelog
end

Cette méthode simple va ouvrir un fichier texte situé dans fastlane/changelogs et renvoyer son contenu. De cette maniÚre on a notre changelog.

NDLR: Oui, il faudra Ă©crire votre changelog Ă  la main dans ce fichier avant de dĂ©ployer, on parlera plus tard de la gĂ©nĂ©ration de changelog automatique. L’article fait dĂ©jĂ  10km lĂ .

🚀 DĂ©ployer sur Firebase

Pour finir, nous allons Ă©crire une lane pour dĂ©ployer sur Firebase đŸ”„.

Pour cela, on va s’appuyer sur un plugin dĂ©jĂ  disponible firebase_app_distribution.

đŸ“Č Installer le plugin

Lorsqu’on suit le tutoriel officiel sur la documentation de Firebase, on voit que pour utiliser le plugin, il faut commencer par l’installer.

Pour cela, on va exécuter la commande suivante

bundle exec fastlane add_plugin firebase_app_distribution

Par la suite, il faut s’authentifier sur firebase (normal, sinon n’importe qui pourrait uploader une app par-dessus la nĂŽtre).

đŸ€ Authentifier Fastlane 🚀 sur Firebase đŸ”„

On voit qu’on a 3 options possibles

  • Via notre compte Google (BOF BOF si on est plusieurs)
  • Avec un compte de service
  • En utilisant firebase CLI

On va prendre la 2nd option, le compte de service.

  1. Rendez-vous sur la Console Google Cloud
  2. SĂ©lectionnez votre projet
  3. Dans la rubrique de Gauche, sélectionnez Comptes de Service
  4. Utilisez ou créez un compte de service

Dans le cas d’une crĂ©ation, remplissez les infos suivantes

Google cloud, création d'un compte de service

Au niveau des rĂŽles, ajoutez bien le rĂŽle admin de distribution

Google cloud compte de service ajout de rĂŽle

Si jamais vous utilisez un agent existant, privilégiez le firebase-adminsdk

  1. SĂ©lectionnez le compte de service (ici on va partir sur le firebase-app-distribution)
Google cloud et la liste des comptes de service
  1. Créez une clé sur ce compte
Google Cloud: Créer une clé sur le compte de service
Google Cloud: Création de la clé JSON
Créez la clé en JSON
  1. Une fois cette clé créée, téléchargez là (un fichier json)
  2. Renommez lĂ  firebase-app-distribution-key.json et copiez-la dans votre projet dans le dossier fastlane (Ă  cĂŽtĂ© du Fastfile et de l’Appfile)
  3. ⚠ Ajoutez cette clĂ© Ă  votre .gitignore, elle n’a rien Ă  faire sur un dĂ©pĂŽt !!

Notre dossier ressemble maintenant Ă 

  • projet
    • app
      • fastlane
        • Appfile
        • Fastfile
        • firebase-app-distribution-key.json

🚚 Distribuer notre APK via firebase_app_distribution

Pour finir, il ne nous reste plus qu’Ă  utiliser firebase_app_distribution pour dĂ©ployer notre APK avec une lane.

Pour faire ça nous aurons besoin de 2 choses en plus de ce que nous avons déjà

  • L’id de l’application sur Firebase, que vous trouverez en configurant le projet comme Ă  l’Ă©tape de l’ajout d’empreintes (on l’appellera VOTRE_IDENTIFIANT_FIREBASE)
  • La liste des groupes vers qui on veut distribuer notre application.
desc "Distribute APK to firebase"
lane :distribute_to_firebase do |options|
    UI.message("📩 Let's send the package to Firebase đŸ”„")
    apk_path = options[:apk_path]
    changelog = options[:changelog]
    firebase_app_distribution(
      app: "VOTRE_IDENTIFIANT_FIREBASE",
      groups: "LISTE DES GROUPES SÉPARÉS PAR UNE VIRGULE", # exemple "Testeurs Internes, Testeurs Externes, Potes, CODIR"
      apk_path: apk_path,
      service_credentials_file: "./fastlane/firebase-app-distribution-key.json",
      release_notes: changelog
    )
    UI.success("📩 Package sent")
end

Que faisons-nous lĂ -dessus ?

Déjà notre lane prend en entrée 2 paramÚtres

  • Le path vers l’APK Ă  dĂ©ployer
  • Le changelog Ă  dĂ©clarer

Ensuite,

  • il met Ă  jour la version de l’application dont l’id est spĂ©cifiĂ© dans app,
  • s’authentifie avec notre fichier firebase-app-distribution-key.json via service_credentials_file et
  • envoie l’APK spĂ©cifiĂ© au chemin en paramĂštre apk_path
  • Update les releases_notes avec notre changelog
  • Notifie les testeurs dans groups

đŸČ Tout mettre ensemble

Pour finir, notre derniĂšre lane est celle qui regroupe tout ce petit monde et fait les actions dans l’ordre

desc "Buil & Deploy the current version 🚀"
lane :deploy_app do
    build_release
    version_code = get_version_code()
    changelog = get_changelog(version_code: version_code)
    distribute_to_firebase(
        apk_path: "app/build/outputs/apk/release/app-release.apk",
        changelog: changelog
    )
end

Et si on met tout ensemble, on obtient ce Fastfile

default_platform(:android)

platform :android do

    desc "Build our App in Release"
    lane :build_release do
        UI.message("Let's build our app in Release")
        gradle(task: 'assemble', build_type: 'Release')
        UI.success("✅ Release is packaged.")
    end

    desc "Get the current version code of the app by reading gradle.properties"
    lane :get_version_code do
        version_code = -1
        File.open('../gradle.properties', 'r') do |properties_file|
            properties_file.read.each_line do |line|
                line.strip!
                i = line.index('=')
                vc = line.index('version_code')
                if (i && vc)
                    version_code = line[i + 1..-1].strip
                end
            end
        end
        version_code
    end

    desc "Read the specified changelog from a version code"
    lane :get_changelog do |options|
        version_code = options[:version_code]
        changelog = ""
        File.open("./changelogs/#{version_code}.txt", 'r') do |changelog_file|
            changelog_file.read.each_line do |line|
                changelog += line
            end
        end
        changelog
    end

    desc "Distribute APK to firebase"
    lane :distribute_to_firebase do |options|
        UI.message("📩 Let's send the package to Firebase đŸ”„")
        apk_path = options[:apk_path]
        changelog = options[:changelog]
        firebase_app_distribution(
          app: "VOTRE_IDENTIFIANT_FIREBASE",
          # exemple "Testeurs Internes, Testeurs Externes, Potes, CODIR"
          groups: "LISTE DES GROUPES SÉPARÉS PAR UNE VIRGULE", 
          apk_path: apk_path,
          service_credentials_file: "./fastlane/firebase-app-distribution-key.json",
          release_notes: changelog
        )
        UI.success("📩 Package sent")
    end

    desc "Buil & Deploy the current version 🚀"
    lane :deploy_app do
        build_release
        version_code = get_version_code()
        changelog = get_changelog(version_code: version_code)
        distribute_to_firebase(
            apk_path: "app/build/outputs/apk/release/app-release.apk",
            changelog: changelog
        )
    end

end

Et on peut tester que tout fonctionne en une commande

bundle exec fastlane android deploy_app

🎉🎉🎉🎉🎉🎉🎉


đŸ€Ż En rĂ©sumĂ©

Bon ! Ca fait combien de temps qu’on y est ?

Il Ă©tait particuliĂšrement long cet article, mais en mĂȘme temps, quel morceau non ?

On a appris Ă ;

  • đŸ”„ CrĂ©er notre projet sur Firebase đŸ”„
  • đŸ“± Activer le service d’App Distribution
  • 📝 Lire un changelog via Fastlane
  • đŸ€ Authentifier notre instance de Fastlane sur Firebase via un compte de service
  • 🚚 Builder et dĂ©ployer un APK automatiquement Ă  des testeurs en 1 ligne de commande

Ce n’est quand mĂȘme pas rien !

Plus d’excuses pour passer l’aprĂšs-midi Ă  faire un dĂ©ploiement (ni mĂȘme 1h) đŸ€Ą

Images

https://www.pexels.com/photo/woman-in-grey-shirt-holding-brown-cardboard-box-761999/
https://www.pexels.com/photo/cannon-castle-lunar-moon-4774/

DerniĂšre modification: 9 novembre 2020