Setup a Flutter CI/CD with GitLab CI — Part 3
By: Roger Tan
Tags: Flutter, Android, Continuous Integration, Engineering, iOS

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”.

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.

is our job name. stage is defined per-job and relies on stages which is defined globally. It enables you to group jobs into different stages, and jobs of the same stage are executed in parallel.

is defined per-job and relies on which is defined globally. It enables you to group jobs into different stages, and jobs of the same are executed in parallel. script This is where the shell script is executed for this job. Here, we will use flutter test to run the unit test.

This is where the shell script is executed for this job. Here, we will use 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 use flutter 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 the flutter_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.

is the new job name for building an Android app. stage has the build value so in the future, we can execute the same stage in parallel when building apps.

has the 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 use flutter packages get to download dependencies and flutter clean to clear the cache.

is the list of command lines which is executed before the job. For these commands, we use to download dependencies and to clear the cache. script is a parameter executed by the runner. The value flutter build apk is used to create an unsigned APK which can be installed on any Android devices.

is a parameter executed by the runner. The value 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.

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.



<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "

<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> ttp://www.apple.com/DTDs/PropertyList-1.0.dtd" class="ct ja" rel="noopener nofollow">http://www.apple.com/DTDs/PropertyList-1.0.dtd "> #adhoc or enterprise #TEAM ID that can find

<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 replace BUNDLE_IDENTIFIER with your previously chosen bundle identifier.

is the bundle identifier of your iOS app. This is similar to the package name for an Android app. Don’t forget to replace 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 replace PROVISIONING_PROFILE_NAME with your previously chosen provisioning profile name

is the provisioning profile name for signing your iOS app. Don’t forget to replace with your previously chosen provisioning profile name The value of <key>method</key> is the way the app is being distributed. It could be development , ad-hoc , enterprise or appstore .

is the way the app is being distributed. It could be , , or . <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 replace TEAM_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 use flutter packages get to download dependencies and flutter clean to clear the cache.

is the list of command lines which is executed before the job. For these commands, we use to download dependencies and 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.

is a parameter executed by the runner. For the list of command lines: is used to build an iOS project. we will change the directory to the ios folder. this is where an iOS project can be archived. 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.

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.