Build/run iOS Xcode project from Terminal - ios

I want to build a Xcode project from Terminal and then run it as required, also from Terminal.
I have been looking for a way to do this for a while now but only managed to find a method which works for the iPhone Simulator, not for the actual device it self.
Is this even possible? The reason I want to a Xcode project on a device from Terminal is because the application runs a series of automated tests and I would prefer to automate this process using a bash script.
Thanks

To build your xcode project from the command line using a bash script use:
/usr/bin/xcodebuild -target TargetYouWantToBuild -configuration Debug
Look at the man page for xcodebuild for more options.
We do this for our unit test suite target, and we use GHUnit.
This is the section of our build script for running the tests:
export GHUNIT_CLI=1
export WRITE_JUNIT_XML=1
clean
echo "Building Bamboo GHUnit Tests..."
OUTPUT=`/usr/bin/xcodebuild -target BambooAutomatedUnitTest -configuration Debug -sdk iphonesimulator4.3 build`
RESULT=`echo "$OUTPUT" | grep "\\*\\* BUILD "`
if [ "$RESULT" != "** BUILD SUCCEEDED **" ]
then
echo "$OUTPUT"
exit 1
fi
echo "${RESULT}\n"

Related

Passing dart environment variables in xcodebuild build-for-testing command

I'm trying to run my flutter integration tests on firebase test lab. Therefore I'm using dart environment variables to set my login credentials. To setup the ios test version I need to run the following command:
xcodebuild -workspace Runner.xcworkspace -scheme Runner -config Flutter/Release.xcconfig -derivedDataPath ../build/ios_integ -sdk iphoneos build-for-testing
My question is now how to set the dart environment variables in this command? On the android gradle task it works when I pass the variable as base64 string -Pdart-defines="${BASE64_STRING}". But that doesn't work for me on iOS.
Run flutter build ios in config-only mode passing your dart defines:
flutter build ios --config-only -t integration_test/example_test.dart --debug --dart-define MY_KEY=MY_VALUE
If it succeeds, you should be able to see your dart defines in Flutter/Generated.xcconfig file (encoded in base64):
$ cat ios/Flutter/Generated.xcconfig | grep DART_DEFINES
DART_DEFINES=TVlfS0VZPU1ZX1ZBTFVF
$ printf 'TVlfS0VZPU1ZX1ZBTFVF' | base64 -d
MY_KEY=MY_VALUE
If you do xcodebuild build-for-testing now, the dart defines will be compiled into your app.

Automatically run tests with each build in Xcode 6

When I run
xcodebuild -workspace ~/Documents/JudgecardXSwift/JudgecardXSwift.xcworkspace -scheme JudgecardXSwift -destination 'platform=iOS Simulator,name=iPhone 6' clean test
from command line, I can successfully run all of my tests.
Now I want to add a run script phase to my Xcode project so it will always run my tests each time I run the app. However, when I added the run script phase with the above xcodebuild command, my build always hangs:
and as you can see, it must be hanging on the run script phase I added, because it has just finished the build phase before it titled Run custom shell script 'Copy Pods Resources':
Is my method of adding a run script phase with the xcodebuild command the proper way to automatically run tests with every build? Why does it cause my build process to hang? Is it causing some kind of infinite loop with each xcodebuild command kicking off another through its run script phase?
Bit late here, so thought I would add my personal experience, but xcodebuild will kick off another build for you, importantly xcodebuild via command line as you have may not run your Build Phases as expected. I have only experienced silent failing copy commands, with those I could view the command in log files, but it did not actually copy the file.
So it may hit an infinite loop, more likely though is it's running through that build, hitting xcodebuild command, and then building as normal without some Build Phases executing properly and thus without running your tests.
In Xcode 9 this works. I've added a run script with:
echo "warning: 🚕🚕🚕 Started running myTests 🚕🚕🚕"
xcodebuild -sdk iphonesimulator -workspace myWorkspace.xcworkspace -scheme "myWorkspaceTests" test -destination 'platform=iOS Simulator,name=iPhone X,OS=11.2' CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
And if one of the tests fail, you're gonna get a build error.

Unable to auto detect APP_BUNDLE_PATH for Calabash + Jenkins

I have integrated iOS project with Jenkins. To run the automation test cases I am using the below code in shell script.
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer/
export CODESIGN_ALLOCATE=`xcode-select -print-path`/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate
xcodebuild -alltargets clean
xcodebuild -alltargets
xcodebuild -sdk iphonesimulator \
-project Myapp.xcodeProj \
-scheme Myapp-cal \
ONLY_ACTIVE_ARCH=NO \
CONFIGURATION_BUILD_DIR="$WORKSPACE/build" \
clean build
cucumber
The automation testing is working fine in xcode where as with Jenkins getting the below error.
Unable to auto detect APP_BUNDLE_PATH. Have you built your app for
simulator? Searched dir:
/Users/test/Library/Developer/Xcode/DerivedData/Myapp-fayplezntrxmdqeteknsfkkvtzla/Build/Products
Please build your app from Xcode You should build the -cal target.
Help appreciated
I believe all you need to do is export your APP_BUNDLE_PATH in your script before you call cucumber.
Something like this:
export APP_BUNDLE_PATH="${WORKSPACE}/build/Build/Products/Debug-iphonesimulator/Myapp-cal.app"
cucumber
To see an example of this in the wild see the briar-ios-example repo. [1]
FYI/BTW APP and APP_BUNDLE_PATH are interchangeable. [2]
[1] https://github.com/jmoody/briar-ios-example/blob/master/Briar/jenkins-calabash.sh
[2] http://calabashapi.xamarin.com/ios/file.ENVIRONMENT_VARIABLES.html
Deleting the contents of /Library/Developer/Xcode/DerivedData and compiling again solved this problem for me. I did not wanted to hardcode the APP_BUNDLE_PATH as I have multiple targets.
My error message was Unable to auto detect APP_BUNDLE_PATH.

Jenkins-ios: how to launch the iphone simulator from Jenkins

I'm using the Jenkins CI as build management tool on the build server and I am running my unit test cases using the below command through Jenkins.
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer/
xcodebuild -sdk iphonesimulator -project MyStore2.xcodeproj -scheme MyStore2 -configuration Debug RUN_APPLICATION_TESTS_WITH_IOS_SIM=YES ONLY_ACTIVE_ARCH=NO clean test 2>&1 | /usr/local/bin/ocunit2junit
The iPhone simulator is not launched from the Jenkins UI, whereas if I use the same command in command prompt, it is working fine.
The build console output is as below:
/Users/Shared/Jenkins/Home/workspace/iOSUnitTestCaseSample/MyStore2/Images.xcassets
2014-08-12 03:11:38.979 IBCocoaTouchImageCatalogTool[92947:303] CFPreferences: user home directory at file:///Users/Shared/Jenkins/Library/Application%20Support/iPhone%20Simulator/User/ is unavailable. User domains will be volatile.
/* com.apple.actool.compilation-results */
/Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/MyStore2-cfjvjlzuxlhdpddpszyhlozlqjdw/Build/Products/Debug-iphonesimulator/MyStore2.app/LaunchImage-700-568h#2x.png
/Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/MyStore2-cfjvjlzuxlhdpddpszyhlozlqjdw/Build/Products/Debug-iphonesimulator/MyStore2.app/Assets.car
/Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/MyStore2-cfjvjlzuxlhdpddpszyhlozlqjdw/Build/Intermediates/MyStore2.build/Debug-iphonesimulator/MyStore2.build/assetcatalog_generated_info.plist
.
.
.
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/MyStore2-cfjvjlzuxlhdpddpszyhlozlqjdw/Build/Products/Debug-iphonesimulator/MyStore2Tests.xctest/MyStore2Tests -o /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/MyStore2-cfjvjlzuxlhdpddpszyhlozlqjdw/Build/Products/Debug-iphonesimulator/MyStore2Tests.xctest.dSYM
Please guide me on how to resolve this issue. Help Appreciated.
Thanks.
I've solved this in the past by using the JNLP client on the Jenkins slave and having a user logged in. My theory is that if you launch the slave agent via SSH, there is no windowing environment for the simulator to run in.
Another solution is to use ios-sim.

Why won't my build phase scripts be executed when creating an IPA from command line?

Question - short version:
Why won't my build phase scripts be executed when creating an IPA from the command line?
When I'm running xcodebuild to create an IPA the predefined build phase scripts does not get executed. Why is that?
Question - lengthy version:
I have a workspace with a scheme I want to create an IPA out of from command line.
This works fine except for one thing; I have two scripts in the build phases of the target that is used to put the correct app version (CFBundleShortVersionString) and the correct svn revision number (CFBundleVersion). These to scripts works fine when archiving from xcode but for some reason they do not get run when archiving from command line.
First of all why is that?
Here are the scripts that are working (if archiving form xCode)
When archiving and creating the IPA from the command line I do (the essentials)
# Building
xcodebuild ARCHS="armv7 armv7s" ONLY_ACTIVE_ARCH=NO -workspace MyWorkspace.xcworkspace/ -scheme MyScheme CONFIGURATION_BUILD_DIR=${PROJECT_BUILD_DIR} -configuration Release clean build
# Creating IPA
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "${PROJECT_BUILD_DIR}/${APPLICATION_NAME}.app" -o "${IPA_OUTPUT_PATH}/${APPLICATION_NAME}.ipa"
It works and creates an IPA but none of the build phase scripts gets executed leaving both the revision number and version number untouched.
All suggestions are appreciated!
UPDATE DUE TO BDASH's ANSWER
Instead of making a clean build I make an install as
xcodebuild install ARCHS="armv7 armv7s" ONLY_ACTIVE_ARCH=NO -workspace MyWorkspace.xcworkspace/ -scheme MyScheme CONFIGURATION_BUILD_DIR=${PROJECT_BUILD_DIR} -configuration Release
The predefined script will IN FACT be executed (can be seen in the project version number) with no errors during the install. However the created IPA will have a size of ~300 bytes (instead of ~10MB) and cannot be installed on a device.
Building the app before installing it, i.e.
# Building
xcodebuild clean build ARCHS="armv7 armv7s" ONLY_ACTIVE_ARCH=NO -workspace MyWorkspace.xcworkspace/ -scheme MyScheme CONFIGURATION_BUILD_DIR=${PROJECT_BUILD_DIR} -configuration Release
# Installing
xcodebuild install ARCHS="armv7 armv7s" ONLY_ACTIVE_ARCH=NO -workspace MyWorkspace.xcworkspace/ -scheme MyScheme CONFIGURATION_BUILD_DIR=${PROJECT_BUILD_DIR} -configuration Release
and then creating the IPA will result in an IPA with executed version script and of correct size BUT it is not possible installing it on a device. Trying to put it on a device will give an error message saying
"The program "MyApp" was not installed on you iPhone device "My Device" because an unknown error has occurred."
You have "Run script only when installing" checked for at least one of the script phases. That phase won't be run when using the build action to xcodebuild, only if using the install action.

Resources