iOS command-line build: How to create xcode archive from command line? - ios

I am using below command to create an signed ipa file from command line i.e. terminal.
xcrun -sdk iphoneos PackageApplication \
"path/to/build/MyApp.app" \
-o "output/path/to/MyApp.ipa" \
--sign "iPhone Distribution: My Company" \
--embed "path/to/something.mobileprovision"
As understood from above, this will create an ipa file. But, I want to create a xcarchive file which will be used to upload to app store using Application Loader. How can I modify this command to achieve that. Any help will be greatly appreciated. Thanks...

Just use xcodebuild archive command

Related

Change the IPA name or Archive name dynamically when archiving

Is there a way to change dynamically the name of the archives when it finishes to compiling without adding it manually like I do now (with a script for example). I would like to add the version after each archiving in suffix to the name of the app, for example :
The command lines in the terminal doesn't interest me as it takes more time to do it by command than just adding 4 characters manually (cf Renaming of IPA app name or Xcode "Build and Archive" from command line) like this:
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "${RELEASE_BUILDDIR}/${APPLICATION_NAME}.app" -o "${BUILD_HISTORY_DIR}/${APPLICATION_NAME}.ipa" --sign "${DEVELOPER_NAME}" --embed "${PROVISONING_PROFILE}”
My goal is to have an ipa with the name of the app, and the version with Xcode.
Thanks.

Create IPA with symbols using xcrun

I noticed a different when creating an .ipa file manually using xcrun than exporting it from xcode. The xcrun version doesn't have any symbols included with the .ipa.
I was wondering what's the best way to create an .ipa with symbols (no reason not to send them) manually from the command line, I'm using TeamCity CI to generate our production .ipa files.
I use the following command line to generate the IPA -
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "DerivedData/MyApp/Build/Products/Release-iphoneos/MyApp.app" -o "~/MyApp.ipa" --sign "<HIDDEN>" --embed "<HIDDEN>"
I run it after invoking xcodebuild so the Release-iphoneos folder got the latest release version of my app.
I'll answer myself -
In Xcode 7 Apple added the ability to specify export options plist file to better control the .ipa file creation.
One of the options there is <key>uploadSymbols</key> that does exactly what I need.
http://www.matrixprojects.net/p/xcodebuild-export-options-plist

How to resign an app with app store provisioning profile to add beta-reports-active key?

In order to distribute apps via Apple's new Test Flight service the beta-reports-active key needs to be present. Currently I'm using Apple's bot server to distribute to the old Test Flight system with and Ad Hoc distribution profile. Using a post build trigger I want to take the archive that is created and build an App Store Distribution ipa that I can upload to iTunes Connect. I've written a script that does this. I use the xcrun command to build:
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "${APP}" -o "${APP_STORE_IPA}" --sign "${SIGNING_IDENTITY}" --embed "${PROVISIONING_PROFILE}"
The SIGNING_IDENTITY and PROVISIONING_PROFILE are both app store distribution certificates/profiles. So the provisioning profile is getting embedded in the ipa and it contains the beta-reports-active flag. However, when I look at the ipa to verify its entitlements it is not present.
What am I doing wrong? All information I've seen on this has just suggested regenerating the provisioning profile. I've done this and know the key is present. It is not getting added to the entitlements. I have a widget that gets bundled in the ipa as well. I am not resigning that.
You could always try using the xcodebuild export command:
xcodebuild -exportArchive -archivePath '{APP}' -exportPath '{IPA}' \
-exportFormat 'ipa' -exportWithOriginalSigningIdentity
or if you want a different profile and identity:
xcodebuild -exportArchive -archivePath '{APP}' -exportPath '{IPA}' \
-exportFormat 'ipa' -exportWithOriginalSigningIdentity \
-exportProvisioningProfile {profilename} -exportSigningIdentity {identityname}
See man xcodebuild for more info.
Alright so I think I've finally got this figured out. It seems as though the Bot Server may have a few kinks that Apple needs to iron out. I noticed that the Distribution IPA that is generated by the Bot Server lacks any of the required entitlements of my Application. I did a little searching and found other people are having the same problem. Here's a question that explains the issue really well: IPA created via Xcode bot fails to run for APNS but runs if built manually via Xcode itself or built as an archive by Xcode
So with this in mind I created and added an entitlement file to my project with the minimum entitlements I needed. I also did the same for the widget that is in my project. Then during my post integration trigger I read both entitlement files and add the necessary entitlements to it.
# Copy the Entitlements file out of the payload so we can update it
APP_ENTITLEMENTS="/tmp/distributionEntitlements.plist"
rm -rf ${APP_ENTITLEMENTS}
codesign -d --entitlements :${APP_ENTITLEMENTS} "/tmp/Payload/MyAppName.app"
WIDGET_ENTITLEMENTS="/tmp/widgetDistributionEntitlements.plist"
rm -rf ${WIDGET_ENTITLEMENTS}
codesign -d --entitlements :${WIDGET_ENTITLEMENTS} "/tmp/Payload/MyAppName.app/Plugins/${WIDGET_NAME}"
# Copy over the latest build the bot just created
echo "Copying latest Archive to /tmp/...";
cp -Rp "${XCS_ARCHIVE}" "/tmp/"
APP="/tmp/Archive.xcarchive/Products/Applications/MyAppName.app"
echo "Updating entitlements file"
/usr/libexec/PlistBuddy -c "Add :beta-reports-active bool true" ${APP_ENTITLEMENTS}
/usr/libexec/PlistBuddy -c "Add :aps-environment string production" ${APP_ENTITLEMENTS}
cat ${APP_ENTITLEMENTS}
echo "Updating widget entitlements file"
/usr/libexec/PlistBuddy -c "Add :beta-reports-active bool true" ${WIDGET_ENTITLEMENTS}
cat ${WIDGET_ENTITLEMENTS}
Then of course you have to codesign these apps again:
echo "Codesign the widget"
cp "${WIDGET_PROVISIONING_PROFILE}" "${APP}/Plugins/${WIDGET_NAME}/embedded.mobileprovision"
codesign -fv -s "${FULL_SIGNING_IDENTITY}" "${APP}/Plugins/${WIDGET_NAME}" --entitlements "${WIDGET_ENTITLEMENTS}" --preserve-metadata=resource-rules,requirements
echo "Codesign the app"
codesign -fv -s "${FULL_SIGNING_IDENTITY}" "${APP}" --entitlements "${APP_ENTITLEMENTS}" --preserve-metadata=resource-rules,requirements
echo "Creating .ipa"
# Remove any whitespace
FILENAME=${XCS_BOT_NAME// /}
echo "Filename: ${FILENAME}"
APP_STORE_IPA="/tmp/${FILENAME}_AppStore_${VERSION_NUMBER}.ipa"
rm "${APP_STORE_IPA}"
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "${APP}" -o "${APP_STORE_IPA}" --sign "${SIGNING_IDENTITY}" --embed "${PROVISIONING_PROFILE}"
After all this, I can upload this IPA to Apple and distribute it using their new TestFlight beta distribution tool.
I use the following commands to resign an ipa which may work for you. The basic technique is to unzip the ipa, add in the desired mobile provisioning profile, resign the code with the desired certificate and then zip into the new ipa.
unzip -q "${IPAFILE}"
cp "${PROV_PROFILE}" Payload/*.app/embedded.mobileprovision
/usr/bin/codesign -f -s "${SIGN_CERT}" --keychain "${KEYCHAIN}" \
--entitlements Payload/*.app/$APP-Entitlements.plist \
--resource-rules Payload/*.app/ResourceRules.plist Payload/*.app
zip -qr "${NEW_IPAFILE}" Payload
You may be able to leave out the --keychain option if you're using the standard keychain. The name of your Entitlements.plist file may be different. SIGN_CERT is the text name of your certificate. e.g. "iPhone Distribution: Blah Blah"
Be sure that the Entitlements plist has the same TEAM ID as your signing cert and provisioning profile.
Xcode adds this beta entitlement to your entitlement list automatically. You just have to make a new revision, click on the Team account under the identity, reselect your account and the new profile will be remade by iTunes connect.
After that, upload your new binary.
Once it is uploaded you can assign beta testers to your app, selecting the pre-release version and adding the internal or external beta testers to the list.
I hope it helped.
A better way of doing this would be set the Release provisioning profile to the App store profile. Then you won't need to provide the --embed flag and the beta reports flag will be true.
Then if you also need a adhoc build you can provide the same xcrun command --embed with the adhoc provisioning profile.
ARCHIVE = "${ARCHIVE_FOLDER}/Products/Applications/${PRODUCT_NAME}.app"
#Adhoc
/usr/bin/xcrun -sdk iphoneos PackageApplication -v ARCHIVE -o IPA_DESTINATION --sign "SIGNING_IDENTITY" --embed PATH_TO_PROVISIONING_PROFILE
#App Store
/usr/bin/xcrun -sdk iphoneos PackageApplication -v ARCHIVE -o IPA_DESTINATION --sign "SIGNING_IDENTITY"

Export an OTA installable IPA from XCARCHIVE

I'm migrating our build scripts to produce xcarchive files, so we can upload builds right from the Xcode Organizer, however, I'm having trouble getting builds to work over the air now.
I'm building the archive with:
xcodebuild -scheme myScheme \
"CODE_SIGN_IDENTITY[sdk=iphoneos*]=$appstore_identity" \
PROVISIONING_PROFILE=$appstore_profile_id \
-archivePath $outputArchive
archive`
Then I'm trying to export and re-sign using my enterprise distribution profile with:
enterprise_profile_name=`basename $enterprise_profile_file .mobileprovision` \
xcodebuild -exportArchive \
-archivePath "$outputArchive" \
-exportFormat IPA \
-exportProvisioningProfile "$enterprise_profile_name" \
-exportPath "$outputIPA"
The resulting IPA looks correct (contains correct profile, codesign says it's valid, etc), however, when we generate a manifest file so this can be installed over the air things stop working. On iOS 7 devices get into the 'Installing..., Waiting...' loop and the app never get's installed.
Any suggestions?
Update 1
I've also tried exporting an app from the archive and then resigning that with PackageApplication:
xcodebuild -exportArchive \
-archivePath "$outputArchive" \
-exportFormat APP \
-exportWithOriginalSigningIdentity \
-exportPath "$outputApp"
xcrun PackageApplication \
"$outputApp" \
-o "$outputIPA" \
--sign "$enterprise_identity" \
--embed "$enterprise_profile_file"
But the resulting IPA still fails to install OTA and syncing via iTunes.
#MishieMoo and I chatted offline and it seems that what I'm trying to do isn't possible because I am trying to work across teams. I have 2 teams A and B, each with their own identity and provisioning profile. A has a enterprise profile for com.foo.*. B has a regular profile for com.foo.bar.
I was building with B and trying to resign with A. However that isn't working because they are 2 different accounts with 2 different team identifiers.
Result: I need to build twice (once for each account).

Generating ipa from xcode command-line

Whats the best approach for generating an IPA file from command-line?
I'm on xcode 4.2 and generating the archive using:
xcodebuild -scheme AppStore clean archive
This generates the .dSYM and .app files in the build output directory, after codesigning. How should I proceed to generate the .ipa file? In other words, I'm looking for the command-line equivalent of doing the following in GUI
Organizer - Archives
Share
iOS App Store Package
Don't Re-sign
Thanks!
The missing piece is using the PackageApplication utility.
/usr/bin/xcrun -sdk iphoneos PackageApplication -v $FULL_PATH_TO_APP -o $OUTPUT_PATH
You can also pass this script options for resigning, and profile embedding. Using the --sign and --embed flags respectively.
This tool makes it trivial to build (and distribute): https://github.com/nomad/shenzhen
After Archive, you need to "Export" to desired format ie ipa:
xcodebuild -sdk iphoneos7.0 -archivePath "path to archive file" -exportPath "path_for_export" -exportFormat ipa -exportArchive -exportProvisioningProfile "provisioning_profile_to_export_with"

Resources