The demand for mobile app solutions is evident, which is why we expect our developers to get busier in years to come.
And we can’t help but notice how their work is only getting more difficult and stressful. Users are becoming more demanding as we speak and are quick to uninstall any application that doesn’t fully match their requirements and expectations. They are unforgiving when it comes to functionality issues, and developers are expected to deliver the code faster and with greater accuracy.
To cope with market pressures, Inviggo’s mobile app developers set up a CI/CD pipeline to help automate certain software delivery processes.
Continuous Integration and Continuous Delivery (CI/CD) is a set of development principles and practices that have become an essential part of the modern application development process. CI/CD automates manual development efforts to improve productivity, increase effectiveness, and streamline workflows and collaboration, maximizing development time.
By automating tedious tasks, from building and testing to deployment and provisioning, CI/CD eliminates human interaction, making the processes repetitive and predictable, thus reducing the error rate. It is popular for building larger applications that benefit from a simplified development process.
CI/CD helps connect the development, operations, and security teams and ensures they work efficiently. As a result, development teams get a chance to innovate and integrate smaller changes more frequently, making their processes more continuous, that way shipping more features to customers.
CI/CD pipeline is the step-by-step specification that software follows from start to finish for the deployment of the app. The pipeline allows development teams to make changes to the code and then have them automatically tested and pushed out for delivery and deployment.
Pipelining is intended to automate app deployment, as the script only needs to be specified once (the first time), and every other instance can be run at the click of a button. The goal is to build better, more quality code, avoiding bugs and failures. Ultimately, CI/CD pipeline reduces downtime and hastens the code releases.
Continuous Integration (CI) refers to the regular integration of all code changes into the main branch of the shared source code repository, where they are verified through automated checks. CI creates tight feedback loops, identifying errors and security issues early in the process so that they are fixed more frequently, easily, and earlier in the app development process.
Frequent merges trigger automated testing and validation, in that way minimize code conflict, which makes CI ideal for large application development projects that involve multiple developers. So instead of having developers check out each code commit, create a build, and run tests locally, they can utilize a CI tool to build and automatically test the app whenever a PR or commit is open.
A typical CI pipeline is comprised of 2 steps:
Continuous Delivery is a software development practice used to release the latest app versions to other team members as quickly as possible. After the code building and testing phase is finished as a part of the CI process, continuous delivery ensures it is ready for deployment to any environment.
The continuous delivery process typically includes the following steps:
Continuous Deployment is the final, fully automated step of the app build deployment. It accelerates the application production process and is used to deliver the app to the customers faster and collect feedback sooner.
While CI can be completed without continuous delivery or deployment, CD can’t be conducted without CI fundamentals in place.
When automating their CI/CD, most projects use two or three different pipelines:
A continuous integration pipeline is the most common, as it ensures code quality by running automated checks whenever a developer tries to merge their code into the main branch or opens a pull request. This pipeline runs build, lint, and tests, as well as code quality checks.
After making sure the code on our main branch is stable, the changes are merged, and a continuous delivery pipeline is triggered. This will build and package our code and deliver it to the QAs and testers. The continuous deployment pipeline is usually triggered on a set schedule or manually and is very similar to the continuous delivery pipeline - the only difference being that it delivers our application to the end users instead of the internal testers team.
The 3 main steps included in every pipelining script are:
There are several types of CI/CD solutions available for app and web development, the main difference being that mobile CI/CD requires special expertise. You can’t take a universal approach, and that’s why the CI/CD pipeline is handled by a mobile developer.
The fundamentals of the CI app development process are the same as for the web CI workflow:
But once we reach the testing phase, similarities end, and challenges kick in.
Mobile app users will not tolerate poor performance, so you can’t let any issues slip through the cracks. If the end-users experience those bugs, they won’t hesitate to run to your competitors. And because there’s a review and release waiting period for end-user deployment, mobile applications should be tested as early and frequently as possible.
But to run functional tests for mobile apps, you need either:
In the mobile app ecosystem, OS providers set the (strict) rules that dictate any decision made concerning how you develop, deploy, and run your application. That is why there is no out-of-box CI/CD solution, but you need to adapt your practices to the specifications enforced by Apple and Google.
It’s also important to mention that mobile CI/CD requires you to set up an independent pipeline as it is based on the deployment of a compiled binary – and you can’t set up instant deployments but need to update it on a mobile device from scratch, every single time.
All this prevents developers from performing incremental CI/CD code deployments and hotfixes. This reduces flexibility and increases the time between releases, making each release packed with more features than you would its web counterparts. Ultimately, the entire process is a lot more complex and difficult to handle.
Your application will require continual maintenance way past its deployment on Google Play and/or AppStore. Dealing with bugs in production is a lot costlier than during the development phase. Fixes are harder and take longer to release, and even after you update your app, you can’t count on users updating to the latest version on their phones. To keep track of user issues, you’ll need a reliable CI service built specifically for mobile to help keep a record of the binaries built.
Setting up a CI/CD pipeline will produce benefits across the entire spectrum: from development, monitoring, testing, fixes, and updates, to meeting users’ expectations, achieving the highest UX standards, gaining a competitive edge, and establishing a strong brand image.
CI/CD allows developers to set up automated tests for specific events, like when a pull request is created or code is pushed on a branch. If the code passes the test, developers can move on to merge and deliver the code. In other words, CI/CD pipeline simplifies testing and makes it more accurate since the code is reviewed in smaller chunks, whereas the traditional approach to debugging would take twice as long.
With most processes automated and less time spent on fixing code issues, your developers get a chance to focus on more innovative, rewarding projects. More frequent code testing, debugging, and working with smaller batches earlier in the development cycle means developers work more quickly as they review fewer lines of code. The burnout is reduced and your employees are happier.
This results in a smaller backlog and the team doesn’t have to deal with small issues but can focus on the big picture. The code quality improves and it can be regularly integrated into a common repository, turning the development process into a collaborative effort.
By optimizing development processes and spending fewer resources on removing deployment bottlenecks, developers can deliver more predictable results and are more capable of estimating accurate project deadlines (and actually achieving them).
CI/CD pipeline is ideal for businesses that expect their apps to scale and require continual improvement and updates. Managers need to set up reliable delivery processes to bridge the gap between developers who want to push changes and product owners who insist on 100% stable applications.
By setting up a CI/CD pipeline, you work with environments that have standardized configurations, continuous testing processes in place, and local environment variables separated from the app.
Many implement scrum and agile approaches to create situations in which developers will have to regularly communicate and share work updates. CI/CD pipeline naturally boosts collaboration among developers who would otherwise likely remain focused only on their own tasks. CI/CD unites the entire team and offers a transparent work environment where everyone is updated about other team members’ project status.
CI/CD enables fault isolation, allowing you to find the root of the problem before it spreads to the entire system. Continual testing of updates that come in small batches makes it easier to pin down the exact location of the issue and fix it quickly. This way, you can roll out the change faster and offer a near-uninterrupted user experience.
CI/CD also cuts down MTTR (mean time to repair), the time it takes to address the broken feature, so the fix is quickly implemented and accurately tested before deploying the new code. All this means you can recover from incidents faster and reduce downtime.
Automated tests ensure that bad code (almost) never makes it to production. App performance monitoring becomes a breeze, there are fewer bugs and errors, and those that you do come across are a lot easier to fix. Ultimately, you are able to keep your application functioning at a high level, which results in improved user experience and higher satisfaction, and an overall better business reputation.
All of the advantages listed above result in accelerated release cycles, as delivery mechanisms are standardized and automated. CI/CD practices allow you to deploy at any time, that way releasing new products and features to the market faster, accelerating time-to-value and gaining a competitive edge. You also get to collect honest suggestions frequently and turn them into actual features, sooner rather than later.
With most processes automated, the overall development costs are lower. CI/CD is especially popular among companies that pay their developers an hourly rate since the development time is accelerated. Finally, with a higher-quality code, you get an excellent return on investment.
First things first – we strongly suggest that you employ the CI/CD tools built specifically for mobile. Then, depending on the project specifics, you’ll need to consider the following features:
But probably one of the biggest questions among those who are adopting mobile CI/CD is whether they should opt for a self-hosted or cloud-based CI/CD.
So what are the best mobile CI/CD tools on the market at the moment? To offer an answer we’re 100% confident in, we talked to Milica, our talented software engineer who’s got several CI/CD projects in her portfolio. She revealed some of the tools she frequently includes in her tech stack when setting up a CI/CD pipeline.
CircleCI automates the build, test, and deployment process, allowing developers to detect and fix bugs before they reach users.
Most tools I have used for CI/CD require a .yaml file which contains the machine-readable instructions which will be executed in a container or a virtual machine. Below is a CircleCI config.yaml file that defines the steps for building and running tests for an Android application.
The project I am working on at the moment uses Kotlin multiplatform to help speed up the development of Android and iOS applications, so we needed a CI/CD process that tests both applications. I have accomplished this on Azure DevOps – since we are already using it as a Cloud provider and to store our repositories, this was the most logical solution.
Below are the build-android.yml and build-ios.yml files, which we use to build our apps and provide them with Google Services files. As the project is in the early stages of development, we still haven’t configured stages that will run the tests and build the artifacts. So far, we only need it to trigger pull requests and build.
You may notice that we are using fastlane for iOS builds – this was to speed up and simplify the build process. We also plan on using the same tool to run tests and prepare release bundles in the future.
Bitrise is a CI/CD PaaS, specialized tool for mobile DevOps that allows developers to automate, test, and deploy apps in phases in just a few clicks.
We love using Bitrise because it’s very easy to use, as it provides a simple graphical interface for steps and configuration. Here is a side-by-side look at the workflows we use for verifying code quality (primary) and building a release version (deploy) for Android apps.
Anything else out there? As Milica mentioned earlier, we typically use fastlane, an open-source platform, to simplify iOS and Android app deployment and speed up the build process. We also plan on using it to run tests and prepare release bundles in the future.
A few other 2023 CI/CD market favorites include:
Now a really fun part: Milica took the time to share some exclusive insight into Selfnest, one of our latest mobile app development projects, giving us full details of how the team approached the process.
Read the full interview below to learn how.
Before starting a project, or a new feature, it is best to take a look at the requirements - make sure to really understand what its implementation entails when it comes to system permissions (like camera, location, etc.) or third-party services. If you are unsure what app capabilities and entitlements are, read the official Apple and Google documentation. It’s also best to communicate any concerns about its implementation with the product owner and clients at this point – their expectations and certain limitations must be aligned.
The best example may be incorporating payment services into mobile apps. This differs drastically from web implementation, which allows various third-party integrations and workarounds, whereas the mobile development team is limited to Apple Pay and Google Pay services.
Another example can be handling various permissions your app may need to function - e.g., Selfnest supports video calls in the app, so we need to ask the users for the camera and audio recording permissions which must be done according to the guidelines.
First of all, we designed an MVP and defined its core functionality. When building the product, we tested its features thoroughly and regularly and paid attention to code quality and automated testing.
When the product had all of the required features, we began releasing iterations on the internal testing channel on the Google Play Store and started testing in production. We kept track of any potential improvements and fixes that could be done before the final release.
This is also the time to incorporate code shrinking, obfuscation, and optimization (if you haven’t already) to make sure there aren’t any related issues with your libraries.
Once the app was available to our team members, we tested it on multiple devices and different operating systems - which can be a lot on Android.
When the app is ready to be submitted for review and released to the store, keep in mind this process can last from a couple of hours to a couple of days and may require some alterations.
Chances are you will be using software like Simulator and Emulator to test your app from the beginning of your development process – utilize them as much as possible to test on various devices and OS versions. Personally, I like to keep several emulator devices of different screen sizes and with different OS versions (the latest OS version and at least 2 previous major releases) so that I can easily run my app on any of them. You should also pay special attention to tablets and adjust the UI and layouts accordingly. Using ConstraintLayout or BoxWithConstraints in Jetpack Compose can help you with this. Supporting different OS versions is very important for user satisfaction, so make sure to cover all the cases your IDE suggests, and when using system services (like push notifications, for example), research their requirements and implementation on different OS versions.
While simulated devices are great for day-to-day testing and offer a wide variety of configurations, it is imperative that you test your app on a real device, as some of its services are only available on real devices. An actual example of this when it comes to Selfnest is the camera on iOS devices, which is not supported on a Simulator. Another reason to consider using a real device from time to time is due to the difference between the hardware of desktop and laptop devices, which simulate mobile devices, and the actual mobile devices, as our code can sometimes run differently.
If you want to go a step further, you can configure a CI/CD pipeline to build your code on various platforms. Moreover, you can configure the pipeline to run tests on various devices to reduce the need for regression testing.
Finally, there will always be some errors and bugs that we may not catch, so monitoring tools like Firebase Crashlytics come in handy. They keep track of the device’s hardware and software details as well as your app version when reporting app crashes and bottlenecks.
Being the one to make the technical decisions and to hold accountability for the entire project has certainly been the most challenging part of working on Selfnest. It required greater responsibility than I had on any of the previous projects, but it certainly is a step in the right direction career-wise. And I cannot wait to see the application on the Play Store and the App Store.
Most importantly, we balanced the focus on MVP with staying flexible. Since the web application was already established in production, we were able to identify some bottlenecks and make improvements on the way. This was possible by nurturing a collaborative environment among the developers and the product team – we were encouraged to discuss the new features and improvements in brainstorming sessions and we held regular meetings.
Got any other questions regarding the CI/CD pipeline you’d like to discuss? Or maybe you’ve got some ideas and suggestions on how to streamline the process – we invite you to reach out, we’d love to hear them!
Featured Photo by Christina Morillo.