Xcode Cloud React Native Setup

Xcode Cloud is a new CI platform from Apple. It will automatically build your app anytime you commit to certain branches. I've found that it's pretty good so far, although if it was a little faster and allowed you to cache dependencies, it would be perfect.
Setting it up for React Native applications is pretty easy. Unlike Github Actions, there is only one machine type. Thankfully it comes with Homebrew already installed, but that's it. So we must install cocoapods, and yarn, then we can actually install our dependencies.
Before we create an Xcode Cloud workflow, we need to setup our app.
Create a new file. It must be located here: ios/ci_scripts/ci_post_clone.sh
#!/bin/sh
# Install CocoaPods and yarn using Homebrew.
brew install cocoapods
brew install yarn
# Install dependencies
yarn
pod install
Edit: Check the bottom section for an updated ci_post_clone after you read through the article.
Now, if you create a new Xcode cloud workflow, it will complete successfully.
At the time of writing Xcode Cloud is in beta. The first time I did a deploy, it took 1 hour and 30 minutes.... but after that, it only took 30-40 minutes for every build. Keep in mind this is including about 10 minutes spent installing pods and npm dependencies. If Apple adds caching support in the future, app builds may get down to 15 minutes for smaller React Native apps.
Workflow Setup
Creating a workflow is pretty easy, I'll include a few step-by-step screenshots if it's your first time.


The first time you set this up, you will have to link Github to Xcode Cloud. It's a very simple process that I am not showing screenshots for.

For my develop branch, I select my debug scheme in this section. For the main branch, I create another workflow, and at this step I use the production scheme.
Also, select "TestFlight and App Store" for the production archive of your app, and "TestFlight (internal testing only)" when doing staging builds.

Without the post action, the archive will be put into App Store connect as an available testflight build, but it will not be sent out to testers automatically.
One thing to note, this section kept disappearing for me... Every time I would add it, hit save, and come back, it was gone. At the time of writing it is still in beta, so it's understandable.
To get the post action added I had to hop into the App Store connect web interface:

Click on the workflow above, and then scroll to the bottom:

With that finished, you can manually start a build, or commit to your branch!
TestFlight Groups

It's been a while since I last used TestFlight. With Xcode Cloud builds, your builds will be in sections for each branch. This is awesome, because you can have staging builds pointing to a test environment on develop, and your main branch can point to production. This makes it easy for testers to use Stripe in test mode, but also ensure production is working perfectly before a release.
My favorite part about all of this is that I have to do nothing as a developer... just code. In the past, releasing iOS apps was stressful, and CI processes were a pain, and would fail to upload builds at times, or require a new password to connect to app store connect, etc. Now, it's something you don't have to worry about anymore!
Conclusion
The only extra setup for React Native involves installing cocoapods and yarn before it builds the app. I was excited to get this working as I have a new app launching in the next few months, and this will be one less thing in the way of releasing updates over time.
If there's anything I missed or you have feedback, feel free to tweet me @zachcodes
RN 66.4 Update
It appears Xcode Cloud had a minor change, and node is no longer installed. Also, with RN 66, there is a sed command that gets ran inside of the post install section that fails to run... Here's the issue I created on the Apple Developer forums. Anyways, here's what your ci_post_clone.sh should look like now:
#!/bin/sh
export HOMEBREW_NO_INSTALL_CLEANUP=TRUE
brew install cocoapods
# have to add node yourself
brew install node@16
# link it to the path
brew link node@16
brew install yarn
# Install dependencies you manage with CocoaPods.
yarn
pod install
# the sed command from RN cant find the file... so we have to run it ourselves
sed -i -e $'s/ && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0)//' /Volumes/workspace/repository/ios/Pods/RCT-Folly/folly/portability/Time.h
I don't have time to explain any more info... it took me forever to even solve this problem... so reach out on twitter if you get stuck.