Smit Vora

Flutter Developer at Sunflower Lab

As we can see in current Mobile Application Development trend, Flutter has gain rapid growth in short span of time compares to any other Mobile application development framework. Earlier when any company or early stage start up pick Flutter for their upcoming Mobile Application Project framework, they tend to rely on readily available features, give their developers to spend some time and provide a space to them so they can get align with this new framework. 

In all cases, from a small start-up group to maintained team of developers, every mobile application industry follows some common software solutions and practices which are beneficial to maintain projects in a good way. Having ready-to-deploy or ready-to-release strategy is one of the best practices that an organization follows. In technical, this is called Continues-Integration & Continues-Deployment (CI-CD). In this article, we’ll be telling you how you can setup CI-CD pipeline on Bitrise for your Flutter Application.  

What actually is Bitrise ?  

Bitrise is the cloud CI/CD tool we use as a Service with main focus on mobile app development (ios, Android, React Native, Flutter, etc..). It is a collection of tools and services to help you with the development and automation of your software projects. 

Whole process of setting up CI-CD pipeline is divided into few sections as below:

  • Configure Flutter Application with different flavours 
  • Configure Flutter Application on Bitrise Web UI 
  • Configure Android & iOS Release Configurations 

In following part of this article, we’ll be covering all these sections one by one. So, let’s begin:  

Part 1 – Configure a Flutter Application with different Flavors

Part 2– Configure Flutter Application on Bitrise Web UI 

There are few steps for initializing your app on Bitrise. Let’s follow the steps in order to configure it. 

Step 1: Add a new application on web UI of Bitrise by clicking on topmost right button (+). 

Step 2: After adding a new app, select if you want the App to be public or private to the organization. 

Step 3: Now add your app from the repository which you want to connect as shown in the picture:

bitrise flutter

Bitrise Scanner automatically detects your git repository which contains a Flutter application and ask you some questions to configure the default Bitrise setup. 

Step 4: In Setup Repository Access, you can select auto-add SSH key or you can add it if you have.  

Step 5: In Branch Select Option, you have to select the branch in which your full code exists. It will then configure and scan it automatically. 

bitrise flutter

Step 6: Select your Schema name inside Project build configuration. 

bitrise flutter

Step 7: Add your app icon and Register a Webhook. When the setup is done, Bitrise automatically triggers a build with the default workflow called primary. 

bitrise flutter

By default, Bitrise creates 2 work flow primary and deploy. The principal difference between two work flow is the build and signing steps in the deploy workflow. 

To observe it in a proper way, go to the workflow tab and then go to the trigger tab. It will show you each workflow triggered by default. 

Get Help On Your Flutter Project

Now, heading towards our changes as a major in Steps through bitrise.yml file. The bitrise.yml tab will allow you to retrive all the configuration of your application on Bitrise. We usually store this file in git repository to have a backup. 

Our need is totally different from the default bitrise.yml file. So, I have created it to fulfil our needs. So, our need is to setup 4 workflow:

  • pull-request: It is used for checking the code quality (tests, code coverage, …) and if the application can be built without bugs. Depending on your needs, you could also make the application available for a functional validation of the new feature. 
  • production: It is used for building the application for the production environment and make it available to POs, testers, stakeholders who need it. 
  • develop: It is used for building the application for the development environment. 
  • unauthorize: It is used for preventing unauthorized actions in our continuous integration kinematics. This workflow throws an error. 

 

Bitrise configuration to meet our needs: 

Step 8: You have to create a bitrise.yml file in your project and refer the below code into your file if you want. 

Note: You would need to change the following things if you paste the below code!!! 

  • custom_export_options_plist_content in xcode-archive 
  • file-downloader/destination ‘key.jks’ to your jks file 
  • flutter-build/ Android and ios additional params 
  • You can also change the branch and schema according to your needs. 

format_version: '6' 

default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git 

project_type: flutter 

trigger_map: 

  - push_branch: develop 

    workflow: develop 

  - push_branch: master 

    workflow: production 

  - pull_request_source_branch: '*' 

    workflow: pull-request 

    pull_request_target_branch: develop 

  - pull_request_source_branch: develop 

    pull_request_target_branch: master 

    workflow: pull-request 

  - pull_request_target_branch: master 

    workflow: unauthorize 

workflows: 

  production: 

    steps: 

      - activate-ssh-key@4.0.3: 

          run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}' 

      - git-clone@4.0.14: {} 

      - script@1.1.5: 

          title: Do anything with Script step 

      - file-downloader@1.0.1: 

          inputs: 

            - destination: "$HOME/keystores/release.jks" 

            #- destination: "$DOWNLOADED_KEYSTORE_PATH" 

            - source: "$BITRISEIO_ANDROID_KEYSTORE_URL" 

      - certificate-and-profile-installer@1.10.1: {} 

      - flutter-installer@0: 

          inputs: 

            - is_update: 'false' 

            - installation_bundle_url: >- 

                https://storage.googleapis.com/flutter_infra/releases/stable/macos/flutter_macos_1.17.5-stable.zip 

      - flutter-analyze@0.1.0: 

          inputs: 

            - project_location: "$BITRISE_FLUTTER_PROJECT_LOCATION" 

      - flutter-build@0.9.2: 

          inputs: 

            - project_location: "$BITRISE_FLUTTER_PROJECT_LOCATION" 

            - android_additional_params: '--release --flavor production -t lib/main.dart' 

            - ios_additional_params: '--release --flavor production -t lib/main.dart' 

            - ios_codesign_identity: '' 

      - xcode-archive@2.4.19: 

          inputs: 

            - project_path: "$BITRISE_PROJECT_PATH" 

            - export_method: "$BITRISE_EXPORT_METHOD" 

            - force_provisioning_profile: '' 

            - force_team_id: '' 

            - force_code_sign_identity: '' 

            - force_provisioning_profile_specifier: '' 

            - custom_export_options_plist_content: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>compileBitcode</key>\n\t<false/>\n\t<key>destination</key>\n\t<string>export</string>\n\t<key>method</key>\n\t<string>development</string>\n\t<key>provisioningProfiles</key>\n\t<dict>\n\t\t<key>com.sfl.sflFlutterFlavorApp</key>\n\t\t<string>SflFlutterFlavorApp_Prod</string>\n\t</dict>\n\t<key>signingCertificate</key>\n\t<string>Apple Development</string>\n\t<key>signingStyle</key>\n\t<string>manual</string>\n\t<key>stripSwiftSymbols</key>\n\t<true/>\n\t<key>teamID</key>\n\t<string>T2D2NVNN89</string>\n\t<key>thinning</key>\n\t<string>&lt;none&gt;</string>\n</dict>\n</plist>" 

            - configuration: Release-production 

      - deploy-to-bitrise-io@1.3.19: {} 

      - github-status@2.2.2: 

          inputs: 

            - auth_token: "$GITHUB_STATUS_TOKEN" 

    envs: 

      - opts: 

          is_expand: false 

        BITRISE_SCHEME: production 

      - opts: 

          is_expand: false 

        BITRISE_EXPORT_METHOD: development 

  pull-request: 

    steps: 

      - activate-ssh-key@4.0.3: 

          run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}' 

      - git-clone@4.0.14: {} 

      - script@1.1.5: 

          title: Do anything with Script step 

      - file-downloader@1.0.1: 

          inputs: 

            - destination: "$HOME/keystores/release.jks" 

            #- destination: "$DOWNLOADED_KEYSTORE_PATH" 

            - source: "$BITRISEIO_ANDROID_KEYSTORE_URL" 

      - certificate-and-profile-installer@1.10.1: {} 

      - flutter-installer@0.9.2: {} 

      - flutter-analyze@0.1.0: 

          inputs: 

            - project_location: "$BITRISE_FLUTTER_PROJECT_LOCATION" 

      - codecov@1.1.5: 

          inputs: 

            - CODECOV_TOKEN: "$CODECOV_TOKEN" 

      - flutter-build@0.9.2: 

          inputs: 

            - project_location: "$BITRISE_FLUTTER_PROJECT_LOCATION" 

            - android_additional_params: '--release --flavor production -t lib/main.dart' 

            - ios_additional_params: '--release --flavor production -t lib/main.dart' 

            - platform: both 

      - xcode-archive@2.4.19: 

          inputs: 

            - project_path: "$BITRISE_PROJECT_PATH" 

            - export_method: "$BITRISE_EXPORT_METHOD" 

            - force_provisioning_profile: '' 

            - force_team_id: '' 

            - force_code_sign_identity: '' 

            - force_provisioning_profile_specifier: '' 

            - custom_export_options_plist_content: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>compileBitcode</key>\n\t<false/>\n\t<key>destination</key>\n\t<string>export</string>\n\t<key>method</key>\n\t<string>development</string>\n\t<key>provisioningProfiles</key>\n\t<dict>\n\t\t<key>com.sfl.sflFlutterFlavorApp</key>\n\t\t<string>SflFlutterFlavorApp_Prod</string>\n\t</dict>\n\t<key>signingCertificate</key>\n\t<string>Apple Development</string>\n\t<key>signingStyle</key>\n\t<string>manual</string>\n\t<key>stripSwiftSymbols</key>\n\t<true/>\n\t<key>teamID</key>\n\t<string>T2D2NVNN89</string>\n\t<key>thinning</key>\n\t<string>&lt;none&gt;</string>\n</dict>\n</plist>" 

            - upload_bitcode: 'no' 

            - configuration: Release-production 

      - github-status@2.2.2: 

          inputs: 

            - auth_token: "$GITHUB_STATUS_TOKEN" 

    envs: 

      - opts: 

          is_expand: false 

        BITRISE_SCHEME: production 

      - opts: 

          is_expand: false 

        BITRISE_EXPORT_METHOD: development 

  develop: 

    steps: 

      - activate-ssh-key@4.0.3: 

          run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}' 

      - git-clone@4.0.14: {} 

      - script@1.1.5: 

          title: Do anything with Script step 

      - file-downloader@1.0.1: 

          inputs: 

            - destination: "$HOME/keystores/release.jks" 

            #- destination: "$DOWNLOADED_KEYSTORE_PATH" 

            - source: "$BITRISEIO_ANDROID_KEYSTORE_URL" 

      - certificate-and-profile-installer@1.10.1: {} 

      - flutter-installer@0: 

          inputs: 

            - is_update: 'false' 

            - installation_bundle_url: >- 

                https://storage.googleapis.com/flutter_infra/releases/stable/macos/flutter_macos_1.17.5-stable.zip 

      - flutter-analyze@0.1.0: 

          inputs: 

            - project_location: "$BITRISE_FLUTTER_PROJECT_LOCATION" 

      - flutter-build@0.9.2: 

          inputs: 

            - project_location: "$BITRISE_FLUTTER_PROJECT_LOCATION" 

            - android_additional_params: '--release --flavor develop -t lib/main.dart' 

            - ios_additional_params: '--release --flavor develop -t lib/main.dart' 

            - ios_codesign_identity: '' 

      - xcode-archive@2.4.19: 

          inputs: 

            - project_path: "$BITRISE_PROJECT_PATH" 

            - export_method: "$BITRISE_EXPORT_METHOD" 

            - force_provisioning_profile: '' 

            - force_team_id: '' 

            - force_code_sign_identity: '' 

            - force_provisioning_profile_specifier: '' 

            - custom_export_options_plist_content: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>compileBitcode</key>\n\t<false/>\n\t<key>destination</key>\n\t<string>export</string>\n\t<key>method</key>\n\t<string>development</string>\n\t<key>provisioningProfiles</key>\n\t<dict>\n\t\t<key>com.sfl.sflFlutterFlavorApp</key>\n\t\t<string>SflFlutterFlavorApp_Prod</string>\n\t</dict>\n\t<key>signingCertificate</key>\n\t<string>Apple Development</string>\n\t<key>signingStyle</key>\n\t<string>manual</string>\n\t<key>stripSwiftSymbols</key>\n\t<true/>\n\t<key>teamID</key>\n\t<string>T2D2NVNN89</string>\n\t<key>thinning</key>\n\t<string>&lt;none&gt;</string>\n</dict>\n</plist>" 

            - configuration: Release-develop 

      - deploy-to-bitrise-io@1.3.19: {} 

      - github-status@2.2.2: 

          inputs: 

            - auth_token: "$GITHUB_STATUS_TOKEN" 

    envs: 

      - opts: 

          is_expand: false 

        BITRISE_SCHEME: develop 

      - opts: 

          is_expand: false 

        BITRISE_EXPORT_METHOD: development 

  unauthorize: 

    steps: 

      - script@1.1.5: 

          title: Do anything with Script step 

          inputs: 

            - content: | 

                #!/usr/bin/env bash 

                # fail if any commands fails 

                set -e 

                # debug log 

                set -x 

 

                # write your script here 

                echo "this script throws an error" 

                exit 1 

    envs: 

      - opts: 

          is_expand: false 

        BITRISE_SCHEME: production 

      - opts: 

          is_expand: false 

        BITRISE_EXPORT_METHOD: development 

app: 

  envs: 

    - opts: 

        is_expand: false 

      BITRISE_FLUTTER_PROJECT_LOCATION: "." 

    - opts: 

        is_expand: false 

      BITRISE_PROJECT_PATH: ios/Runner.xcworkspace

We added the File Downloader, Certificate and profile installer, CodecovXcode Archive & Export for iOS and Github status steps. 

File Downloader: It is used for downloading the Android certificate. 

Certificate and Profile Installer: It is used to get the mobile provision and certificate for iOS signing. 

Xcode Archive & Export for iOS: It is used to build and sign the iOS app 

Github Status: It is used to send Github status checks on each PR. You can configure your repository on Github so that status checks are mandatory to merge a PR. 

Part 3 – Configure Android & iOS Release Configurations 

Android Signing Configuration: 

The Signing config for Android is defined like this in the build.gradle file : 

bitrise flutter

You must generate the Android keystore if you don’t have one. Once you have the keystore, you need to upload it on Bitrise. Go to the Workflow Tab and then in the Code Signing Tab:

bitrise flutter

Note: Keystore Password, Keystore Alias and Private Key Password are mandatory to fill as of your .jks file. 

 IOS configuration: 

You must be having iOS certificate and mobile provision file. 

For this step, you must have an Apple Developer account to create the mobile provisioning and the certificate. Once you have you can upload them in Bitrise, go to the Workflow Tab and then in the Code Signing Tab. 

gitlab flutter

Now Let’s Start the build for the app, The Android and iOS build should not have any error. You can see your file generated inside the Apps and Artifacts Tab.  

gitlab flutter
gitlab flutter

Hence, we’re done with setting up CI-CD pipeline for a Flutter Project on Bitrise. We wish these details are helpful for setting up pipeline for anyone. Stay connected for our upcoming articles.  

Sunflower Lab is an award-winning company now providing result driven android app development services, ios app development services, robotic process automation services with a history of helping clients solve their toughest technology issues, we exist to build a better and brighter tomorrow.

Get a FREE estimate for your project today.

Our team of experts will review your project and give you a quote at no cost.

Get a quote on your project!

Related Posts

How to Create Singleton Pattern in Dart

Singleton Pattern creation in Dart or Flutter replaces the redundant code with a single line command. Let's code together!

How to Calculate ROI for RPA

RPA can help your business increase innovation and productivity while decrease time and money expenditure. Discover how to calculate ROI…

How To Use Updated Flutter Button Widgets

Description and styling directions for buttons, ElevatedButton, TextButton, and OutlinedButton using Flutter.