Xcode Cloud scripts: Fastlane and Cocoapods

Xcode Cloud is a CI/CD service made by Apple which is deeply integrated into Xcode. Since its introduction, there has been a lot of discussion amongst iOS developers on whether it is a good alternative to existing CI/CD providers and what migration to Xcode Cloud would look like.

Setting up this new service is rather straigh-forward for small or new apps but it can be daunting for big codebases which have been around for a long time. These big codebases tend to still rely to some extent on third-party dependency managers such as CocoaPods and on third-party CI/CD tools such as Fastlane.

The use of such third-party frameworks tends to put people off switching over to Xcode Cloud but, in this article, I will go through how the use of custom CI scripts can help you and your team progressively migrate to Xcode Cloud without having to abandon the tools you have used for a long time. More specifically, this article explains how to build an app using CocoaPods and upload the resulting app archive to AppCenter using Fastlane from an Xcode Cloud workflow.

CI scripts

Xcode Cloud provides a way to run shell scripts at different stages of a workflow. These scripts can install third party dependencies and perform tasks on top of the workflow's pre-defined steps. I won't go into too much detail about how these scripts work as Xcode Cloud's documentation provides a great explanation on the topic, but I will give you a TLDR on the most important things you need to know about them:

  1. Xcode Cloud looks for a directory called ci_scripts in the Xcode project to find scripts to run. These scripts are similar to git hooks in the way they work.
  2. Xcode Cloud looks for .sh scripts with specific names inside the ci_scripts directory. It then runs any matched scripts at different stages of the workflow based their names:
  1. The scripts need to have executable permissions: chmod +x <executable_name>.sh.

Now that we know how CI scripts work, let's see what we can do with them.

Installing CocoaPods dependencies

Apple recommends installing third-party tools and dependencies in the ci_post_clone.sh script and they specifically talk about making CocoaPods dependencies available to the build step in that same script too.

To do so, and assuming that you have the pod project setup, create a ci_post_clone.sh script under the ci_scripts directory mentioned earlier and add the following contents to it:

ci_post_clone.sh
#!/bin/sh

brew install cocoapods

pod install

If you push these changes and trigger a new build, Xcode Cloud will run a post clone step to install the CocoaPods dependencies.

The Xcode Cloud build page showing a successful run with a post clone script.

CocoaPods installs and links all its dependencies by creating a .xcworkspace. You need to update your workflow to use this .xcworkspace instead of the default .xcodeproj file.

Running a Fastlane lane

On top of using CocoaPods, our project requires us to upload the resulting app archive to AppCenter. Our team currently uses a Fastlane lane to do this, which in turn uses Microsoft's appcenter fastlane plugin.

To run this lane from Xcode Cloud, we must first install Fastlane in the hosted runner using the same ci_post_clone.sh script from earlier:

ci_post_clone.sh
#!/bin/sh

brew install cocoapods
brew install fastlane

pod install

After installing Fastlane, we need to create a separate script to upload the app's archive to AppCenter after the build has completed. We can do this by creating a script called ci_post_xcodebuild.sh in the ci_scripts directory, making it executable and adding the following contents to it:

ci_post_xcodebuild.sh
#!/bin/sh

# Call the custom lane
fastlane run upload_to_appcenter ipa:$CI_AD_HOC_SIGNED_APP_PATH/$CI_PRODUCT.ipa

The ci_post_xcodebuild.sh script retrieves the path to the app's archive, which is generated by the Xcode Cloud workflow, using environment variables, which are also provided by the workflow itself.

Email icon representing an email newsletter

iOS CI Newsletter

A fortnightly independent newsletter gathering all updates and news about Continuous Integration and Continuous Delivery from the iOS community.