7

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.

jervine10
  • 3,039
  • 22
  • 35

5 Answers5

4

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.

Sandy Chapman
  • 11,133
  • 3
  • 58
  • 67
  • Thanks for the suggestion. I'm working on modifying my script to use that command instead. Right now it's failing with this: "error: mismatch between specified provisioning profile and signing identity" This is confusing to me because I've verified that the Provisioning Profile is the correct one and I'm signing with my iOS Distribution certificate. Any thoughts? – jervine10 Dec 02 '14 at 17:05
  • 1
    I think you might need to make sure your signing identity is full specified. I.e. instead of just "iPhone Distribution" you use "iPhone Distribution: Company Ltd. (ABCD1234)" – Sandy Chapman Dec 02 '14 at 17:21
  • @jervine10 Also, the value for `-exportProvisioningProfile` is the name, not the UUID, not the filename, but the actual name of the profile (as it shows up on the Provisioning Profiles section in the Xcode build settings). If you need help finding this, let me know. – Sandy Chapman Dec 02 '14 at 17:33
  • Thanks, I did manage to figure that out, but after that is where I'm getting the error I mentioned. – jervine10 Dec 02 '14 at 18:10
  • @jervine10 Do the App Ids of the provisioning profiles you're using match? – Sandy Chapman Dec 02 '14 at 23:02
  • I'm awarding you the bounty because I think this is going to be the correct approach. I was pulled from this task this week to work on something else, so I haven't been able to complete my investigation. I will report progress hopefully this week. Thanks again! – jervine10 Dec 07 '14 at 16:58
  • @jervine10 Another tip: If you want to verify the package before uploading to iTunesConnect, run `codesign --verify --verbose=2 --no-strict /path/to/package.xcarchive/Products/Applications/AppName.app`. This will print out `valid on disk` and `satisfies its Designated Requirment` if it's got the right provisioning profile and is signed with the right cert. – Sandy Chapman Dec 08 '14 at 11:52
2

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.

Community
  • 1
  • 1
jervine10
  • 3,039
  • 22
  • 35
1

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.

Glenn
  • 1,996
  • 2
  • 24
  • 32
0

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.

Endre Olah
  • 875
  • 2
  • 9
  • 25
0

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.

enter image description here

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"
Chase Florell
  • 46,378
  • 57
  • 186
  • 376
StackRunner
  • 1,463
  • 2
  • 16
  • 22