Error when attempting to run UI automation script from jenkins - ios

I am using Xcode 6.1. And i need to run a UI automation script from jenkins as a post build action. The command that i use is shown below.
instruments -t $TRACETEMPLATE -w $DEVICE $APP_PATH -e UIASCRIPT $SCRIPT -e UIARESULTSPATH $RESULTS_PATH | grep "<" > test-reports/test-results.xml
When i run that the following error is thrown by jenkins.
Failed to authorize rights (0x1) with status: -60007.
2014-11-12 16:31:30.685 instruments[488:2607] -[XRSimulatorDevice prepareConnection:]: Unable to authorize simulated daemon (99637): 8
Instruments Trace Error : Target failed to run: Permission to debug com.test.app was denied.
Any help is much appreciated.

The user that invokes Instruments must have developer permissions. The user must be in the _developer group.
Security permissions allowing the user to access Instruments must be set. See the man page for DevToolsSecurity
The user must be logged in to a window server to use the simulator. How to do this will depend somewhat on your Jenkins and OS configuration for that user. In older versions of MacOS creating an SSH connection back into the machine and running Instruments through that connection typically worked. YMMV.
Note that any of the above steps escalates the rights for the Jenkins user, which was security implications.

I got an almost identical error message to yours, and it seemed to be because when Jenkins is launched as a Launch Daemon, it doesn't have access to the screen, even if you log in as "jenkins".
I found the solution from reading this discussion: https://issues.jenkins-ci.org/browse/JENKINS-14421
You can either launch Jenkins from Terminal with java -jar jenkins.war, or you can create a Launch Agent, which runs as the logged-in user and has access to the user's screen.
I achieved the latter solution by moving /Library/LaunchDaemons/org.jenkins-ci.plist to /Library/LaunchAgents/org.jenkins-ci.plist and removing the UserName key and value from the plist. Now Jenkins doesn't start automatically when I boot the machine, but it does start when I log into the desktop, which is required for running UI Automation tests anyway.
It appears that Jenkins still can't actually launch the Simulator app, but if Simulator is already running, the UI Automation scripts proceed just fine.

I also got this error message. Moving service from LaunchDaemons to LaunchAgents didn't solve the problem. My solution was as following:
remove the service by deleting /Library/LaunchAgents/org.jenkins-ci.plist file
create an iOS application using Automator tool. (Which I think exists by default):
I chose "Library" -> "Utilities" -> "Shell Script".
Enter the content of /Library/Application Support/Jenkins/jenkins-runner.sh.
Put export JENKINS_HOME=/path/to/jenkins at the top.
Save the app somewhere
Go to Preferences -> Users & Groups -> choose your user -> Add the saved app.
This way, jenkins is run as an application after login and it has all the privilages of any other application.

Related

Jenkins iOS build using credentials and developer profile

We are using Jenkins as our CI server for our iOS team with the following setup:
Master server on OSX, not running any job
2 slaves on OSX running our integration jobs + UI Testing
Currently all signing identities and provisioning profiles for the apps are uploaded each slave which makes the administration a tad tedious and adding a new node to the cluster even more painful.
To work around this we've looked into using the credentials plugin with Developer profiles and import the profile as the first build step on all iOS jobs but are faced with to main issues:
The import developer profile seems to work the first time (at least for creating the keychain entries) but the job fails with a "no matching provisioning profile" error, even if the developer profile contains all the provisioning profiles required by the target.
Second run on the same job always fail with a "Keychain already exist" error
We've tried some work arounds for the second issue adding a shell build step removing the particular keychain but are still faced with the first error. If we manually install the profile on the slave the build passes but this defeat the purpose of using the credentials plugin.
What do you guys think?
I think the newest version of the credentials plugin now first removes any existing keychains with a matching name before importing, as seen in the log output below.
$ security delete-keychain jenkins-MyAppsBuildName-iOS
$ security create-keychain -p ******** jenkins-MyAppsBuildName-iOS
$ security unlock-keychain -p ******** jenkins-MyAppsBuildName-iOS
Because of this fact, I don't think you will have an issue anymore with duplicate keychain errors on the second run.
As far as the issue relating to the provisioning profile not being found, add the following line inside the execute shell command and run a build on jenkins.
security list-keychains
Take a look at the console for that specific build and you should see a list of all the keychains that are currently in the scope of the shell.
If you do not see "jenkins-MyAppsBuildName-iOS" as a listed keychain, this is why you are having the signing issue. Because the keychain is not listed, it is never even being searched through to find the proper signing identity/profile.
Solution: Warning: it's hacky
I'm not 100% sure why this is happening, but from other threads it appears to be a permissions issue.
Luckily there is an easy way around this.
In the execute shell command add the following:
security list-keychain -s jenkins-${JOB_NAME}
This will reset the keychain list to include the keychain needed to successfully build the project.
To verify that this now lists the proper keychain, you can add the following lines to the shell command:
security list-keychain
security list-keychain -s jenkins-${JOB_NAME}
security list-keychain
Now compare the output of the first list-keychain command with the second list-keychain command in the console. Make sure that the jenkin's build keychain is listed after the second security list-keychain output.
Warning: This will permanently change the keychain list on the system, so it is probably a good idea to reset the keychain after the build completes. You can accomplish this by settings the default desired keychain values in the xcode configuration inside of Jenkin's System Configuration section. After doing so, make sure to tick the check box "Restore OS X keychains after build process as defined in global configuration" under build environment inside of the Jenkins job's page.
Additional info: In my example I set the keychain-list to only include the keychain generated from Jenkins, but you may decide to also include the standard system and login keychain's by modifying the line as such:
security list-keychain -s jenkins-${JOB_NAME} login.keychain System.keychain
Keywords: Jenkins, iOS, slave, node, Xcode, plugin, credentials, .developerprofile

iPad run with black screen in Jenkins

i configured out jenkins in way that it was launched under my account but when i build a project for my unit tests with KIF framework, Jenkins launches iPad simulator with black screen and nothing happens (jenkins also doesn't provide any useful information).
Can anyone advice to solution of this issue?
Please note that everything works just fine from command line.
Finally, i've found the solution need to use iPad Retina or iPad Retina (64-bit):
-destination OS=7.0,name=iPad Retina
So, the last supposed suggestion doesn't work either - need another solution.
Just ran into this myself. Following up on user2738882's self-answer, I have a fix for the pitfalls his solution has:
He's correct that it was occurring due to Jenkins being run as a launch daemon process. Daemon's are launched at start without login, but they aren't intended to have access to the UI. This is what causes the issue.
Unfortunately Jenkins defaults to installing as a launch daemon if you install via the Archive (.war).
The solution I went with is to move it over to a launch agent. To do so follow these steps:
sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
sudo cp /Library/LaunchDaemons/org.jenkins-ci.plist /Users/<Path to Jenkins User>/Library/LaunchAgents/org.jenkins-ci.plist
Right click - > Get Info on the org.jenkins-ci.plist file
Change the read write permissions to all users (bottom)
Modify the plist file to change GroupName key value from "daemon" to "agent"
Right click -> Get Info again
Reset the file access to as it was before
sudo launchctl load /Users/<Path to Jenkins User>/Library/LaunchAgents/org.jenkins-ci.plist
The drawback of this approach is launch agents don't start until the user they're associated with logs in. In order to accommodate this I've configured my Jenkins user to login when the server starts up. To do this:
Open System Preferences
Open Groups & Users
Login Options
Set your Jenkins user as the Automatic Login:
This is obviously a security concern, but these machines should only ever be accessible on your local network and in a secure location anyway. Regardless I set the machine to show a screensaver as quickly as possible with a login.
The work-around that I see is that you can create AppleScript, which will run a simulator using terminal. Example:
do shell script "script"
where, script is your terminal command.
After script is created, add build step 'Execute shell script' to jenkins and write script which will run your AppleScript.
Example:
open /Applications/MyScript.app
The issue was in Jenkins and it was solved in the following way:
Stop the jenkins daemon via command:
sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
Start Jenkins as process via command:
sudo nohup java -jar /Applications/Jenkins/jenkins.war --httpPort=8080 --ajp13Port=8010
And it works perfectly!
But there is a pitfall, after launching Jenkins under your user, all jobs disappear and you need to create it once again.

Jenkins accessing Window Server

I have the following problem: I have an ANT-task in Jenkins-CI that (apparently) needs access to OSX' window server (it needs to show a window). After doing some research, it appears that only the currently logged in user and the 'root' user (or SUDO) can access OSX' window server.
The ANT task (Adobe ADL) is one that actually 'runs' a build, so it has to popup a screen.
I'm on a macBook running OSX 10.7.something (Lion), Jenkins 1.487, Ant 1.8.4.
What i have tried so far:
to start with, tried the 'barebone' < exec > task to invoke ADL. Works, but getting error that means that Jenkins running as daemon (with homedir /Users/shared/Jenkins/Home) cannot access OSX' Window Server.
Run Jenkins as myself, by changing USER_NAME, GROUP_NAME, JENKINS_HOME in the jenkins launchd.conf file: https://wiki.jenkins-ci.org/display/JENKINS/Thanks+for+using+OSX+Installer
this gives a lot of errors/trouble, which i tried to solve in communication with the creator of the Jenkins CI but, unfortunately to no avail.
Try to have Ant run an < exec > task (running a shell script) in which i try to sudo with a password using this sneaky way of passing a password to the stdinput: echo < password > | sudo -S < command > which is really bad, but as i'm running Jenkins locally (not reachable from the outside of my LAN) it's np.
Tried to have Ant run an < exec > task, using a 'redirector' with as inputstring my password. also superbad, but yea, i just want it to work. which it did not.
Tried a Jenkins SSH plugin: didn't work. I could, however, SSH to my own localhost using terminal, thing is, i don't know what the Jenkins SSH was trying to do (how can i figure that out anyway?) so i don't know why it wouldn't work.
Tried to have Ant run an SSHEXEC task (which, after some hours, finally worked. Ant for mac is borked, something with optional .jar tasks not being re-named correctly or something) but i'm getting a "com.jcraft.jsch.JSchException: Auth fail" which i googled for, and can't seem to resolve. only applicable solution is to have sshd accept password auths, did that, still got the same error.
I think what i want to accomplish was NOT worth the 2 days that i spent so far on this problem, although i learned a lot. However, i just want this to work and will not accept defeat, yet :)
My question: have you had to solve a similar problem, how did you go about it? are there any other methods i can try to solve this problem? Is there a method mentioned that should JUST _WORK_ and i did something wrong?
[edit] I have decided to go with the Jenkins standalone app, as i think (for me) this is a nicer solution in total, as my laptop is not a build server. Also, the Jenkins app can start at startup so it actually acts as a local server.
Just a quick guess: if you don't want the interactivity of the script, and the script can do without it, you can try to set the headless mode on the java command-line:
-Djava.awt.headless=true
I have decided to go with the Jenkins standalone app, as i think (for me) this is a nicer solution anyway, as my laptop is not a (headless) build server. Also, the Jenkins app can start at startup so it acts as a server too.

Running iOS UIAutomation tests from Jenkins

For a while now I've been trying to work out how to run UIAutomation tests from Jenkins - every time I run the build, it builds fine, then it runs my instruments command (using the same command as detailed here ( Can Instruments be used using the command line?) and jenkins just hangs, well the whole machine does, and when I look at activity monitor I can see an instruments process using 2gb of memory.
When I set up jenkins, I original ran it as from a hidden user - this presented some challenges with jenkins being a deamon and not being able to access the window server. I then decided to change the jenkins account to a normal user, logged in and ran instruments from the command line - this worked fine.. but still had no luck with running it from jenkins.
I have set the jenkins account as a developer - no admin though
Please let me know if there's anything else that I could try, or if anyone has got this running successful your guidance would be much appreciated - Thanks
Jenkins on OS X is started from a launchd script and will run as "daemon" by default. The thing to do is change the user in the launched script.
First, get Jenkins ready to shutdown (in "Manage Jenkins" in the GUI).
Then unload the job from launchd, like so:
$ sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
Then edit the "UserName" property in the launchd plist, using the user which you want to run jenkins. There's also a GroupName property, which you may want/need to adjust accordingly with your user's group.
Finally, reload Jenkins with:
$ sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist
Hope that helps!
So if you run it as a daemon, first thing to check what happens if you run Jenkins in the foreground The simplest way to do it is with java -jar jenkins.war [other options] command (see this document).
Maybe you can use this https://github.com/houlianpi/robot4ios.
Then in jenkins execute shell:
sh setup.sh
sh runTests.sh ./sample/alltests.js "/Users/komejun/Library/Application Support/iPhone Simulator/5.0/Applications/1622F505-8C07-47E0-B0F0-3A125A88B329/Recipes.app/"
and the report will be auto create in ./ynmsk-report/test.xml

iphone reboot programmatically

I have code
system("reboot")
The reboot command works in the terminal, but even if I run the app as root, the operation is still denied. Has anyone found any way that works, or can explain a bit about SBSetting's reboot, which makes me curious?
I have finally found a way to programmatically restart an iOS device without rooting a device!!!!
The command line tool to restart an iOS device is called libimobiledevice:
http://krypted.com/mac-os-x/use-libimobiledevice-to-view-ios-logs/
It is truly amazing. One snag I ran into while installing was trying to install this line:
brew install -v --devel --fresh automake autoconf libtool wget libimobiledevice
However I got around the install problem by running this line:
brew install -v --fresh automake autoconf libtool wget libimobiledevice
After that problem, I followed the rest of the instructions and voila!
Most of the commands can be found on this page:
http://krypted.com/uncategorized/command-line-ios-device-management/
The magic command that restarts the iOS device is:
idevicediagnostics restart
What is truly amazing about this tool is not only restarting an iOS device but also outputting iOS device logs to mac's terminal app using the following command:
idevicesyslog
I figured out a way to do it, although it's a bit convoluted. The problem is that even if you setup your app to run as root, when you make system() calls, you're apparently still limited to user mobile privileges. Since mobile cannot call reboot (successfully), this doesn't work.
The way I got around this problem is to take advantage of a new feature that SBSettings supports. SBSettings has a privileged daemon process that runs. It allows you to plug in your own commands, by simply writing a script (or other executable) and dumping it in the appropriate directory (/var/mobile/Library/SBSettings/Commands). Once you then restart the sbsettingsd process, you can get it to run your script by posting a notification. If you name your script
com.mycompany.reboot
then from within your app, you can execute this code:
#import <notify.h>
notify_post("com.mycompany.reboot");
Then, you make com.mycompany.reboot a simple shell script like this:
#!/bin/sh
reboot
And make sure to chmod 755 on your com.mycompany.reboot script. The full details of this SBSettings command feature can be found here:
http://thebigboss.org/guides/sbsettings-toggle-spec (see Calling External Functions and Scripts ...)
Anyway, it does require your app to depend on SBSettings, but it's a free app, and most users would probably want to have it anyway. For now, it accomplishes the goal of rebooting (or anything else that requires root access) programmatically, via notify_post().
This answer might feel hacky to some but I have not found a better solution on how to restart an iOS device that has not been jailbroken so here goes my answer:
In order to restart a device from the command line I do some prep work:
Connect device to computer
Add iTunes shortcut to your dock
Select spotlight and search for an application called Automator [must have Xcode installed in order to launch Automator!]
When Automator launches, select the Application option
Select the record button to start recording following actions
Select the iTunes shortcut
Select your device from the Device options
Select the Restore Backup... button
Select the Restore button
Select the stop button on the Automator app to stop recording.
From the Automator application, select File from the top bar and Save your newly recorded app to a location of your choosing
At this point you have an app file that will execute the steps mentioned above. I tend to leave iTunes open as it will always have the iOS device hooked up and ready to be accessed. When iTunes is closed and relaunched, the device takes time to fully connect with iTunes and this tends to break the flow of the Automator app.
At this point I can go into a terminal, go to the location of the app file and run the following command [EXAMPLE]:
open automator.app
(replace 'automator.app' with the name of your file)
If you are like me and your are running this command in jenkins, you will need to run the following commands:
open [location]/[your_app_name.app]
sleep 30
For some reason, the automator app needs the sleep time to complete all the recorded actions.
Also, I am sure you can also write an applescript to do all of this but I hate applescript and took the easy way out!
did you try NSTask: Execute a terminal command from a Cocoa app
This is not possible if the app is running in its sandbox. on a jailbroken phone you might be able to execute the reboot shell command.

Resources