simctl + xcodebuild changing simulator state - jenkins

I'm trying to automate the functional testing I have in my project. For this, I use Jenkins and run the test tasks using the post-receive git hook. The job is properly invoked, but before the tests are run, I need to erase the simulators in order to tests first time startup of the app. I do the following:
#!/bin/bash --login
# simulator we want
sim="iPhone 6"
# close the iOS simulator if open
echo "Trying to close iOS Simulator"
osascript -e 'tell app "iOS Simulator" to quit'
# find all booted devices
booted=( $(xcrun simctl list | sed -n 's/.*(\(.*\)) (Booted)/\1/p') )
if [ ${#booted[#]} != 0 ]; then
echo 'Found the following booted devices:'
for device in ${booted[#]}
do
echo $device
done
else
echo 'There are no booted devices, skipping'
fi
# shutdown all of them to be able to erase them
for device in ${booted[#]}
do
echo "Trying to shutdown $device"
xcrun simctl shutdown $device
echo "Done"
done
# sanity check, all devices should be shutdown
booted=( $(xcrun simctl list | sed -n 's/.*(\(.*\)) (Booted)/\1/p') )
if [ ${#booted[#]} != 0 ]; then
echo 'Even though we shut down all the devices, some devices are still booted:'
for device in ${booted[#]}
do
echo $device
done
exit 1
fi
# erase the device so we can test index page and tutorial
allDevices=( $(xcrun simctl list | sed -En 's/.* \((.*)\) \((Shutdown)\)/\1/p') )
for device in ${allDevices[#]}
do
echo "Erasing device $device"
xcrun simctl erase $device
echo
done
# sanity check, all devices should be shutdown
booted=( $(xcrun simctl list | sed -n 's/.*(\(.*\)) (Booted)/\1/p') )
if [ ${#booted[#]} != 0 ]; then
echo 'Even though we shut down all the devices, some devices are still booted:'
for device in ${booted[#]}
do
echo $device
done
exit 1
fi
echo device list:
echo $(xcrun simctl list)
dev=( $(xcrun simctl list | sed -En 's/'"$sim"' \((.*)\) \((Shutdown)\)/\1/p') )
echo Booting the device $dev
xcrun simctl boot $dev
# clean is not good enough, need to remove DerivedData contents manually
rm -rf ~/Library/Developer/Xcode/DerivedData
/usr/local/bin/xctool -workspace MyApp.xcworkspace -scheme MyApp_QA2 clean
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp_QA2 -destination 'platform=iOS Simulator,name=iPhone 6,OS=8.1' test | xcpretty -c -r html
When I run this, I get:
These lines are responsible for booting:
dev=( $(xcrun simctl list | sed -En 's/'"$sim"' \((.*)\) \((Shutdown)\)/\1/p') )
echo Booting the device $dev
xcrun simctl boot $dev
So, I comment them, but then the build fails with:
2015-03-10 09:56:13.036 xcodebuild[84840:4008451] [MT]
iPhoneSimulator: Unable to connect to
"com.apple.instruments.deviceservice.lockdown" (Error
Domain=com.apple.CoreSimulator.SimError Code=146 "Unable to lookup in
current state: Shutdown" UserInfo=0x7fbcb2f00af0
{NSLocalizedDescription=Unable to lookup in current state: Shutdown})
Looks to me like Xcode and simctl can't agree which one should be responsible for booting the correct sim. Any ideas?

You can launch the simulator with xcrun instruments -w "iPhone 5 (8.4 Simulator)"
and to shut down the simulator with killall "iOS Simulator"

In Xcode 6 and Xcode 7, Simulator.app is responsible for booting the device it uses. If you use simctl to boot the device, it will not be usable by Simulator.app in that state because it will be booted to a headless state.

Related

Xcode 13 beta: "xcrun: error: Failed to locate 'instruments'"

Please note, I'm looking for /Applications/Xcode.app/Contents/Developer/usr/bin/instruments util (lower-case), not the Instruments app which can be found in Xcode.app/Contents/Applications.
I have both Xcode12 and Xcode13-beta-5 on my computer.
When run xcrun instruments -w <device id>, Xcode13 says xcrun: error: Failed to locate 'instruments'.
Locating the "instruments" in Xcode12:
olia#Olhas-MacBook-Pro % ls /Applications/Xcode.app/Contents/Developer/usr/bin/*instruments*
# output ✅
/Applications/Xcode.app/Contents/Developer/usr/bin/instruments
Locating the "instruments" in Xcode13:
olia#Olhas-MacBook-Pro % ls /Applications/Xcode-beta.app/Contents/Developer/usr/bin/*instruments*
# output ❌
zsh: no matches found: /Applications/Xcode-beta.app/Contents/Developer/usr/bin/*instruments*
Here, Xcode-beta.app is Xcode13, and Xcode.app is Xcode12.
There's no "instruments" util because it was deprecated in Xcode12, and in Xcode13 it seems to be removed.
Apple recommends using xcrun xctrace instead of xcrun instruments in Xcode12.
But as command xcrun instruments -w is for pre-launching Simulator, xctrace doesn't apply there.
We can run smth like
open -a Simulator.app --args -CurrentDeviceUDID <device id>
haha ~, I copied Xcode 's instruments to Xcode13 's /Applications/Xcode.app/Contents/Developer/usr/bin/ , then run react-native run-ios successful.
For me I needed to upgrade react-native using:
yarn upgrade react-native

Jenkins iOS Codesigning failed with exit code 1

What Jenkins settings need to be configured for it to sign iOS apps for apple mobile devices? I'm trying to set up Jenkins on a spare MacBook to do CI on a new iOS app for the first time.
I can build and deploy from the command line
Jenkins is configured to use the same command as the one that works in the terminal PATH=~/Qt/5.9.2/ios/bin:$PATH make -j 12 QMAKE_FLAGS="QPROTOC=/Users/admin/projects/build-QObjectProtobufCompiler-Desktop_Qt_5_9_2_clang_64bit-Debug/qprotoc/qprotoc CONFIG+=iphoneos CONFIG+=device" BUILD_ARCH=ios
I set Jenkins to use the same user as the one I am building on the command line with (including changing folder, log, etc ownership)
this is a qt project (make invokes qmake and then make on the auto-generated makefile)
This is the Jenkins error output I get:
PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/ Xcode.app/Contents/Developer/usr/bin:/Users/admin/Qt/5.9.2/ios/bin:/usr/bin:/bin:/usr/sbin:/sbin"
export XCODE_DEVELOPER_USR_PATH=/Applications/Xcode.app/Contents/Developer/usr/bin/..
/Applications/Xcode.app/Contents/Developer/usr/bin/ibtool --errors --warnings --notices --module connect --output-partial-info-plist /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app/connect.build/ Debug-iphoneos/connect.build/LaunchScreen-PartialInfo.plist --auto-activate-custom-fonts --target-device iphone --target-device ipad --minimum-deployment-target 8.0 --output-format human-readable-text --compile / Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app/Debug-iphoneos/connect.app/LaunchScreen.nib / Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app/connect.xcodeproj/LaunchScreen.xib
ProcessInfoPlistFile Debug-iphoneos/connect.app/Info.plist /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/app/ ios/Info.plist
cd /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/ Applications/Xcode.app/Contents/Developer/usr/bin:/Users/admin/Qt/5.9.2/ios/bin:/usr/bin:/bin:/usr/sbin:/sbin"
builtin-infoPlistUtility /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/app/ios/Info.plist -genpkginfo / Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app/Debug-iphoneos/connect.app/PkgInfo -expandbuildsettings -format binary -platform iphoneos -additionalcontentfile /Users/Shared/Jenkins/Home/ workspace/mobileAppIOS/.build/ios/app/connect.build/Debug-iphoneos/connect.build/Launch-PartialInfo.plist -additionalcontentfile /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app/connect.build/ Debug-iphoneos/connect.build/LaunchScreen-PartialInfo.plist -o /Users/Shared/Jenkins/Home/workspace/ mobileAppIOS/.build/ios/app/Debug-iphoneos/connect.app/Info.plist
ProcessProductPackaging /Users/admin/Library/MobileDevice/Provisioning\ Profiles/ REDACTED.mobileprovision Debug-iphoneos/connect.app/embedded.mobileprovision
cd /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/ Applications/Xcode.app/Contents/Developer/usr/bin:/Users/admin/Qt/5.9.2/ios/bin:/usr/bin:/bin:/usr/sbin:/sbin"
builtin-productPackagingUtility /Users/admin/Library/MobileDevice/Provisioning\ Profiles/ REDACTED.mobileprovision -o /Users/Shared/Jenkins/Home/workspace/ mobileAppIOS/.build/ios/app/Debug-iphoneos/connect.app/embedded.mobileprovision
Touch Debug-iphoneos/connect.app
cd /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/ Applications/Xcode.app/Contents/Developer/usr/bin:/Users/admin/Qt/5.9.2/ios/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/usr/bin/touch -c /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app/Debug-iphoneos/connect.app
ProcessProductPackaging "" connect.build/Debug-iphoneos/connect.build/connect.app.xcent
cd /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/ Applications/Xcode.app/Contents/Developer/usr/bin:/Users/admin/Qt/5.9.2/ios/bin:/usr/bin:/bin:/usr/sbin:/sbin"
Entitlements:
{
"application-identifier" = "REDACTED.com.precisionplanting.connect";
"com.apple.developer.team-identifier" = REDACTED;
"get-task-allow" = 1;
"keychain-access-groups" = (
"REDACTED.com.precisionplanting.connect"
);
}
builtin-productPackagingUtility -entitlements -format xml -o /Users/Shared/Jenkins/Home/workspace/ mobileAppIOS/.build/ios/app/connect.build/Debug-iphoneos/connect.build/connect.app.xcent
CodeSign Debug-iphoneos/connect.app
cd /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app
export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin /codesign_allocate
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/ Applications/Xcode.app/Contents/Developer/usr/bin:/Users/admin/Qt/5.9.2/ios/bin:/usr/bin:/bin:/usr/sbin:/sbin"
Signing Identity: "iPhone Developer: Michael Rink (REDACTED)"
Provisioning Profile: "iOS Team Provisioning Profile: *"
(REDACTED)
/usr/bin/codesign --force --sign EA9034E507C1108550F4A5269522F7EAA05FDE05 --entitlements /Users/Shared/Jenkins/ Home/workspace/mobileAppIOS/.build/ios/app/connect.build/Debug-iphoneos/connect.build/connect.app.xcent --timestamp=none /Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app/Debug-iphoneos/connect.app
/Users/Shared/Jenkins/Home/workspace/mobileAppIOS/.build/ios/app/Debug-iphoneos/connect.app: unknown error -1=ffffffffffffffff
Command /usr/bin/codesign failed with exit code 1
** BUILD FAILED **
The following build commands failed:
CodeSign Debug-iphoneos/connect.app
(1 failure)
make[2]: *** [xcodebuild-debug-device] Error 65
The key is to enable the keychain containing the certificates and provisioning profiles for code signing. This can be accomplished by:
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k keychainPass keychainName
This is a related issue on fastlane's github
This is the post I wrote to setup the whole pipeline using fastlane and Jenkins

Using xcodebuild to install application on iPhone

I am working on a shell script that builds and install our xcodeproj directly to the first found and connected iDevice. This is the script
#!/bin/bash
cd ../../cordova/platforms/ios
deviceName=$(ideviceinfo | grep -i DeviceName)
deviceName=${deviceName//DeviceName: /} #This is the device name you set in Settings->General->Info->Name on your iDevice
deviceUdid=$(system_profiler SPUSBDataType | sed -n -e '/iPad/,/Serial/p' -e '/iPhone/,/Serial/p' | grep "Serial Number:" | awk -F ": " '{print $2}')
if [ -n "deviceUdid" ]; then
echo 'Found device "'${deviceName}'" with UUID "'${deviceUdid}'", process...'
xcodeProject=$(ls | grep -i *.xcodeproj)
if [ -n "$xcodeProject" ]; then
echo "Is xCode project dir, start building..."
################### Not working command ###################
eval "xcodebuild -scheme AppScheme -destination 'platform=iOS,id=$deviceUdid' install" #This line is not really working
################### Not working command ################
else
echo "Directory is not an xCode project directory!"
fi
else
echo 'It looks like there is no iDevice connected!'
fi
Everything works, except installing it on my iPhone. I get the correct device name, it looks like as if it finds the device, but I don't see the app on my iPhone. The strange thing is, that everything works well if I install it from xCode.
Does anyone know how to fix this issue?
I use this following commands to build and run my Application in Simulator:
xcodebuild -sdk iphonesimulator8.4 -arch i386 -workspace MyApp.xcworkspace -scheme MyApp install DSTROOT=~/MyApp
xcrun instruments -w "iPhone 5s (8.4 Simulator)"
xcrun simctl install booted ~/MyApp/Applications/MyApp.app
if you want to run in another Simulator try see available simulators with:
xcrun instruments -s

weirdness when packaging with xcrun (codesign fails when using variable)

I try to parameterize my application build script when running into this behaviour:
the app already has been build (with 'cordova build ios --release') and is available.
when calling:
$ xcrun ... -sign "iPhone Developer: XXX" -embed ...
everything goes fine. so far so good :)
now i instead want to use a variable in the call like:
$ identity="iPhone Developer: XXX"
$ xcrun ... -sign $identity -embed ...
where i later pass the $identity parameter to my build script
doing the 'xcrun ...' like above logically results in the fact that the 'codesign' command only gets "iPhone" as parameter and fails (of course:)
thus i'm trying to mask the $identity
closest call for success is to use
$ xcrun ... -sign \""$identity"\" -embed ...
which results into a 'codesign' call by the xcrun like
$ xcrun ... -sign \""$identity"\" -embed ...
[...]
/usr/bin/codesign ... --sign "iPhone Developer: XXX" ...
Program /usr/bin/codesign returned 1 : ["iPhone Developer: XXX": no identity found
]
interestingly enough executing the command directly from shell (/bin/bash) works okay !!?
i tried as well to define $identity already having double-quotes but that runs into the initial behaviour with no quotation at all. using single-quotes in various combinations didn't help either so far.
any idea why xcrun is getting it wrong ? ... or, how to do it differently?
like said: the goal is to have a parameterized build script
-------- system parameters ---------
$ uname -a
Darwin allianz 13.0.0 Darwin Kernel Version 13.0.0: Thu Sep 19 22:22:27 PDT 2013; root:xnu-2422.1.72~6/RELEASE_X86_64 x86_64
$ xcrun -version
xcrun version 22.
Okay, this weirdness seems to be due to the fact that I assembled the command line like
xcrun -sdk iphoneos PackageAppliction $package -o $ipafile -sign \"$identity
\" -embed $profile
doing it the way to assemble the parts (option1 $variable1 option2 $variable2 ... etc.) to just one string first, like
assembledstring="-sdk iphoneos PackageAppliction $package -o $ipafile -sign \"$identity
\" -embed $profile"
and only then doing a
sh -c "xcrun $assemledstring"
sorts the issue.

Is there any automatic Testflight upload script on application archiving?

I found that Testflight is supporting application uploading through API call http://testflightapp.com/api/builds.format. It accepts application package, dsyms, application info and other.
So my question is next: Is there any automatic script for xcode which will upload build into Testflight after "archive" operation? Share the links, please.
SOLUTION IS HERE (Mac OS X 10.8):
1) Follow this manual and setup post-execution script
2) Remove Replace "echo" strings with next rule:
#!/bin/bash
#
# (Above line comes out when placing in Xcode scheme)
#
API_TOKEN="<YOUR-TESTFLIGHT-API-TOKEN>"
TEAM_TOKEN="<YOUR-TESTFLIGHT-TEAM-TOKEN>"
SIGNING_IDENTITY="iPhone Developer"
PROVISIONING_PROFILE="${HOME}/Library/MobileDevice/Provisioning Profiles/<YOUR-PROFILE-NAME>.mobileprovision"
LOG="/tmp/testflight.log"
GROWL="/usr/bin/terminal-notifier -title Xcode -message"
DATE=$( /bin/date +"%Y-%m-%d" )
ARCHIVE=$( /bin/ls -t "${HOME}/Library/Developer/Xcode/Archives/${DATE}" | /usr/bin/grep xcarchive | /usr/bin/sed -n 1p )
DSYM="${HOME}/Library/Developer/Xcode/Archives/${DATE}/${ARCHIVE}/dSYMs/${PRODUCT_NAME}.app.dSYM"
APP="${HOME}/Library/Developer/Xcode/Archives/${DATE}/${ARCHIVE}/Products/Applications/${PRODUCT_NAME}.app"
#/usr/bin/open -a /Applications/Utilities/Console.app $LOG
#echo -n "Creating .ipa for ${PRODUCT_NAME}... " > $LOG
${GROWL} "Creating .ipa for ${PRODUCT_NAME}"
/bin/rm "/tmp/${PRODUCT_NAME}.ipa"
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "${APP}" -o "/tmp/${PRODUCT_NAME}.ipa" --sign "${SIGNING_IDENTITY}" --embed "${PROVISIONING_PROFILE}"
#echo "done." >> $LOG
${GROWL} "Created .ipa for ${PRODUCT_NAME}"
#echo -n "Zipping .dSYM for ${PRODUCT_NAME}..." >> $LOG
${GROWL} "Zipping .dSYM for ${PRODUCT_NAME}"
/bin/rm "/tmp/${PRODUCT_NAME}.dSYM.zip"
/usr/bin/zip -r "/tmp/${PRODUCT_NAME}.dSYM.zip" "${DSYM}"
#echo "done." >> $LOG
${GROWL} "Created .dSYM for ${PRODUCT_NAME}"
#echo -n "Uploading to TestFlight... " >> $LOG
${GROWL} "Uploading to TestFlight"
/usr/bin/curl "http://testflightapp.com/api/builds.json" \
-F file=#"/tmp/${PRODUCT_NAME}.ipa" \
-F dsym=#"/tmp/${PRODUCT_NAME}.dSYM.zip" \
-F api_token="${API_TOKEN}" \
-F team_token="${TEAM_TOKEN}" \
-F notes="Build uploaded automatically from Xcode."
#echo "done." >> $LOG
${GROWL} "Uploaded to TestFlight"
/usr/bin/open "https://testflightapp.com/dashboard/builds/"
3) Reveal provision profile in finder: go to Organazier/Devices/Provision profiles, then right mouse on your profile, and click "Reveal in finder". Copy profile name and paste to PROVISIONING_PROFILE variable instead of <YOUR-PROFILE-NAME>
4) Open terminal and install terminal-notifier:
sudo gem install terminal-notifier
5) You're ready :)
I've also created a ruby gem for this if you want to integrate this into rake tasks:
gem install testflight_upload
source on my github here
Here's a nice collection of utilities http://nomad-cli.com/
I ended up using Shenzen to automate builds and testflight deployments.
Here is one nice tutorial..may be useful for you:
http://developmentseed.org/blog/2011/sep/02/automating-development-uploads-testflight-xcode/
Shenzhen is discontinued, you can use pilot instead. It's a Ruby based tool to upload new builds and manage your beta testers. Under the hood it uses the iTunes Transporter and spaceship.

Resources