Continuous Integration and your mobile development workflow
Continuous Integration (CI) is a development practice where incremental code changes from multiple contributors are regularly reconciled and merged back into a shared codebase. After each merge is performed, the application is built and tested to ensure ongoing integrity of the codebase.
By integrating and testing small changes as frequently as possible, teams can increase visibility into all of the work happening in parallel, which makes it easier to spot and fix bugs early on and ultimately reduces overall development time and cost. This kind of stability improvement and efficiency gain is especially significant for mobile app teams, because binaries take time to ship and get approved and deployment cannot be continuous.
Successful companies need to iterate quickly and their mobile apps must continuously adapt to the needs of — and feedback from — their users. So, it’s no wonder that CI has become a critical part of the modern mobile development workflow.
In recent years, automated CI tools have radically transformed how teams of all sizes perform CI. These tools have made it possible to, for example, automatically run tests against new commits, assign action items to appropriate actors, or cherry-pick specific commits for integration, reducing the need for human intervention and speeding up the overall process.
Often, CI is combined with Continuous Delivery in a CI/CD pipeline. CD in a mobile app context involves automatically generating and distributing builds either for internal testing, or for external distribution. Automating the creation and distribution of builds allows for consistent testing until a suitable Release Candidate build emerges that should make it through to the app’s live user base.
CI is especially useful for mobile development
There are a number of reasons why CI’s general benefits are particularly attractive to mobile development teams:
- The cost of bugs in production is higher for mobile apps than it is for websites or web-based apps: fixes take longer because deployment is slower and gated by app store approvals, and even when fixes are released there’s no guarantee that users will update to the latest version of your app
- Generating mobile release builds comes with a lot of overhead (provisioning profiles, signing certificates, dependency management) that’s well-suited for automation
- Differences between environments can make it difficult to standardize and reliably execute testing and release workflows. Having a centralized, consistent environment in which to run these jobs — like a cloud-based CI server — helps to eliminate these issues (avoiding those ‘but it works on my machine!’ clichés)
- Many other steps unique to the mobile development workflow can benefit from scripting and automation implemented in a smart CI setup; for example, preparing and executing an upload to the App Store.
In short, a well-implemented CI solution reduces risk, and enables teams to produce better and more stable releases at shorter intervals. Developers work more efficiently and confidently with the safety net that CI provides, and PMs and product owners know their teams can respond more quickly when fixes need to get out the door, or deadlines need to be met.
The typical mobile CI/CD pipeline
Today, the term ‘CI’ most commonly refers to the use of automated tools to advance the goal of continuous integration. In practice, this means configuring an automated CI pipeline to repeatedly run building, testing, and deployment tasks that would normally be executed manually by the team. For mobile teams, a basic CI pipeline might contain the following steps:
- Check out the codebase from version control (e.g. GitHub, BitBucket)
- Install any dependencies (e.g. running `pod install`, `carthage bootstrap`, or similar)
- Run unit tests and automated UI tests
- On successful test runs, install required distribution provisioning profiles and certificates
- Build the app for distribution with the correct configuration (e.g. Release or Enterprise for iOS)
- Distribute build for either testing or release (e.g. using TestFlight, App Center or similar)
Often, a basic pipeline like the one described above can be set up to run whenever code is committed or merged into a main branch, guaranteeing that any and all changes being made are verified for regressions (via the unit testing step) and then distributed for testing or release.
These common pipeline tasks only scratch the surface of what’s possible with today’s modern CI tools. It’s now possible to automate many more of the logistically complicated and oft-repeated tasks that often bog developers down such as:
- Linting the codebase for formatting or stylistic errors
- Generating and uploading code coverage reports, or even flagging when changes result in reduced code coverage
- Blocking breaking changes from being merged into the main branch
- Precise management of feature and development branches after a merge
- Sending notifications via Slack or other communication channels upon build outcomes
- Caching build dependencies across build runs, which can improve the speed of subsequent builds
And the range of what’s possible using modern CI tools will only continue to grow as CI providers expand their capabilities, and as developers of open source and third party software continue to build automated solutions for common development tasks.
Common CI pitfalls and how to avoid them
Once you have a CI system in place, it can supercharge your development cycle. Still, adopting and integrating CI into your workflow can pose certain challenges. Avoiding these CI speed bumps can help make the transition less disruptive and the end result more successful:
- Lack of relevant dashboards and metrics: Collecting metrics along your CI pipeline — like build times, build concurrency and success rates — and surfacing them in a meaningful way can help you improve the pipeline and foster team buy-in. Think about who needs what information, and tailor dashboards to specific roles. For example, does an engineering manager need to see the same metrics as a PM? How about a CTO? Systematically sampling the right data and distributing it effectively can help in evangelizing process improvements and putting a spotlight on emerging issues.
- Not iteratively adopting CI and prioritizing: If you're part of a team that’s somewhat new to DevOps workflows and tools, adopting CI across the board and implementing end-to-end pipelines can be a challenge. It’s best to identify and prioritize those processes most in need of CI and those that can transition to it with minimal disruption. Core integration tasks like compilation, running builds, and automated unit testing are usually the most straightforward and good early targets for CI. Next, identify other rote jobs that are frequently repeated or would be less error-prone when automated.
- Lack of coordination at the interface between CI and CD: In cases where a team hasn’t implemented a combined CI/CD pipeline, not properly syncing CI and CD tasks can make both pipelines and the overall process less effective and more difficult to manage. For example, this often occurs when CI and CD pipelines are operating at different frequencies (say, daily vs. weekly).
- Culture and attitude shift: Successful CI adoption often requires some questioning of deeply ingrained priorities and definitions. For example, for teams operating with “waterfall” methodology, the more “agile” mindset that CI brings with it can require a cultural change: understanding that testing should be implemented at every step and before most of the app is finished, and adjusting the team’s “definition of done”. CI also usually involves a major shift to an individual, instead of collective, model of ownership.
- Testing, testing, and testing: Automated unit testing shouldn’t be the only type of testing you do. To properly assess unknowns and edge cases, and to cover more complicated user stories, the team needs to commit to a repeatable, robust and measurable manual QA process. Effective automated and manual testing both require a quality-first mindset as well as organization-wide buy-in from all stakeholders.
Comparing mobile CI providers
When it comes to choosing a third party CI provider, you’ll find there are a wide variety of options out there catering to different types of software development, teams, and particular contexts. Some can be quite feature-rich, offering functionality like early bug detection, conflict resolution, out-of-the-box automation and risk management, often with integrated tools that enhance collaboration and communication.
The ideal fit for a given team and app can vary widely depending on various factors: the need for scalability, current workload and number of parallel projects, existing infrastructure and tech ecosystem, and cost considerations. Evaluation of cost should extend beyond the CI’s subscription or licensing cost alone, and factor in time and labor required for onboarding and maintenance and purchase of any prerequisite software or hardware.
There are a few characteristics of any particular CI provider that should always be considered:
- Hosting: Is the service hosted on-premise or in the cloud? If the former, what are the hosting requirements, both in terms of software and hardware? A common “gotcha” is that it is only possible to build iOS apps in macOS running on Apple hardware.
- Platform support: iOS, Android, or multi-platform?
- Concurrency and build performance: How many builds can run at once? Are builds throttled? Some providers offer free or cheaper subscription plans with minimal concurrency and relatively slower build times, but costs increase significantly if you need more throughput and better performance.
- Integrations: Can you add this service to your current toolchain with reasonably low overhead and little ongoing maintenance? Does it have a programmable API?
- Configuration: How do you set up and change your pipeline’s build steps and other processes and settings? Is there a UI-based option, or is everything handled by a configuration file (e.g. YAML)?
- Licensing tiers and pricing: In addition to fixed subscription or licensing costs, consider how your overall cost footprint is affected by usage-based pricing given your team’s build throughput, and user-based pricing given your team’s size. How many separate projects can you develop on each tier? Are there other restrictions?
Clearly, there’s no “one-size-fits-all” choice here. Below, we compare five of the top CI platforms for mobile development, but remember that choosing the ideal provider is a highly individual process!
Bitrise is a Platform-as-a-service (PaaS) CI provider (with Public Cloud and Private Cloud options) that actually specializes in mobile app development for iOS and Android. It features a UI-based workflow builder and an impressive list of integrations with productivity tools, as well as robust support for popular build frameworks such as React Native, Xamarin, Flutter and Ionic/Cordova.
A free “Hobby tier” suited to very small projects is available; Public Cloud plans start at $40/month. You unlock higher concurrency, unlimited team members, and other features with higher paid tiers.
CircleCI is another cloud-based PaaS provider, with fully or partially self-hosted options also available. It can be configured to support several different languages and frameworks, including both Android and iOS, and to build in Windows, Linux, MacOS, and Docker environments. It’s used by some of the world’s leading tech giants, such as Facebook, Intuit, Spotify and Shopify.
CircleCI has a usage-based pricing model with a free bottom tier (that doesn’t include iOS). Higher-tier packages start at $15/month (for 3 users) and unlock additional usage credits as well as improved performance. Open-source developers are allotted a substantial amount of free usage credits per month.
GitLab is a popular open-source end-to-end software development platform. Although it shares a lot of DNA with GitHub, GitLab’s robust built-in CI capabilities and role-based access controls make life easier for DevOps teams, and for QA in particular. Huge names like Electronic Arts, Sony, and Uber use GitLab CI for their projects.
Gitlab’s paid, usage-based plans start at $4 per user/month, with a free tier that accommodates unlimited users but has a low usage cap.
Jenkins is an open-source CI server, founded as “Hudson” in 2006. Thanks to its modular and extensible architecture, developers have contributed hundreds of plugins that solve just about any need you can imagine, including a ton of integrations with popular productivity tools like Slack, Jira, AWS CodeDeploy, and more. Because of this large and active community of contributors, and its strong core feature set and configurability, Jenkins is still one of the most widely used CI tools out there. This despite the fact that it’s a bit less polished and is trickier to set up and maintain than other options.
Jenkins is completely free to use. It can run on Windows, macOS, and Unix-based systems, and it supports both Android and iOS app development. Some notable Jenkins users include Facebook, LinkedIn, and eBay.
Visual Studio App Center
While Visual Studio has a 20+ year history as a giant in the IDE space, App Center was launched in 2017 as an all-in-one solution for mobile developers. It supports the building, testing, distributing, and monitoring of apps for iOS, Android, Windows, React Native, Unity, and more. It’s a particularly popular choice for Xamarin development (not surprising, given that the framework is Microsoft-owned).
App Center offers a free plan that includes limited build time and only comes with a 30-day automated testing trial. However, you can use all other premium features. Pricing starts at $40/month.
You can also take advantage of Visual Studios’ rich collaboration and project management (Team Services) tools. Using frameworks like Appium, Espresso, and XCUITest, you can run tests on nearly any combination of device and configuration, in the cloud.
Continuous integration can pave the way for more streamlined app lifecycles by encouraging and enabling your team to develop, test, and integrate bite-sized chunks of code on a regular basis. As a practice, it’s key to a development and product culture that encourages collaboration and transparency. And, with a bit of tooling and automation, CI can become an invaluable part of a robust workflow that is vigilant about detecting and fixing issues at an early stage when it’s still cost-effective to do so.
Despite its potential, your team should approach the task of adding CI to an existing toolchain with proper planning and preparation. But once it’s integrated, with the necessary support and buy-in, you’ll wonder how you lived without it.