From Team Ovia: Fixing a bad pod repo update

ovia_badgeFrom Team Ovia: Our engineering team is working every day to solve problems in pursuit of our mission to support women and families. We’ll be documenting our solutions here to pay forward the knowledge we gain! Nick Servidio, an iOS developer at Ovia Health, recently found a solution for an interesting CocoaPods issue.

The Problem

If you’re familiar with the iOS app submission process, you know that it’s overly complicated and that it can fail even at the last second. You can have perfectly running code on your computer, but actually packaging up that code and sending it to Apple is easier said than done! I ran into some problems recently when I was about to submit a beta version of our Fertility app for review.

To set the stage, we use CocoaPods to help manage our third-party dependencies. My issues began when I ran a seemingly innocuous command in my terminal:

pod repo update

Then, when I went to install my pods using:

pod install

I got the following error:

[!] Unable to satisfy the following requirements:

- `Firebase/Performance` required by `Podfile`
- `Firebase/Performance (= 4.8.1)` required by `Podfile.lock`

None of your spec sources contain a spec satisfying the dependencies: `Firebase/Performance, Firebase/Performance (= 4.8.1)`.

You have either:
* out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
* mistyped the name or version.
* not added the source repo that hosts the Podspec to your Podfile.

Unfortunately, all of these error messages are misleading. I had just run:

pod repo update

So the first suggestion was not helpful.

I knew that I hadn’t mistyped the name or version; I actually don’t specify a version for the pod in question. Next, I checked that I had spelled the pod correctly.

The error message is deceptive because it references Firebase/Performance (= 4.8.1). If you look at the Firebase/Performance page, you can see that the latest version is only 1.1.1 as of this writing.

There’s this last hint though:

not added the source repo that hosts the Podspec to your Podfile.

This would eventually help me out, though not at first.

The CocoaPods Master Repo

I was a bit stumped, but determined to figure this out. To continue troubleshooting, I focused in on the first part of the last bullet of the error message:

not added the source repo that hosts the Podspec...

According the documentation, a Podspec “describes a version of Pod library. It includes details about where the source should be fetched from, what files to use, the build settings to apply, and other general metadata such as its name, version, and description.”

There is a Podspec for every version of every pod supported by CocoaPods. The easiest way to see how these Podspecs line up with pod versions is to go to a page like AFNetworking and click See Podspec in the lower right pane. From there, back out to the main folder containing all of the Podspecs:

AFNetworking

If you specify a version such as “1.0” in your Podfile:

pod 'AFNetworking', '1.0'

CocoaPods will use the Podspec located in the 1.0 folder to install the pod.

When a pod author wants to add a new version of a pod, they create a new Podspec, commit it, and push it up to the master repo. All of the git operations are taken care of through the CocoaPods trunk command.

As a pod user, your local CocoaPods installation becomes aware of new Podspecs by running… pod repo update!

This got me thinking: Is it possible that the Podspec for Firebase 4.8.1 is no longer hosted in the Specs Repo? It must have been located there at some point, because it was recorded in my Podfile.lock. I went to the Firebase Spec folder and sure enough, it appeared as though version 4.8.1 had been removed:

Firebase

Next, I wanted to find the exact version of the Specs Repo that used to contain Firebase 4.8.1.

After a little searching, I discovered that the Specs Repo gets cloned to your machine during your initial pod install or pod setup at ~/.cocoapods/repos/master. I went to that folder:

cd ~/.cocoapods/repos/master

It took about 30 seconds for the folder to index on my early 2015 MacBook Pro. In order to view a version history of my folder structure, I ran:

git reflog

Here’s what I saw:

09051608f68 HEAD@{0}: reset: moving to origin/master
22a847d9e74 HEAD@{1}: reset: moving to origin/master
3d32dc088be HEAD@{2}: reset: moving to origin/master
57fe50fec68 HEAD@{3}: reset: moving to origin/master
dd73ec7fefb HEAD@{4}: reset: moving to origin/master
431e3d6dddb HEAD@{5}: reset: moving to origin/master
431e3d6dddb HEAD@{6}: reset: moving to origin/master
431e3d6dddb HEAD@{7}: reset: moving to origin/master
431e3d6dddb HEAD@{8}: reset: moving to origin/master
f9a1da22d13 HEAD@{9}: checkout: moving from master to master
f9a1da22d13 HEAD@{10}: clone: from https://github.com/CocoaPods/Specs.git

I knew that pod install was working at the previous HEAD position, so I checked out the state of the Firebase Specs at SHA 22a847d9e74:

Firebase4_8_1

Sure enough, there was version 4.8.1! In order to get back to my previous state, I ran:

git reset 22a847d9e74 --hard

And just like that, my pod install worked!

Coming full circle, the situation I encountered does coincide with the error message that I originally observed:

not added the source repo that hosts the Podspec to your Podfile.

It turns out that when I ran:

pod repo update

The source repo that I specified, https://github.com/CocoaPods/Specs.git (the default Specs Repo), did not contain a podspec for Firebase 4.8.1. Google deleted it! This is interesting because it seems to violate the CocoaPods guidelines, which specify that, “A specification cannot be deleted.”

One last thing: There was some confusion about Firebase/Performance being cited in the error message, even though the “root” Firebase pod was actually the culprit.

The explanation for this lies in the fact that Firebase/Performance is a subspec of Firebase.

If you check out the Podspec Syntax Reference, it will tell you that “the ‘sub-specifications’ to compile need the source files, the dependencies, and the other attributes defined by the root specification.”

Therefore, in order to use Firebase/Peformance 1.1.1 you need Firebase 4.8.2.

Another Solution

I realized only after I had finished my journey that the simpler fix here would be to run:

pod update Firebase/Performance

This would update the offending pod version. However, this solution doesn’t sit well with me for a few reasons.

First, updating the pod would introduce considerable changes to my code base. When I’m submitting a release to Apple, I don’t like to commit anything new to my git repository. I want to be able to submit the exact version of the code that was just running beautifully on my test device.

This policy is my attempt to adhere to the scientific method, which involves controls and variables. The version of the app currently used by the general public is the control. The changes that I’m submitting to the App Store are the variable. I don’t want to introduce an additional variable by updating my third party dependencies.

Furthermore, in software development, I always like to have an undo button. I often make dumb mistakes and like to have a quick way to revert the horror!

In Conclusion

Pod makers are continually fixing and updating their products. You can keep up to date with these benefits by running:

pod repo update

And then:

pod update YourPodNameHere

After all my hemming and hawing, it turns out that Firebase 4.8.1 was removed from the Specs Repo for a reason! It probably would not be a bad idea to update your version to 4.8.2 so you can enjoy all of the nice bug fixes.

And if you don’t want to mess around by introducing unwanted changes to your repo, you can always reset the master branch of your local copy of the Specs Repo.

Thanks for reading!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s