Setup a Flutter CI/CD with GitLab CI — Part 3
Unit testing Flutter apps in CI Pipeline
In the previous post, we learnt how to install Android SDK, Xcode and Cocoapods.
In this post, we will learn how to set up our CI Pipeline.
The most common CI Pipeline in the Mobile world is Build -> Test -> Deploy. But when using Flutter, we run a Unit Test and Widget Tests without building the entire app.
What I’ve learnt, is that it’s probably more efficient to start with unit tests, followed by widget tests as we receive a faster feedback, and if there is a failure, there is no need to build the app.
Creating a unit test lane
Before a job is created, a new GitLab Configuration file .gitlab-ci.yml
needs to be generated from the root source of your codebase.
Copy and paste the configuration shown below into your .gitlab-ci.yml
.
stages:
- test # All jobs related for testing such as Unit Test
flutter_test: # Name of the lane
stage: test # type of stage
script:
- flutter test # Run Flutter test
tags:
- flutter # Tags for runner
stages
is used to define stages that can be used by jobs and is defined globally. The value we use will be “test”.flutter_test
is our job name.stage
is defined per-job and relies onstages
which is defined globally. It enables you to group jobs into different stages, and jobs of the samestage
are executed in parallel.script
This is where the shell script is executed for this job. Here, we will useflutter test
to run the unit test.tags
is used to select specific Runners from the list of all Runners that are allowed to run this project. We will useflutter
which was defined during the runner setup.
When you commit and push to your git repository, you should see the first successfully running job 🎉.
Creating an Android build lane
In this step, we will build our first Android APK.
Firstly, add another value under the stages heading called build
as shown in the example below.
stages:
- test # All jobs related for testing such as Unit Test
- build # All jobs related for building app for iOS and Android
Beneath theflutter_test
lane, paste the following example (in bold)
####
#### flutter_test lane
####
flutter_build_android: #Job name
stage: build # kind of job
before_script:
- flutter packages get
- flutter clean
script:
- flutter build apk
artifacts:
paths:
- build/app/outputs/apk/release/app-release.apk
tags:
- flutter
flutter_build_android
is the new job name for building an Android app.stage
has thebuild
value so in the future, we can execute the same stage in parallel when building apps.before_script
is the list of command lines which is executed before the job. For these commands, we useflutter packages get
to download dependencies andflutter clean
to clear the cache.script
is a parameter executed by the runner. The valueflutter build apk
is used to create an unsigned APK which can be installed on any Android devices.artifacts:paths
is a parameter used to define the path where an APK should be saved.tags
is used to select specific Runners from the list of all Runners that are allowed to run this project.
Now, let’s commit and push the updated .gitlab-ci.yml
file to our repository. We should now have our APK build from the CI Machine. 🎉
Creating an iOS build lane
In this step, we focus on creating an IPA build for iOS devices.
Installing iOS certificate on your machine
Before moving onto the next step, ensure the distribution certificate is installed on your machine. If not, refer to this documentation.
Creating an ExportOptions.plist
Before building and exporting an IPA. xcodebuild
needs to know how it should be exported as an archive. For this example, we will use our provisioning profile and export using the method ad-hoc
so it can be distributed to our internal end-users.
If you have an enterprise membership, I recommend using the enterprise method so your allocated devices (Limited to 100 per membership annual period) won’t be wasted except if you need to have debugged from the device.
We need to create a new file called ExportOptions.plist
and paste the following text (see below) into the file.
<?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>provisioningProfiles</key>
<dict>
<key>BUNDLE_IDENTIFIER</key>
<string>PROVISIONING_PROFILE_NAME</string>
</dict>
<key>method</key>
<string>ad-hoc</string> #adhoc or enterprise
<key>teamID</key>
<string>TEAM_ID</string> #TEAM ID that can find
</dict>
</plist>
<key>BUNDLE_IDENTIFIER</key>
is the bundle identifier of your iOS app. This is similar to the package name for an Android app. Don’t forget to replaceBUNDLE_IDENTIFIER
with your previously chosen bundle identifier.<string>PROVISIONING_PROFILE_NAME</string>
is the provisioning profile name for signing your iOS app. Don’t forget to replacePROVISIONING_PROFILE_NAME
with your previously chosen provisioning profile name- The value of
<key>method</key>
is the way the app is being distributed. It could bedevelopment
,ad-hoc
,enterprise
orappstore
. <key>teamID</key>
is the ID which Apple assigns to your membership Apple Developer Program which can be found on this page. Don’t forget to replaceTEAM_ID
with the value from the membership details page.
Configuring an iOS build lane
In this section, we will build an iOS flutter project from the CI.
Beneath the flutter_build_android
lane, paste the following example (in bold).
####
#### Unit test and flutter build android
####
flutter_build_ios:
stage: build
before_script:
- flutter packages get
- flutter clean
script:
- flutter build ios
- cd ios
- xcodebuild clean archive -workspace Runner.xcworkspace -scheme Runner -archivePath RunnerArchive
- xcodebuild -exportArchive -archivePath RunnerArchive.xcarchive -exportOptionsPlist ExportOptions.plist -exportPath ./build
artifacts:
paths:
- ios/build/Runner.ipa
tags:
- flutter
before_script
is the list of command lines which is executed before the job. For these commands, we useflutter packages get
to download dependencies andflutter clean
to clear the cache.script
is a parameter executed by the runner. For the list of command lines:- flutter build ios
is used to build an iOS project.- cd ios
we will change the directory to the ios folder.- xcodebuild clean archive [..]
this is where an iOS project can be archived.- xcodebuild -exportArchive [..]
these are a process of code signing your archive and generating an IPA.artifacts:paths
is a parameter used to define the path where an IPA should be saved.tags
is used to select specific Runners from the list of all Runners that are allowed to run this project.
After you commit and push the updatedgitlab.yml
, you should now see your first iOS app build. 🎉
On the next post, we will learn how to deploy our APK and IPA via a distribution platform such as Visual Studio App Center or an equivalent.