In modern software development practices, the adoption and effective utilization of Continuous Integration (CI) and Continuous Delivery (CD) has become a game-changer. This phenomenon, collectively referred to as CI/CD, is revolutionizing how we build and deliver applications, specifically in the context of Flutter apps.
To keep pace with the accelerating rate of changes in the software industry, embracing the CI/CD process becomes vital for every app developer seeking to operate at the forefront of the industry. However, CI/CD is more than just a software development practice. It signifies a substantial shift in the approach toward coding and software delivery.
In this blog, we will unpack the different facets of CI/CD, explore some of the best CI/CD tools for Flutter, delve into the practical implementation of CI/CD in Flutter apps using FastLane, and how to manage the deployment process with minimal effort. Our journey will also take us through the intricacies of setting up an XCode Cloud for CI/CD in Flutter apps.
Treading deeper into the landscape of CI/CD, the route uncovers an intriguing yet complex system, integral to the development lifecycle in the software industry.
CI/CD, standing for Continuous Integration and Continuous Delivery, is a vital cogwheel of modern software development practice. It emphasizes a culture, set of operating principles, and collection of practices that enable teams to deliver code changes more frequently and reliably.
Continuous Integration (CI) is a practice that entails developers merging their changes back to the main branch as often as possible - definitely more than once per day. Upon each integration, automated tests and other validations run to catch any inconsistencies or errors.
On the other hand, Continuous Delivery (CD) stretches the concept further. As soon as the changes in the source code pass the automated tests, they are automatically deployed onto the production environment, resulting in frequent yet safe release cycles. It is indeed a strategic approach to mitigate the risks associated with the release processes, broaden the scope for delivering new features, enhance software quality, and respond more swiftly to software issues.
These twin aspects of CI/CD are transforming the operational blueprint of development and operations teams around the globe.
The machinery of the CI/CD process is designed to handle the complexities and challenges posed by comprehensive software development projects.
It begins with developers writing code for a new service or feature. The new code is tested locally where the entire application is emulated. Then, it is pushed into a shared code repository.
Upon the push, CI/CD pipeline triggers a series of tests including unit tests, integration tests, and static code analysis. This phase of continuous testing is critical to check the integrity of this term—new code in multiple developers' surroundings. Once the code passes all predefined tests, it is then merged into the master branch of the code repository.
The continuous deployment process picks up from here. The code is deployed multiple times a day into the live production environment, ensuring the delivery of validated code, thus amplifying the end-user adeptness. Catching issues in the early stage helps reduce the time spent on diagnosing and fixing bugs in the later stages of development.
CI/CD pipeline is a strategic asset that delivers tangible benefits in the software development lifecycle.
There's a myriad of tools and services available in the realm of CI/CD, each with its unique features and offerings. Let's steer this journey toward understanding some of the best CI/CD tools for Flutter.
It's important to note that the integration of CI/CD into Flutter apps is facilitated by different tools. Here are some of those key players:
Codemagic, built by Flutter developers for Flutter apps, is highly appreciated software within the Flutter community. It’s a fully-hosted and cloud-based CI/CD solution that enables automated build, test, and deployment cycles without the need for human intervention. Codemagic lets developers adopt the CI/CD pipeline to their Flutter development lifecycle with minimal effort.
Bitrise is another major player among CI/CD solutions for Flutter apps. It offers a multitude of integrations, workflows, and other tools that can be customized to create a perfect fit for your Flutter app development framework. With its visual workflow editor, managing and structuring the CI/CD process becomes a breeze.
Appcircle, as a fully automated CI/CD platform, takes away the tedious manual tasks and allows developers to focus on the development. With its cloud application framework, the complete lifecycle management of applications from building to publishing becomes seamless.
Fastlane is a remarkable open-source tool that automates building and releasing mobile apps and smoothly integrates with existing workflows. This tool adds efficiency to your CI/CD pipeline by automating the tests, build and deployment, and release, thereby speeding up the development and operations teams.
Here's a simple example of how Fastlane can be integrated with Github Actions in your CI/CD process.
1 2 name: Flutter 3 on: [push] 4 jobs: 5 build: 6 runs-on: ubuntu-latest 7 steps: 8 - uses: actions/checkout@v1 9 - uses: actions/setup-java@v1 10 with: 11 java-version: '12.x' 12 - uses: subosito/flutter-action@v1 13 with: 14 flutter-version: '1.12.13+hotfix.5' 15 - run: flutter pub get 16 - run: flutter test 17 - run: flutter build apk 18 - run: flutter build ios --release --no-codesign 19 - name: Fastlane Action 20 uses: thesayyn/fastlane-action@1.4.0 21 with: 22 lane: 'test' 23 subdirectory: 'android' 24 bundle-install-path: 'vendor/bundle' 25 env: 26 MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} 27 FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }} 28 29
If you are looking for a versatile tool to enhance your CI/CD applications, Fastlane is the optimal choice. Let's look at how we can expedite the building and deployment of Flutter apps with Fastlane.
Fastlane is an open-source tool suite that helps manage the tedious tasks associated with the development process. It handles everything from screenshots, managing provisioning profiles, versioning, app release, and various other tasks, making it an excellent add-on to your CI/CD pipeline.
It is recommended that you first set up and test these processes locally before migrating to a cloud-based system.
Start by installing Fastlane using gem install fastlane or brew install fastlane, followed by setting an environment variable FLUTTER_ROOT holding the root directory of your Flutter SDK. Examine if your project builds with Android flutter build appbundle and iOS flutter build IPA. Initiate Fastlane projects for each platform and adjust the Appfiles to match your app metadata.
Then, you'll need to sort out your local login credentials for the app stores. Please note taking the necessary measures when handling the JSON file that contains your login credentials to prevent any unintended data leaks. All setup processes should be performed with keen attention to security details.
Once the local setup has been tested and validated, the deployment process can be migrated onto a cloud system, like Travis. It is crucial to understand that any credentials needed for the CI/CD process should not be left on the server. To handle this, your CI system should support encrypted environment variables.
Our journey from local to the cloud requires some additional tasks related to your login credentials. For Android, we must remove the json_key_file field from the Appfile and place it directly in your CI system's encrypted variable. On the other hand, for iOS, shifting the local FASTLANE_PASSWORD environment variable to use encrypted environment variables on the CI system is indispensable.
This best CI/CD for Flutter pipeline laden with precautions allows us in a cloud-based system to leverage secure ways of automating and executing processes, underlining the subtle nuances that make CI/CD a modern software development practice distinct from the traditional approaches.
1 2 #Android 3 upload_to_play_store( 4 ... 5 json_key_data: ENV['<variable name>'] 6 ) 7 8 #For decoding the upload key (Android) 9 echo "$PLAY_STORE_UPLOAD_KEY" | base64 --decode > [path to your upload keystore] 10 11
With the setup ready, your CI/CD processes are now prepared to function both locally and on a cloud-based system.
Once the Fastlane has been integrated into the Flutter app, the immediate next step would be to test the deployment locally. It ensures that the setup is functioning as expected without introducing possible errors in the cloud environment.
The first step towards local deployment is initiating the building process for the release mode app. Both Android and iOS require different commands:
1 flutter build appbundle //Android 2 flutter build ipa //iOS 3
After successfully building the app, the next step is to run the Fastfile script for each of the platforms. Similar to the build process, this also involves running distinct commands for both platforms within their respective directories:
1 cd android 2 fastlane [name of the lane you created] //Android 3 4 cd ios 5 fastlane [name of the lane you created] //iOS 6
With these processes, your local setup is ready to deploy the app successfully with automated tests and lesser human intervention, manifesting the smoothness and efficiency of the CI/CD process.
Transitioning from local to cloud adds another level of efficiency to your CI/CD pipeline. It facilitates the software delivery process by offering a more scalable and manageable infrastructure. But, how do we set this up? Let's take a look.
For the security of your app, it is paramount to ensure that credentials like your Play Store service account JSON or your iTunes distribution certificate are not left on the cloud server. The solution is to use encrypted environment variables which can be passed using --dart-define MY_VAR=MY_VALUE while building the app. This way, secrets are not exposed, and your security remains intact.
On Android, you need to remove the json_key_file field from Appfile and store the string content of the JSON in your CI system's encrypted variable. Serialize your upload key (for example, using base64) and save it as an encrypted environment variable. You can deserialize it on your CI system during the install phase.
1 upload_to_play_store( 2 ... 3 json_key_data: ENV['<variable name>'] 4 ) 5 6 echo "$PLAY_STORE_UPLOAD_KEY" | base64 --decode > [path to your upload keystore] 7
On iOS, it involves transitioning the local environment variable FASTLANE_PASSWORD to use encrypted environment variables on the CI system. The CI system also needs access to your distribution certificate, and Fastlane's Match system is recommended to synchronize your certificates across machines.
Moreover, use Gemfile instead of using an indeterministic gem install fastlane on the CI system. This helps to ensure the Fastlane dependencies are stable and reproducible between local and cloud machines.
1 source "https://rubygems.org" 2 gem "fastlane" 3 bundle update 4
During this journey from local to cloud in the CI/CD process, the emphasis remains on keeping your credentials secure and managing them efficiently without sacrificing the automated nature of the process.
When factoring in the convenience of a fully-fledged ecosystem, utilizing Xcode Cloud for CI/CD in Flutter can be an excellent choice for applications destined for Apple platforms.
Xcode Cloud is a continuous integration and delivery service built into Xcode, making it significantly easier for you to adopt CI/CD in your development workflow. This service is designed specifically for Apple platforms and is an excellent tool to facilitate automated workflows for the building, testing, and distribution of apps and frameworks.
It does, however, come with a few prerequisites:
Xcode Cloud supports the execution of custom build scripts at different stages of a build and provides a set of environment variables to interact with the build system.
A post-clone script can be leveraged to perform specific actions right after Xcode Cloud clones the Git repository. Let's create a file at ios/ci_scripts/ci_post_clone.sh with the following script:
1 #!/bin/sh 2 3 # The default execution directory of this script is the ci_scripts directory. 4 cd $CI_WORKSPACE # change working directory to the root of your cloned repo. 5 6 # Install Flutter using git. 7 git clone https://github.com/flutter/flutter.git --depth 1 -b stable $HOME/flutter 8 export PATH="$PATH:$HOME/flutter/bin" 9 10 # Install Flutter artifacts for iOS (--ios), or macOS (--macos) platforms. 11 flutter precache --ios 12 13 # Install Flutter dependencies. 14 flutter pub get 15 16 # Install CocoaPods using Homebrew. 17 HOMEBREW_NO_AUTO_UPDATE=1 # disable homebrew's automatic updates. 18 brew install cocoapods 19 20 # Install CocoaPods dependencies. 21 cd ios && pod install # run `pod install` in the `ios` directory. 22 23 exit 0 24 25
To mark this file as executable, use git add --chmod=+x ios/ci_scripts/ci_post_clone.sh.
The Xcode Cloud workflow defines the steps the CI/CD process follows once triggered, providing a strong foundation for a seamless CI/CD process.
Creating a new workflow tailored to suit the needs of your Flutter project is straightforward in Xcode and requires the following steps:
The above steps ensure that the Xcode cloud workflow is attuned to your Flutter development requirements, putting you on the road to a more smooth and simplified CI/CD process.
By default, Xcode Cloud will detect any changes made to your Git repository’s default branch, triggering new builds based on these changes. However, you might want Xcode Cloud to trigger your workflow when modifications occur in your Flutter packages, or when either Dart or iOS source files within the lib\
and ios\
directories are modified, respectively. This can be achieved by using the "Files and Folders conditions" within Xcode Workflow.
Maintaining version consistency is an important part of delivering apps. Xcode Cloud defaults the build number for new workflows to 1 and increments it with each successful build. If you're migrating an existing app with a higher build number, ensure you adjust the "Next Build Number" in your iteration.
After creating and configuring your workflow in Xcode, your CI/CD process will be more streamlined and efficient, ensuring that your app gets to market faster while maintaining high software quality.
With the Xcode cloud environment optimally set up for your CI CD in Flutter apps, we have now traversed through the vast landscape of CI/CD in Flutter apps, from understanding concepts, various CI/CD tools, integration of Fastlane in the workflows to configuring cloud builds and deployments.
Our exploration of CI/CD in Flutter apps has highlighted its essential role in modern software development practices. Adopting a CI/CD pipeline in Flutter leads to automatic testing and deployment of integrated code changes, enhancing software quality, and speeding up delivery.
We also examined various CI/CD tools for Flutter, especially noting Fastlane's efficiency and seamless integration with existing workflows. As we ventured onto the cloud, Xcode Cloud showcased its potential, especially its role in scripting and managing workflows for Apple platforms.
In essence, the effective application of CI/CD methodologies in Flutter development is transformative, taking a step up from merely writing code to building high-quality, market-ready apps more efficiently. Let this guide serve as your foundation, helping you navigate the exciting realm of Flutter app development with CI/CD.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.