Vous souhaitez mettre en place une chaîne automatisée CI/CD qui compile votre app Ionic et qui la déploie directement sur Diawi, le tout avec Github Actions ?
Je vous explique comment faire dans cet article. ;)

Introduction

Lorsque nous travaillons sur un projet de développement logiciel, nous nous rendons vite compte que compiler, tester, et déployer le projet devient vite lourd et rébarbatif.

Ces dernières années les techniques de CI/CD -- Continuous Integration/Continuous Development (ou le terme courant pour définir l'automatisation des builds, tests et déploiement) fleurissent.

Nous allons donc nous y intéresser pour le déploiement d'un app Ionic automatisé par Github Actions.

Contexte

Dans cette article, nous allons voir comment :

  • compiler une app Ionic avec Github Actions
  • déployer cette app pour iOS avec Diawi

Nous n'allons pas aborder le déploiement pour Android (qui est relativement simple une fois qu'on a fait iOS), le déploiement sur les stores (ce sera peut-être l'objet d'un nouvel article) ni les tests qui pourraient être fait en CI/CD.

Pré-requis

Pour pouvoir suivre ce guide, vous devez :

Mise en place du projet Ionic

Au préalable, vous devez avoir un projet Ionic avec une app mobile iOS :

  • développé via Angular (à vous d'adapter les commandes et scripts pour les autres frameworks)
  • qui utilise Capacitor

Le guide se focalisera sur l'environnement de dev du projet.

Afin d'utiliser le CLI locale de la version d'Angular installé pour le projet, ajoutez le script suivant dans package.json:

{
    // ...
    "scripts": {
        "build-dev": "node ./node_modules/@angular/cli/bin/ng build",
        // ...
    }
}

Mise en place de l'action de Build

Nous allons cette fois ci créer l'action Github qui nous permettra de compiler notre app lorsqu'on pousse notre projet.

Pour cela, créez le fichier .github/workflows/dev-jobs.yml avec les lignes suivantes :

# Github Actions
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions

# Ici, on indique à Github que le job doit s'executer sur push de la branche dev
on:
  push:
    branches:
      - dev

# On configure l'environnement des outils qui seront utilisés lors de l'execution de notre tâche
env:
  NODE_VERSION: 16.x
  JAVA_VERSION: 11.0.10

jobs:
  # C'est notre job de build, qui s'occupera de build tout l'ensemble de notre app jusqu'à l'application final
  build:
    name: Build App
    # Comme on devra compiler une app iOS, il est préférable d'utiliser une image système de Mac fourni par Github
    runs-on: macos-latest
    steps:
      - name: Config - Use Node.js ${{ env.NODE_VERSION }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ env.NODE_VERSION }}

      - name: Checkout
        uses: actions/checkout@v2

      - name: Project - Install dependencies
        run: npm ci

      - name: Project - Build
        run: npm run build-dev

      # Ici, si nous voulons déployer notre app pour le web, nous pouvons traiter les fichiers disponible dans www.

A ce stade, nous avons un projet qui, une fois poussé sur Github dans la branche dev, se compile et fournit les fichiers HTML / JS / CSS dans le dossier www du worker.

Gestion des certificats et des profiles iOS

Generation du certificat

Pour pouvoir distribuer une app iOS, nous aurons besoin d'un certificat de distribution et d'un profil de provision fourni par l'espace developer Apple.

Commençons donc par créer un certificat :

Sur votre mac, double-cliquez sur le fichier du certificat pour l'installer dans votre trousseau de clés.

Conversion du certificat en p12

Pour que Github Actions puisse utiliser votre certificat, vous devrez l'exporter en certificat d'échange d'informations (.p12).

Pour cela :

  • Ouvrez votre trousseau de clés (keychain access)
  • Dans session, accédez à l'onglet Mes certificats
  • Recherchez le certificat nouvellement installé, puis clique droit et Exporter Apple Distribution: ...
  • Choisissez Echange d'informations personnelles (.p12)

Vous devrez fournir un mot de passe pour sécuriser votre certificat.

Génération du profile de provision

Une app iOS a besoin d'un profile de provision (Provisioning profile) pour savoir où et comment distribuer l'App.
Nous allons utiliser la méthode Ad-Hoc afin de pouvoir distribuer l'App via Diawi sur une liste de devices prédéfinie.

Pour cela :

  • Accédez à https://developer.apple.com/account/resources/profiles/list
  • Ajoutez un nouveau profile en choisissant Distribution et Ad-Hoc
  • Sélectionnez l'app concernée (vous devez avoir au préalable créer votre identifier dans la section Identifiers)
  • Sélectionnez le certificat de distribution créé ci-dessus
  • Sélectionnez les devices qui pourront exécuter l'app (vous devez au préalable ajouter l'UUID des iPhones dans la section Devices)
  • Générez et téléchargez le profile.

Mise en place de l'environnement de déploiement iOS pour Github Actions

Pour iOS, nous allons devoir créer et ajouter des fichiers au repo git afin de mettre en place l'environnement de déploiement iOS sur le worker de Github Actions.

Mise en place des secrets dans Github

Nous allons mettre en place les secrets dans Github qui seront utilisé dans les jobs de notre projet par Github Actions. Nous avons deux données à enregistrer:

  • IOS_CERTIFICATE_PASSWORD: le mot de passe utilisé précédement pour protéger l'export du fichier p12
  • DIAWI_TOKEN: Token d'accès à votre compte Diawi

Pour cela :

  • ouvrez le repo de votre projet sur Github.
  • Accédez à Settings
  • Cliquez sur Secrets and Variables > Actions
  • Ajoutez un repository secret pour chaque variable ci-dessus.

Génération de ExportOptions.plist

Le processus de création d'une app iOS passe par :

  • la création d'une archive
  • l'export de l'archive en .ipa.

Pour pouvoir exporter l'archive, nous avons besoin de l'environnement d'export qui est décrit dans un fichier XML ExportOptions.plist.

Nous allons le générer.

Pour cela :

  • Ouvrez XCode (commande ionic cap open ios)
  • Choisissez l'app et la target Any iOS Device
  • Cliquez sur Product puis Archive
  • Une fois la popup ouverte, cliquez sur Distribuer l'app
  • Suivez le processus en choisissant:
    • Ad Hoc
    • App Thinning: None
    • Votre certificat de distribution

Dans le dossier d'export, récupérez le fichier ExportOptions.plist.

Configuration de l'environnement

Nous allons ici ajouter les fichiers nécessaires à la configuration de l'environnement de déploiement et à la compilation de l'app.

Ajoutez les fichiers suivants :

  • distribution.p12 (fichier Echange d'informations personnelles .p12 exporté précédemment) dans .github/ios/certificates
  • ExportOptions.plist (fichier d'environnement d'export généré précédemment) dans .github/ios/Options
  • profile.mobileprovision (fichier de profile de provision téléchargé précédemment) dans .github/ios/profiles

Création des scripts

Pour installer les profiles et générer les apps, nous allons mettre en place des scripts Shell.

Pour installer les profiles, ajoutez le fichier suivant .github/ios/scripts/install-profiles:

#!/usr/bin/env bash
#  Script to install iOS profiles

# Define project root path
scriptPath=$(readlink -f "$0")
projectRoot=$(dirname "$scriptPath")/../../..

# Install Provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $projectRoot/.github/ios/profiles/profile.mobileprovision ~/Library/MobileDevice/Provisioning\ Profiles/

# Ajouter ici les autres commandes pour copier les autres profiles de provision nécessaires. 

Pour compiler et générer l'App iOS, ajoutez le fichier suivant .github/ios/scripts/build

#!/usr/bin/env bash
#  Script to build iOS App

# Define project root path
scriptPath=$(readlink -f "$0")
projectRoot=$(dirname "$scriptPath")/../../..
iosAppRoot=$projectRoot/ios/App

# Build archive
echo ""
echo "Build archive"
cd $iosAppRoot || exit
xcodebuild -workspace App.xcworkspace -scheme Default -configuration AdHocDistribution -archivePath $iosAppRoot/build/App.xcarchive clean archive
# Le scheme définit également le nom cible de l'app .ipa.

# Export IPA
echo ""
echo "Export IPA"
xcodebuild -exportArchive -archivePath $iosAppRoot/build/App.xcarchive -exportOptionsPlist $projectRoot/.github/ios/Options/ExportOptions.plist -exportPath $iosAppRoot/build/apps

echo ""
echo "List folder files"
ls -l $iosAppRoot/build/apps

Mise à jour de dev-jobs.yml

Nous avons maintenant tout ce qu'il nous faut pour générer une app iOS. Il nous manque plus qu'à configurer le job du workflow Github Actions.

Dans le job build, ajoutez les lignes suivantes:


      # ...

      - name: Project - Sync capacitor
        if: success()
        run: npx cap sync

      # https://github.com/Apple-Actions/import-codesign-certs
      - name: iOS - Install Certificates and Keys
        if: success()
        uses: apple-actions/import-codesign-certs@v1
        with:
          p12-filepath: ./.github/ios/certificates/distribution.p12
          p12-password: ${{ secrets.IOS_CERTIFICATE_PASSWORD }}

      - name: iOS - Install profiles
        if: success()
        run: ./.github/ios/scripts/install-profiles

      - name: iOS - Build Project
        if: success()
        run: ./.github/ios/scripts/build

      - name: Save artifact - iOS outputs ipa
        if: success()
        uses: actions/upload-artifact@v3
        with:
          name: app_ios
          path: ios/App/build/apps/*
          if-no-files-found: error

     # Ici, nous avons sauvegardé le résultat du build dans un Artifact que nous récupérons dans un autre job pour déployer sur diawi.

Créons maintenant le job deploy_ios qui s'occupe de déployer l'app iOS sur Diawi :

Ajoutez les lignes suivantes dans .github/workflows/dev-jobs.yml :

  # Deploy iOS app on Diawi
  deploy_ios:
    name: Deploy iOS App on Diawi
    needs: build
    runs-on: macos-latest
    outputs:
      # Cette variable peut être utiliser dans un autre job pour récupérer le lien de partage Diawi (Notification sur Slack par exemple)
      url: ${{ steps.diawi.outputs['url'] }}
    steps:
      - name: Download artifact - iOS outputs ipa
        uses: actions/download-artifact@v3
        if: success()
        with:
          name: app_ios
          path: ipa

      - run: ls ${GITHUB_WORKSPACE}/ipa

      - name: Deploy to Diawi
        if: success()
        id: diawi
        uses: rnkdsh/action-upload-diawi@v1.3.0
        with:
          token: ${{ secrets.DIAWI_TOKEN }}
          file: ./ipa/Default.ipa

      - name: Diawi URL
        run: echo ${{ steps.diawi.outputs['url'] }}

Vous pouvez maintenant pousser votre projet et Github Actions se chargera de compiler et déployer l'app à votre place.

Conclusion

A travers cet article, vous pouvez maintenant configurer un environnement de déploiement automatisé via Github Actions.

Cette délégation de tâche vous simplifiera la maintenance de votre projet et vous facilitera grandement la tâche rébarbatif qui est de compiler, (tester) et déployer une app.

J'espère que cet article vous a été grandement utile, et je vous dis à plus pour le prochain ! xD


Crédits

Article précédent Article suivant


Ajouter un commentaire