EngineeringCategory

GoDaddy Android App Bitrise Optimizations

10 min read
Fernando Prieto Moyano
Image of a high-rise building

Introduction

Lately, I've been focused on enhancing our Continuous Integration (CI) pipeline for the Android team at GoDaddy. By leveraging powerful features from Bitrise—like parallelization and flexible workflows—I introduced key improvements that significantly accelerated pull request (PR) merges, streamlined UI testing, and made the overall CI setup cleaner and easier to understand. These changes help our team ship faster, with greater confidence and clarity.

Smarter CI built for mobile development

At GoDaddy, building reliable, high-performing mobile experiences means investing in tools that support speed, scale, and simplicity. For our mobile CI/CD needs, we use Bitrise—a platform purpose-built for mobile app development.

Bitrise stands out because it handles many of the complexities that often slow teams down. It provides ready-to-use environments tailored for iOS and Android, eliminating the need for manual setup of Xcode versions, Android SDKs, or signing tools. With features like pre-built steps, smart caching, and built-in code signing and deployment support, our teams can focus more on building and testing features—not maintaining infrastructure.

Most importantly, Bitrise helps reduce DevOps overhead. Its managed macOS and Linux environments give us consistent, reliable builds without the hassle of maintaining our own CI machines or dealing with local environment issues. For GoDaddy's mobile teams, that means faster iteration, more stable pipelines, and a better developer experience overall.

Improving builds with workflows and pipelines

At GoDaddy, we've been taking advantage of some of the more advanced features of Bitrise to streamline and scale our CI/CD processes for mobile. Central to this are Steps, Workflows, and Pipelines—the building blocks that define how our automation runs.

Each build is made up of a sequence of Steps—discrete tasks like installing dependencies, running tests, or signing the app. These Steps are organized into Workflows, which we can customize and reuse across projects. Inputs and outputs from each Step can be passed along, allowing us to build complex automation logic with clear structure and control.

One of the key advantages we've embraced is Workflow chaining—linking multiple Workflows together to create clean, modular processes. This helps us run different workflows depending on the branch or tag being pushed, keeping our pipelines both dynamic and predictable.

At the highest level, we use Pipelines to run entire sets of Workflows in parallel. For example, we can run UI tests and unit tests at the same time, significantly reducing build times while maintaining confidence in our releases. This level of flexibility allows us to tailor automation around our development process—so it supports how we build, rather than the other way around.

Our CI setup before optimization

Our previous setup on Bitrise relied heavily on Workflows defined with sequential Steps. This meant each step was executed one after the other—from building the project, running linters, creating the release candidate, running unit tests & UI tests, to uploading code coverage reports to our internal code efficiency and quality Dashboard.

The following images show the build duration (total of 19m 31s) for the sequential Steps set up and the entire list of Steps, listed sequentially:

UI Image with build information
Image of GUI showing build and times

Using sequential workflows produced some sub-optimal results like:

  • Longer build times: sequential execution prevents parallelism—even independent tasks like testing and linting must wait for previous steps to finish.
  • Repetition and redundancy: similar sequences (e.g. build + download secrets) are repeated across workflows with identical logic.
  • Cluttered configuration: the bitrise.yml grows complex and harder to maintain. When logic changes, all affected workflows must be updated manually.
  • Low readability: team members, especially newcomers, find it harder to understand which parts of the process do what.

Modular Workflows with Step bundles

One of the most impactful improvements we've adopted in our CI setup at GoDaddy is the use of Step bundles—a feature in Bitrise that allows us to group a series of related Steps into a single, reusable unit.

Step bundles have brought structure and simplicity to our workflows. Instead of repeating the same five to ten steps across multiple workflows, we define them once in a Bundle and reference them wherever needed. This significantly declutters our configuration files, making them easier to read and maintain.

The following list describes some of the key benefits with using Step bundles:

  • Reusability: The same bundles are used across different types of workflows—CI, PR validation, release builds—ensuring consistency without code duplication.
  • Improved readability: Step bundles make it easy for developers to understand what a workflow is doing at a glance. Rather than parsing a long list of individual steps, teams see clearly defined, high-level actions that reflect our development process.
  • Centralized updates: When we need to change how we set up the Android environment, for example, we modify the logic in one Bundle—and every workflow that uses it instantly benefits from the update.

By modularizing our CI logic with Step bundles, we've made our workflows not only more scalable, but also far easier to navigate and evolve as our needs grow.

Isolating the basic setup Steps allowed us to reuse them across different Workflows, whether using Pipelines or sequential definitions. Any changes made to this configuration are automatically reflected everywhere the bundle is used.

The following image shows the bundled structure of the workflow:

Step bundles + Bitrise Pipelines = Smarter, Faster CI

At GoDaddy, our goal is always to deliver high-quality mobile features quickly and reliably. One of the most effective ways we've achieved that is by combining Step bundles with Bitrise Pipelines, particularly using Graph Pipelines—a powerful setup that's transformed the way our CI/CD flows operate.

Pipelines with stages run workflows in parallel within each stage, but stages themselves run in strict sequence, so you can’t specify that one workflow should wait for another unless they’re in different stages. Graph pipelines let you define exactly which workflows depend on which others, so you can, for example, run unit_tests only after build finishes, while allowing lint to run in parallel with build — giving you precise control over both when and how workflows run.

By integrating Step bundles into Pipelines, we've been able to:

  • Run Steps in parallel: instead of executing tasks one after another, we now run them simultaneously. For example, we can build the APK, run UI tests, and execute lint checks at the same time—dramatically cutting down total build time.
  • Decompose complex builds: our builds used to be long, monolithic processes. Now, we break them down into smaller, focused units using Bundles—each responsible for a specific part of the pipeline. This modular design makes them easier to test, optimize, and reuse across different workflows.
  • Accelerate feedback loops: faster Pipelines mean faster feedback. Developers now get results from tests and builds within minutes, helping them spot issues early and stay in flow during development.

The Impact

What used to take 19 minutes in a linear pipeline can now be completed in as little as 13 minutes or less with parallel execution—saving valuable time on every pull request and accelerating our delivery cycle.

These improvements aren't just technical wins—they're quality-of-life improvements for our developers. With less time waiting on builds, our teams can focus more on building great mobile experiences and less on watching progress bars.

Speed vs. Build Credit Consumption

As we continue optimizing our CI Pipelines at GoDaddy, one consideration we keep a close eye on is build credit usage—especially when leveraging parallel execution with Bitrise Pipelines.

One important nuance of Bitrise's billing model is that each parallel Workflow within a Pipeline is treated as a separate build. So, when a Pipeline kicks off three parallel Workflows—say, one for building the APK, one for running UI tests, and another for linting—Bitrise charges for three builds instead of one.

For a single project, that might not seem like much. But across multiple apps and teams, the overhead can add up quickly—especially if not managed with care.

Our Strategic Approach

That said, we've found the time savings are often well worth the additional cost, particularly when our top priority is developer velocity and fast CI feedback loops. A streamlined development process makes a tangible difference for our engineers pushing code throughout the day.

To keep things sustainable, we take a strategic approach to when and how we use Pipelines:

  • High-frequency builds (PR triggers, merges): optimized for speed with parallel workflows for fast, actionable feedback
  • Scheduled jobs (overnight, weekends): kept simpler and more linear to avoid unnecessary build credit consumption while still ensuring important tasks like cache warming or deep regression testing get done

This balanced strategy allows us to maximize efficiency where it matters most, without overspending on infrastructure for less time-sensitive operations.

Final Solution Architecture

In the case of builds that run frequently—like those triggered by pull requests or feature branch updates—we've designed our Pipelines to prioritize speed and immediate feedback. In our final solution, all three core stages—BuildTest, and Lint—are executed in parallel, significantly reducing overall build time.

Each of these stages uses the shared logic defined in our bundle_basic-setup, keeping the configuration consistent and easy to maintain. Despite running simultaneously, each stage has a clear, focused role:

  • Build stage: ensures the app compiles correctly and the UI builds without issues
  • Test stage: runs unit tests and produces a code coverage report
  • Lint stage: handles automated code checks and static analysis

This setup is a great example of how we've used Step bundles and Pipelines together to speed up day-to-day development workflows. By breaking the work into distinct, reusable units and running them in parallel, we've reduced wait times for developers without compromising quality or coverage.

The following images show the build time after using the Pipelines feature and the Pipeline structure:

GUI image of pipeline build time
graphical user interface of pipeline structure

Conclusion

Our optimization of the Bitrise setup—transitioning from a sequential, repetitive Workflow model to a modular and parallelized structure—has resulted in a CI/CD process that is both faster and easier to manage. By isolating reusable logic into Step Bundles, we significantly reduced duplication and improved workflow clarity, enabling teams to better understand and maintain the configuration.

Leveraging Bitrise Pipelines, especially Graph Pipelines, has unlocked parallel execution of independent processes like building, testing, and linting. This shift not only reduced our build time by six minutes, but also provided clearer separation of responsibilities and better error isolation.

While Pipelines do introduce increased build credit consumption due to each parallel Workflow being billed separately, the time savings and efficiency gains make the trade-off well worth it for our team. Overall, this approach ensures a more scalable, maintainable, and performant CI pipeline tailored for Android development.

All known trademarks contained herein are the property of their respective owners and their inclusion does not represent any affiliation, endorsement, or sponsorship.


Photo by Joel Filipe on Unsplash