Please Review

Jul 9, 2021

How to re-sign an .xcarchive and export to .ipa for App Store submission

I often need to submit for review on App Store Connect app projects coming from external contractors.

I am usually given .xcarchives which bundle identifiers, version numbers and codesigning need to be updated. 😅

Here is a step-by-step guide explaining how I proceed. 🤓

Suggestions are welcome and greatly appreciated, hit me up on Twitter. 🐥

0️⃣ Extract the .app from the .xcarchive

All the necessary work will be done with or within the .app, thus it is easier to create a working directory and extract it there right away :

cp -r ARCHIVE.xcarchive/Products/Applications/ .

1️⃣ Update the bundle identifier

Now we need to start updating the app's Info.plist, so let's use the right tool for the job, aka PlistBuddy : 🔧

# update the app
/usr/libexec/PlistBuddy -c "set :CFBundleIdentifier APP_BUNDLE_ID"

# and each extension accordingly
/usr/libexec/PlistBuddy -c "set :CFBundleIdentifier EXTENSION_BUNDLE_ID"

2️⃣ Extract the entitlements

Before re-signing the app, we need to update its entitlements.

Let's get these sneaky bastards thanks to codesign : ✍️

# app's entitlements
codesign -d --entitlements :- > APP_ENTITLEMENTS.plist

# extensions' entitlements
codesign -d --entitlements :- > EXTENSION_ENTITLEMENTS.plist

3️⃣ Update the entitlements data

Again, call PlistBuddy to the rescue !

This time, we will use several PlistBuddy commands in a row for the entitlements update. Instead of using -c to execute one change at a time, we will load the .plist with the tool, tell it each task we want it to execute, then save the .plist and exit when we are done.

# update app's entitlements
/usr/libexec/PlistBuddy APP_ENTITLEMENT.plist
set :application-identifier TEAM_ID.APP_BUNDLE_ID
set :keychain-access-groups:0 TEAM_ID.APP_BUNDLE_ID

# and extensions' entitlements accordingly
/usr/libexec/PlistBuddy EXTENSION_ENTITLEMENT.plist
set :application-identifier TEAM_ID.EXTENSION_BUNDLE_ID
set :keychain-access-groups:0 TEAM_ID.EXTENSION_BUNDLE_ID

4️⃣ Remove the code signature

It is time to destroy the current codesigning by fire. 🔥

rm -rf
rm -rf*/_CodeSignature
rm -rf*.appex/_CodeSignature

5️⃣ Replace the provisioning profiles

The last step before signing is to put the proper provisioning profiles in the app and its extensions :

cp APP_PROFILE.mobileprovision

cp EXTENSION_PROFILE.mobileprovision

6️⃣ Sign the .app

🚨 Be careful, respect this exact order when using codesign to re-sign the app :

# first, frameworks
codesign -f -s "Apple Distribution: CERTIFICATE"*

# then, extensions
codesign -f -s "Apple Distribution: CERTIFICATE" --entitlements EXTENSION_ENTITLEMENTS.plist

# finally, the app
codesign -f -s "Apple Distribution: CERTIFICATE" --entitlements APP_ENTITLEMENTS.plist

7️⃣ Create the .ipa 🎁

Last but not least, make the .ipa for your newly signed .app :

# some scaffolding first
mkdir output
mkdir output/Payload

# deliver the payload
mv output/Payload/

# 🚨 do not forget to copy the SwiftSupport directory from the xcarchive
cp -r ARCHIVE.xcarchive/SwiftSupport output/

# wrap everything nicely
cd output
zip -qr APP.ipa .

8️⃣ Submit the app for review 🤞🏽

Tagged with: