Photo par Olia Nayda

Comment builder et signer votre application Flutter iOS avec les GitHub Actions

Intégration continue avec les actions GitHub

Créé par Damien Aicheh le 22 April, 2021 · 10 mins

Lors du développement de votre projet Flutter hébergé sur GitHub, vous pouvez facilement configurer des GitHub Actions pour builder et distribuer régulièrement votre application à vos utilisateurs.

Aperçu des étapes

Pour atteindre votre objectif, vous devez suivre ces étapes:

  • Installez le certificat Apple et le provisioning profile
  • Spécifiez la version correcte de Flutter
  • Restaurer les packages pub
  • Builder l’application
  • La signer en utilisant le bon certificat Apple
  • Générer un .xarchive
  • Générer un .ipa à partir du .xarchive
  • Partagez-le avec vos utilisateurs

Pour pouvoir suivre ce tutoriel, vous devez:

  • avoir accès à votre certificat Apple (.p12) avec le mot de passe associé
  • le provisioning profile

Avec cela prêt, commençons!

Présentation des GitHub Actions

L’idée est d’automatiser ce processus à l’aide des GitHub Actions, ce processus est appelé intégration continue.

L’intérêt d’utiliser les GitHub Actions est que:

  • C’est accessible de partout
  • Vous ne serez pas en charge de la maintenance du serveur
  • Vous avez tout en un seul endroit: GitHub

Nous allons créer quelque chose appelé une GitHub Actions qui vous permettra de générer votre ipa en un seul clic.

Configurez vos propres GitHub Actions

Créons notre premier workflow ! Dans votre projet, vous devez créer un dossier workflows dans le dossier .github, puis créer un nouveau fichier appelé: ios-release.yml par exemple. Ce fichier contiendra notre premier job appelé build_ios:

name: Flutter_iOS

on:
  push:
    branches: [main]

jobs:
 build_ios:
   runs-on: macos-latest

   steps:
   - name: Checkout the code
     uses: actions/checkout@v2

Ce job sera déclenché lorsque vous introduirez de nouvelles modifications sur la branche main. La première step que nous allons faire est de récupérer le code de notre branche.

Installer les certificats Apple

Vous devez utiliser quelque chose appelé secrets. Cela vous permet de stocker ces fichiers en toute sécurité afin d’accéder à votre certificat .p12 et à votre provisioning profile pour votre application. Si vous n’avez jamais utilisé de secrets auparavant, consultez cet précédent article.

Définissons-en un pour le certificat .p12 appelé P12_BASE64 et un pour le mot de passe associé appelé P12_PASSWORD.

L’étape suivante consiste à installer votre certificat Apple, pour ce faire, nous utiliserons une action de la communauté appelée apple-actions/import-codesign-certs@v1 et utiliserons nos secrets précédemment définis:


- name: Install Apple Certificate
  uses: apple-actions/import-codesign-certs@v1
  with:
    p12-file-base64: ${{ secrets.P12_BASE64 }}
    p12-password: ${{ secrets.P12_PASSWORD }}

Pour signer l’application, nous devons également installer notre provisioning profile:


  - name: Install the provisioning profile
    env:
      PROVISIONING_CERTIFICATE_BASE64: ${{ secrets.PROVISIONING_PROFILE_BASE64 }}
    run: |
      PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision

      echo -n "$PROVISIONING_CERTIFICATE_BASE64" | base64 --decode --output $PP_PATH

      mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
      cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles

Comme vous pouvez le voir ci-dessus, ce script comporte 3 opérations:

  • Créer la variable
  • Importer le provisioning profile à partir des secrets
  • Appliquer le provisioning profile

Compiler le code Flutter

Pour pouvoir utiliser Flutter dans notre workflow, nous devons l’installer. Pour y parvenir, nous utiliserons une autre action de la communauté:

- name: Install and set Flutter version
  uses: subosito/flutter-action@v1.4.0
  with:
    flutter-version: '2.0.1'

Nous devons ajouter cette action et spécifier la version de Flutter que nous voulons utiliser. Il est recommandé de corriger cette version au lieu d’utiliser stable comme valeur pour éviter d’éventuelles modifications importantes lorsqu’une nouvelle version est publiée.

Nous sommes maintenant en mesure de restaurer les packages de notre application:

- name: Restore packages
  run: flutter pub get

Une fois qu’ils ont été récupérés, nous pouvons builder l’application en mode release sans la signer:

- name: Build Flutter
  run: flutter build ios --release --no-codesign

En effet, nous appliquerons nos certificats précédemment installés à l’étape suivante!

Generer une xArchive

Tout d’abord, ouvrez votre projet iOS à l’aide de XCode et sélectionnez la target et dans Signing & Capabilities, assurez-vous que Automatically manage signing n’est pas cochée afin que nous puissions le signer en utilisant les certificats que nous voulons sans modifier le projet XCode.

Ensuite, lorsque vous signez une application iOS, vous ne signez pas les pods qui lui sont associés, vous devez donc le spécifier dans votre Podfile comme ceci:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
      config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
    end
  end
end

Avant de pouvoir générer notre xarchive, nous devons résoudre les dépendances Swift de notre projet. Ceci est particulièrement utile lorsque vous avez des plugins Flutter iOS écrits en Swift.

- name: Build resolve Swift dependencies
  run: xcodebuild -resolvePackageDependencies -workspace ios/Runner.xcworkspace -scheme Runner -configuration Release

Maintenant, pour créer une xarchive, vous devez chercher des informations situées dans votre provisioning profile ou dans votre certificat Apple:

  • L’identifiant de l’équipe de développement
  • L’UUID qui est l’identifiant de votre provisioning profile
  • L’identité de signature du code

Avec tout cela fait, nous pouvons l’utiliser comme ceci:

 - name: Build xArchive
   run: |
     xcodebuild -workspace ios/Runner.xcworkspace -scheme Runner -configuration Release DEVELOPMENT_TEAM=YOUR_TEAM_ID -sdk 'iphoneos' -destination 'generic/platform=iOS' -archivePath build-output/app.xcarchive PROVISIONING_PROFILE=YOUR_UUID clean archive CODE_SIGN_IDENTITY="Apple Distribution: Damien Aicheh"

Générer un ipa

Avec le xarchive généré, nous pouvons l’exporter en tant que ipa. Pour y parvenir, nous devons ajouter un nouveau fichier appelé ExportOptions.plist à notre projet pour spécifier les options d’exportation.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>method</key>
  <string>app-store</string> <!-- app-store, ad-hoc, enterprise, development -->
  <key>teamID</key>
  <string>YOUR_TEAM_ID</string>
	<key>signingStyle</key>
	<string>manual</string>
  <key>provisioningProfiles</key>
	<dict>
		<key>YOUR_BUNDLE_ID</key>
		<string>YOUR_UUID</string>
	</dict>
</dict>
</plist>

Selon les configurations de votre projet, vous devrez peut-être ajouter d’autres options à ce fichier. Vous pouvez avoir un fichier ExportOptions.plist pour chaque environnement de votre projet si vous en avez besoin.

Ensuite, exécutez simplement cette ligne de commande et votre ipa sera généré:

- name: Export ipa
  run: xcodebuild -exportArchive -archivePath build-output/app.xcarchive -exportPath build-output/ios -exportOptionsPlist ios/ExportOptions.plist

Publier les artefacts

Pour accéder à l’ipa généré précédemment à partir de l’interface GitHub ajoutons cette dernière action:

- name: Publish iOS Artefacts
  uses: actions/upload-artifact@v1
  with:
    name: release-ios
    path: build-output/ios

Cela publiera le dossier ios qui contient notre package. Ensuite, vous pouvez l’installer sur votre appareil.

Publish Artefacts

Touche finale

Vous êtes maintenant prêt à partager votre application avec vos utilisateurs en fonction du contexte de votre projet ! Vous trouverez un exemple de code sur ce répertoire Github.

N'hésitez pas à me suivre sur pour ne pas rater mon prochain tutoriel !