Coming to terms with Xcode 8’s new Build settings with FastLane
I have built, and am responsible for managing the build pipeline for our iOS mobile research efforts. We run 3 different build: Alpha, Beta, Release each going to a different output: HockeyApp, TestFlight, AppStore

Each of these release points are triggered by a commit to a different git branch. A commit to develop will automatically send a build to Microsoft HockeyApp, a commit to master will automatically build two versions of the App, one that is automatically sent to Apple TestFlight, while preparing a slightly different build we can manually deploy to the Apple App Store.

To make things even more interesting some of our projects two separate app targets which brings us to a total of six different configurations.
When I transitioned our build server and our projects over to Swift 3 and Xcode 8 the build configuration no longer was working so well. Apple has made some changes to how code signing and provisioning works in the new version of Xcode and as such I had to update our process.
The core of the build pipeline is fastlane which we use to automate most steps of the process.
Manual Signing
My initial hope was that I could have the project file set to Automatic signing and then when it got to the CI server the server would rewrite all the necessary fields in the project file to turn it into manual signing.

This is possible but it becomes rather difficulty if you have both frameworks and app targets inside your project — which was the case in some of our software. So we stuck with Manual signing for everything.
With Manual Signing it requires us to manage our provisioning profiles manually — which can be come somewhat of a hassle — but at least we have a small team so its currently managable.

One of my goals is to make sure that the fastlane process is non-destructive, meaning you could run it from a development machine and it would not break your project. As such the high level process flow is to store the existing build settings, then rewire the project file (as needed), do a build and restore the project back to what it was before.
Bundle ID and other Unique Fields
Each of our three build paths has a unique set of fields. The Bundle ID for example must be unique for each app.

Aditionally each bundle ID has its own unique provisioning profile provisioning — connected to the apple developer account associated with that build. So for distribution we are using our main developer account whereas, in beta and alpha testing we are signing with an enterprise account.
The provisioning profile is now stored in the build setting: PROVISIONING_PROFILE_SPECIFIER so using a combination of xcodebuild, grep and awk I extract this value
# Use a XcodeBuild | Grep | Awk | Chomp to extract provisioning profile name
EXISTING_PROFILE = sh(“xcodebuild -project #{PROJECT_FILE_PATH} -scheme #{SCHEME} -showBuildSettings | grep PROVISIONING_PROFILE_SPECIFIER | sed -E s’/[[:space:]]+PROVISIONING_PROFILE_SPECIFIER = //g’”).chomp()Once we have the value extracted I setup some additional commands. Depending on the build path I’ve defined ALPHA_PROFILE_NAME and BETA_PROFILE_NAME as well as some other variables at the top of my Fastfile
# User Specified Constants
ALPHA_PROFILE_NAME = “myProject — Alpha”
BETA_PROFILE_NAME = “myProject — Beta”
PROJECT_FILE = “myProject.xcodeproj”
# Auto Generated Constants
PROJECT_FILE_PATH = “../#{PROJECT_FILE}”
PROJECT_FILE_XML = “#{PROJECT_FILE}/project.pbxproj”
PROJECT_FILE_XML_PATH = “../#{PROJECT_FILE_XML}”The variable provisioning_profile_specifier gets set depending on which lane you are using … aka for Alpha it would be set to the value in ALPHA_PROFILE_NAME.
Next I build some sed commands:
CONVERT_REGEX = “s/#{EXISTING_PROFILE}/#{provisioning_profile_specifier}/g”RESTORE_REGEX = “s/#{provisioning_profile_specifier}/#{EXISTING_PROFILE}/g”CONVERT_CMD = “sed -i ‘’ ‘#{CONVERT_REGEX}’ #{PROJECT_FILE_XML_PATH}”RESTORE_CMD = “sed -i ‘’ ‘#{RESTORE_REGEX}’ #{PROJECT_FILE_XML_PATH}”Basically the goal here is to store the existing provisioning profile, rewrite the project file to use the provisioning profile for build, (Bundle ID and App Name also get changed), build and then restore the profile.
Before building I call
sh CONVERT_CMD
And in the after_all block I call:
if defined? RESTORE_CMD
sh RESTORE_CMD
end
The end. :)