Note: Continious Delivery has not been integrated yet into the pipeline. 😏
This project has the following goals:
- Setup a CI/CD pipeline for a flutter app that builds an Android and an IOS app
- Show that you can build the IOS app without a physical macOS device
- Provide inspiration/templates for setting up CI/CD pipelines for your flutter project
- Show how to link your app to Firebase
This project uses the following technologies:
- Azure DevOps for setting up the pipelines
- Google Firebase to do the app distribution
This project starts from the basic create new Flutter project project. There is no extra functionallity added to the app. This only thing added are:
- a CI/CD pipeline
- link with Firebase
Both the Android pipeline and the IOS pipeline are encapsulated into one azure-pipelines.yml
file. What follows is a chronological explenation of all the steps I undertook to create the whole pipeline.
- Create an Azure DevOps project
- Install this Azure DevOps Flutter extension on my Azure DevOps project
- Create a simple new Azure DevOps build pipeline for the android build. This pipeline doens't yet include signing
- Add signing to the android build
- Create a keystore. See here how
- Add the keystore file to Azure DevOps Secure Files library (I called the keystore file
releaseKeyStore.jks
) - Adjust the pipeline (see changes here)
- Add variables to the pipeline.
- Note: the passwords are saved as secret variables
- Add a step to download the
releaseKeyStore.jks
secure file - Add step to set environment variables. These environment variables are used in the signing process
- Add variables to the pipeline.
- Edit build.gradle file to include signing when release building.
- Add a job to the pipeline for IOS building. See changes here
- Add certificate and provisioning profile to the CI build
- Enroll in the Apple developer program
- In the Apple developer console create a new Certificate
- Choose
Apple Distribution
as the type of the certificate - When asked to upload a
Certificate Signing Request
, create a new certificate by running these commands in Windows, and upload the generatedcertificateSigningRequest.certSigningRequest
openssl genrsa -out mykey.key 2048 openssl req -new -key mykey.key -out certificateSigningRequest.certSigningRequest -subj "/[email protected], CN=Your Name, C=BE"
- Download the generated
distribution.cer
Certificate from the Apple developer console - Convert the
distribution.cer
file into a.p12
file by running these commands on Windows# convert .cer to .pem openssl x509 -in distribution.cer -inform DER -out distribution.pem -outform PEM # combine the .pem and the .key file into one .p12 file openssl pkcs12 -export -out distribution.p12 -inkey mykey.key -in distribution.pem
- Upload
distribution.p12
to your Azure DevOps Secure Files library
- Choose
- Register a new Identifier in Apple developer console
- Choose
App IDs
as the type of the identifier - Enter your package ID. In this example it is
com.example.ciCdTemplate
- Enter a description for the identifier. I chose
Flutter CI CD
- No need to edit the capablities
- Register the Identifier
- Choose
- In Apple developer console create a new profile
- Choose
Ad Hoc
Distribution type - Next choose the App ID you registered. In chose
Flutter CI CD
- Next choose the Certificate you previously created.
- Next choose a device for which this profile will work.
- Yes you'll have to register an iPhone device in the Apple developer portal. You can use a friends iphone for this
- Give the Provisioning profile a name. I chose
Flutter CI CD - ad hoc
- Download the generated provisioning profile. For me the file is called
Flutter_CI_CD__ad_hoc.mobileprovision
- Upload the
Flutter_CI_CD__ad_hoc.mobileprovision
file to your Azure DevOps Secure Files library
- Choose
- Edit the pipeline (see changes here)
- Add
InstallAppleCertificate
andInstallAppleProvisioningProfile
steps to the pipeline- Be sure to add the password used to create the
distribution.p12
to the variables. I call the variabledistribution.p12-password
- Be sure to add the password used to create the
- Add
- Add signing and packaging to
.ipa
(see changes here)- Add
exportOptions.plist
- Use your own teamID instead of mine. You can find your teamID in the Apple developer console in the top right corner
- Use your own packageID instead of my
com.example.ciCdTemplate
- Use your own provisioning profile name instead of my
Flutter CI CD - ad hoc
- Add
XCode
step to pipeline - Add
PublishBuildArtifacts
step to pipeline
- Add
Do this steps to link your app with Firebase. All code changes for these steps are visible in this commit.
- Create an account on Firebase
- Create a new project inside the Firebase console
- Add an android app in your Firebase project
- Follow this setup wizard
- Add an IOS app in your Firebase project
- Follow the setup wizard
- Add
GoogleService-Info.plist
to theios/Runner/
folder- Note: If you do not run this from
XCode
, then be sure to includeGoogleService-Info.plist
to theRunner
target insideproject.pbxproj
- This can be done by manually editing the
ios/Runner.xcodeproj/project.pbxproj
file as seen in this commit - If you don't do this your app will crash on startup with this error
Could not locate configuration file: 'GoogleService-Info.plist'.
- FYI: I used iTools for getting IOS logging on Windows
- This can be done by manually editing the
- Note: If you do not run this from
- You can skip the Add Firebase SDK step
- I'm not sure, but it seems this is not needed with flutter
- You can skip the Add initialization code step
- I'm not sure, but it seems this is not needed with flutter
- Add
- Edit
ios/Podfile
so you don't encounter this build errorerror: FirebaseCoreDiagnostics does not support provisioning profiles. FirebaseCoreDiagnostics does not support provisioning profiles, but provisioning profile Flutter_CI_CD__ad_hoc has been manually specified. Set the provisioning profile value to "Automatic" in the build settings editor. (in target 'FirebaseCoreDiagnostics' from project 'Pods')
- Apply this fix
- Note:
ios/Podfile
will only be created once you runflutter build ios
. If you don't have amacOS
device you can get the createdPodfile
from your build pipeline as an artifact. You'll have to add this step to your pipeline, and the createdPodfile
will be available as an artifact of your build.- task: PublishBuildArtifacts@1 displayName: Publish artifact condition: always() inputs: PathtoPublish: '$(Build.SourcesDirectory)/ios/Podfile' ArtifactName: 'Podfile' publishLocation: 'Container'
- Follow the setup wizard
- Add the following dependencies to
pubspec.yml
firebase_core: ^0.4.4+3 firebase_analytics: ^5.0.11
The google-services.json
and GoogleService-Info.plist
committed with your source code should be of an development
or local
environment. In the build pipeline you should override these files with the configuration of a test
environment. This way you keep your data/diagnostics/crashReports seperated.
To achive this I've added the google-services.json
and GoogleService-Info.plist
files of my test environment of Firebase (= a new Firebase project) to the secure files in Azure pipelines. Now at build time I override the google-services.json
and GoogleService-Info.plist
of my source code with those of my test environment. See changes here.
First you'll need to do some manual steps before we can setup the automatic CD pipeline.
- In your Firebase project go to the distribution tab
- Make sure you select the android app
- The CI build created artifacts. One of those artifacts is
apk/app-release.apk
. Download that artifact to your device and upload it to App Distribution tab in Firebase- This will create a new release
- Add testers to the release (e.g. your own email)
- Next add some release notes
- Next click Distribute
- You should now receive an email with instruction how to install the application on your device
- Follow those instructions on an Android device, and you should be able to run the application
- Note: Appearently I forgot something because I can't install the application on my Android device. Give me some time to figure this out
Next we'll setup the CD pipeline. This so we can automatically push a new version of the app to our testers.
Todo: provide a CD pipeline
Manual steps
- In your Firebase project go to the distribution tab
- Make sure you select the ios app
- The build created artifacts. One of those artifacts is
ios/Runner.ipa
. Download that artifact to your device and upload it to App Distribution tab in Firebase- This will create a new release
- Add testers to the release (e.g. your own email)
- Next add some release notes
- Next click Distribute
- You should now receive an email with instruction how to install the application on your device
- Open that email on the ios device that you have registered in the Apple developer console, and that you have added to the distribution profile
- Note: the app will only work on the registered devices in your provisioning profile
- Note: follow these instructions if you want to add ios test devices
Next we'll setup the CD pipeline. This so we can automatically push a new version of the app to our testers.
Todo: provide a CD pipeline