10. CocoaPods: The Dumpster Fire That Refuses to Die
This is the most painful process. I thought it would take like three minutes, but NO - it took hours upon hours of figuring out what on earth was going wrong and why.
So, since I had to suffer through this second layer of hell torment, you don't have to.
What Even Is CocoaPods?
Essentially, Apple's developer tooling is a dumpster fire wrapped in shiny aluminum. For years, the go-to package manager in iOS land wasn't even made by Apple. It was CocoaPods - a third-party hack duct-taped together by the community because Apple couldn't be bothered.
It runs on Ruby (because of course it does, why not throw another language into your toolchain?) and you install it as a gem. Fun times.
The name?
Cocoa → Apple's cutesy branding for their frameworks.
Pods → little self-contained modules you drop into your app.
So no, not entirely arbitrary - but very much the vibe of someone way too pleased with themselves while naming it.
To Apple's credit, they eventually built Swift Package Manager, which is what they actually want you to use now. But for years, CocoaPods was the duct tape holding half the iOS ecosystem together.
Why It Breaks (And Keeps Breaking)
If you're building with Ionic/Capacitor (like CutCompass), CocoaPods is unavoidable. And it loves to implode at the worst times.
Classic errors:
CocoaPods install failed.
[!] CocoaPods could not find compatible versions for pod "Capacitor"
pod install returned an error code
No explanation. No fix. Just vibes.
So How Do We Fix This?
By making our own Fastlane workflow. (Good God save us.)
⚠️ Note: this is all assuming you're using Ionic + Appflow for automation. If you're using literally anything else… best of luck, since this might not even be applicable.
Step 1 - Root .bundle/config
---
BUNDLE_PATH: "vendor/bundle"
BUNDLE_DEPLOYMENT: "true"
BUNDLE_FROZEN: "true"
BUNDLE_WITHOUT: "development:test"
Step 2 - Root Gemfile
source "https://rubygems.org"
ruby ">= 3.1"
gem "fastlane", "~> 2.228"
gem "cocoapods", "~> 1.15", ">= 1.15.2"
Step 3 - iOS Project Gemfile
ios/App/Gemfile
source "https://rubygems.org"
gem "cocoapods", "~> 1.16" # plays nice with Xcode 16
And add another .bundle/config in ios/App/ pointing back to ../../vendor/bundle.
Step 4 - Fastlane Workflow
fastlane/Fastfile
# fastlane/Fastfile
default_platform(:ios)
platform :ios do
desc "Build Capacitor iOS via Bundler-managed CocoaPods"
lane :build_capacitor do
# Root bundle for fastlane, etc. (optional if you don't need root gems)
sh("bundle install --path=vendor/bundle")
# >>> Install the ios/App bundle (this is the critical bit) <<<
sh(%q[bash -lc 'cd ios/App && bundle config set path ../../vendor/bundle && bundle install --jobs=4 --retry=3'])
# Make sure subsequent Bundler calls use ios/App/Gemfile
ENV["BUNDLE_GEMFILE"] = File.expand_path("../ios/App/Gemfile", __dir__)
# CocoaPods via Bundler from ios/App (ok if Appflow also runs its own step later)
cocoapods(
project_directory: "ios/App",
use_bundle_exec: true,
repo_update: false,
verbose: true
)
# Now Capacitor sync (will call bundle exec pod install again, which now works)
sh("npx cap sync ios --deployment")
build_ios_app(
workspace: "ios/App/App.xcworkspace",
scheme: "App",
clean: true,
export_method: "app-store"
)
end
end
Step 5 - Lock It Down
From root:
rm -f Gemfile.lock
bundle config set path vendor/bundle
bundle install
bundle lock --add-platform ruby
bundle lock --add-platform arm64-darwin-23
bundle lock --add-platform x86_64-darwin-23
bundle install
Do the same in ios/App/.
Survival Tips
Don't trust system Ruby - install with Homebrew. (Seriously, just don't, it is outdated)
Keep Gemfiles in sync (root + ios/App).
Expect CocoaPods to break for no reason.
Pray. Sometimes that's the only fix.
Coming Up Next
Now that we've bullied CocoaPods into working, it's time to set up the pipelines that will save you from repeating this process: CI/CD automation with Appflow.
Because if you had to do this manually for every update? You'd quit apps forever.


