This article is written by Pedro Piñera Buendia, Software Engineer @ Tuist
Headline: The transition to Codemagic made our CI builds faster and more reliable and positively impacted the experience of contributors contributing to our open-source project, Tuist.
Thanks to Codemagic’s support, we can bring new free goods to the Swift community and the ecosystem of app developers.
Helping scale Xcode development
Since the introduction of the iOS platform, the Apple ecosystem has experienced an explosion of new platforms, capabilities, and programming languages like Swift that Xcode had to keep up with to support developers in their journey of making apps. While Xcode and Xcode projects provide all the tools necessary to build, test, analyze, and release apps, they still need to support developers who use them to develop apps at scale. Organizations often experience slow and unreliable incremental builds, brittle modular projects that are hard to reason about, and a lack of data and flexibility to make informed decisions about the project’s future to ensure it remains healthy and fosters a healthy development environment.
At that point, some organizations prefer to abstract the platform with technologies like React Native or Flutter, which leverage runtimes with better hot-reloading capabilities. Others prefer to replace Xcode’s build system with alternatives like Bazel, which comes at a considerable cost for many organizations. For everyone else, no solution existed until 2018, which motivated us to build Tuist, an open-source tool for working with Xcode projects at scale.
Since its inception, the tool has grown in capability and popularity, supporting large organizations like Trendyol, Bumble, Monday.com, Etsy, and American Express. Their teams love the tool, and we work very closely with their platform teams to build the best tool in the space while ensuring its simplicity of usage makes it accessible.
Recently, we decided to look for an alternative CI solution that could provide faster and deterministic environments with higher bandwidth, and that is to keep supporting our open-source development, which, as you know, is known for its limited budget. When we came across Codemagic and pitched the idea of adopting it as a service, they poured resources into helping us make that happen and supporting us in our vision. What follows is our experience migrating to Codemagic.
Automating workflows with CI pipelines
Our usage of CI pipelines is standard. We build the project and run tests in every commit pushed upstream. We use the same tool used locally to provision the environment deterministically, Mise, and then bash scripts encapsulate the logic for building and testing, which we do through the Swift Package Manager, Tuist itself, and xcodebuild. Additionally, we have pipelines that automate releases and warm the Tuist Cloud binary cache to speed up CI and local workflows, ensuring contributors feel productive while working on the project.
Before moving to Codemagic, we used a CI/CD service from GitHub. While it worked fine in the project’s early days, we had been stretching it beyond its limits for the last few months, resulting in frequent headaches and inconveniences that prompted us to look for alternatives.
First, they needed to catch up with OS and Xcode updates. We believe being fast there is critical because developers usually auto-update Xcode in their environments, and it’s essential that we use the same version on CI that they use locally. Unfortunately, some of their updates took way too long, and some came with inconsistencies with previous images or bugs, which caused some of our builds to fail after the update. We understand that the virtualization of macOS is complex since we were in charge of maintaining similar infrastructure at previous companies. Still, at the scale in which they operate, the quality of the service was far from what we expected.
The second challenge that we faced was limited bandwidth for open-source projects. Early in the project lifecycle, when a few commits were being pushed, CI builds started seconds after we pushed commits, translating into outstanding turnaround CI times. However, lately it has taken up to an hour to start running the build. In open-source projects, where motivating someone to contribute is already a considerable effort, slow feedback in PRs might make those contributors run away out of frustration and miss the opportunity to get more involved in the project and bring new ideas.
Last but not least, they were also slow to add the latest hardware to their offering. With the transition from Intel to Apple silicon, we had to use a different environment on CI for a while compared to the one most developers were using locally, M1s. These days, most developers are already on Apple silicon and have support for M1s, so keeping up with processor updates is less critical. Still, speeding up CI runs is valuable.
Consistent, fast, and up-to-date environments with Codemagic
When we contacted Codemagic and presented them with our challenges, they were supportive. They gave us access to their system to migrate some of our pipelines and assess their solution to make an informed decision. Thanks to their M2 offering and higher bandwidth, our jobs ran faster, and spent no time in the queue waiting to be picked up. It felt insanely fast. We trusted their word for their ability to keep up at a good pace with Apple’s updates, which we could validate once we have everything migrated and Apple released new versions of their software. They update their images very quickly and seem extremely careful not to introduce breaking changes that might cause the breakage of existing pipelines.
After migrating the first pipeline and having a great experience, we moved all our pipelines to Codemagic. One important lesson from that work is that it is essential to have as little logic as possible in the pipelines and more in scripts, which can also be run locally. This is key for portability, which was not optimized when we started working on the project.
One of the pieces that played an instrumental role was Mise, a tool that we use for provisioning environments deterministically with the tools the project depends on. If you are familiar with Homebrew, think of it as Homebrew, but it’s better at managing multiple versions and with the ability to scope versions to projects and activate them automatically. In the case of Tuist, we use the tool to install SwiftLint, SwiftFormat, and the last released version of Tuist, which we run against the Tuist project itself. Thanks to the tool, setting up the Codemagic environments came down to just invoking “mise install.”
Moreover, Mise provides support for what they call tasks, which you can think of as an improved version of Makefiles, but that also ensures the proper dependencies are activated and used from your scripts. We moved all our logic to scripts and used Mise as an interface to invoke them. For instance, our documentation is built by running “mise run docs:build”.
One minor hiccup was that contributors could only access the build logs if they were part of the organization on Codemagic. When we presented them with the problem, they blew our minds when they came back with a solution in less than a day. Developers can now access the logs of the builds associated with their PRs. They do this by ensuring that the logs have been previously processed to prevent any sensitive information from leaking.
Closing words
Transitioning from CI services is costly since there’s no standard pipeline language that makes setups portable. However, the transition to Codemagic proved worth it, considering the speed boost and the reliability we got after the transition. Don’t people say that the best services are those that you don’t notice exist because they are doing a fantastic job in the background? Codemagic has become one of those for us.
Moreover, we are grateful that Codemagic supported us in the transition by offering free service. Open-source projects traditionally need help to remain sustainable. The existence of companies like Codemagic that acknowledge those challenges and contribute their part to it is a net positive for the entire ecosystem of Tuist users and users of the open source work that we produce under the Tuist organization, like XcodeProj, and the new component kit for building great terminal experiences with Swift, SwiftTerminal. With companies like Codemagic, producing commodities many organizations can benefit from is possible.
Discussion about this post