Fastlane, xcconfig files, and build numbers

I recently migrated 4 Xcode build configuration settings from being stored in the *.xcodeproj file into separate *.xcconfig files per configuration. I used James Dempsey‘s Build Settings Extractor to autogenerate the config files for me from the existing project build settings.

I updated the build configurations to use these xcconfig files, and then deleted the manually set values from the project file’s build settings. All of those bold customized values in Xcode’s build settings are a thing of the past – everything is in clean xcconfig files now, and it’s fantastic. Any changes we make to a build are much easier to see in the git diff, a bit win for simplicity and readability.

An interesting thing happened to our Fastlane release though. We use the following snippet in our Fastfile to update the build number for the build: increment_build_number(build_number: build_number). Oddly – our build number stopped getting updated after I made the switch to xcconfig files. All of the settings were the same, but fastlane stopped updating the build number for some reason.

This manifested by the build failing with the following in the logs:

[03:56:43]: ------------------------------------
[03:56:43]: --- Step: increment_build_number ---
[03:56:43]: ------------------------------------
There does not seem to be a CURRENT_PROJECT_VERSION key set for this project.  Add this key to your target's expert build settings.
...
[03:58:42]: ERROR ITMS-90189: "Redundant Binary Upload. You've already uploaded a build with build number '2' for version number '2.0.0'. Make sure you increment the build string before you upload your app to App Store Connect. Learn more in Xcode Help (http://help.apple.com/xcode/mac/current/#/devba7f53ad4)."

Strange, since the xcconfig files most certainly had the CURRENT_PROJECT_VERSION defined. However, re-editing that one key in the build settings and setting the value to sometime custom brought me one step closer. Fastlane was then able to update the build number, but was for some reason still showing the wrong static build number during upload.

[03:56:43]: ------------------------------------
[03:56:43]: --- Step: increment_build_number ---
[03:56:43]: ------------------------------------
[03:56:44]: $ cd /Users/distiller/project && agvtool new-version -all 210575 && cd -
[03:56:44]: ▸ Setting version of project Muse to:
[03:56:44]: ▸ 210575.
[03:56:44]: ▸ Also setting CFBundleVersion key (assuming it exists)
...
[03:58:42]: ERROR ITMS-90189: "Redundant Binary Upload. You've already uploaded a build with build number '2' for version number '2.0.0'. Make sure you increment the build string before you upload your app to App Store Connect. Learn more in Xcode Help (http://help.apple.com/xcode/mac/current/#/devba7f53ad4)."

The noncommittal note about CFBundleVersion gave me a clue. Our path to the Info.plist had also been set explicitly in the build settings before the move to xcconfig. I removed INFOPLIST_FILE from the xcconfig files and set the value manually in the project build settings, and suddenly fastlane was able to correctly generate new build numbers and set them for the product.

[05:16:54]: ------------------------------------
[05:16:54]: --- Step: increment_build_number ---
[05:16:54]: ------------------------------------
[05:16:55]: $ cd /Users/distiller/project && agvtool new-version -all 210591 && cd -
[05:16:56]: ▸ Setting version of project Muse to:
[05:16:56]: ▸ 210591.
[05:16:56]: ▸ Also setting CFBundleVersion key (assuming it exists)
[05:16:56]: ▸ Updating CFBundleVersion in Info.plist(s)...
[05:16:56]: ▸ Updated CFBundleVersion in "Muse.xcodeproj/../Muse Tests/Info.plist" to 210591
[05:16:56]: ▸ Updated CFBundleVersion in "Muse.xcodeproj/../Muse/Info.plist" to 210591
[05:16:56]: ▸ Updated CFBundleVersion in "Muse.xcodeproj/../MuseShare/Info.plist" to 210591

Sure enough! After explicitly setting both the CURRENT_PROJECT_VERSION and the INFOPLIST_FILE, Fastlane was able to set the build number correctly. If either or both of those were set only in xcconfig files, the build version would fail – they both need to be set manually in the project’s build settings.