Building an iOS app with Jenkins - ios

I want to automate the iOS app building process that currently is totally manual on a desktop computer (Mac). A central build server Hudson/Jenkins, running on a Gnu/Linux machine, is already available inside the organization infrastructure.
Is it possible to build this iOS app with Jenkins, using tools like Jenkins distributed builds (and so configuring a Mac machine as a slave)?
Do you have any example, know any technique or alternative to do this?

Yes its possible. We are doing this and it works fine. You could configure a Xcode-slave within Jenkins by choosing the Xcode-plugin. There are tons of nice tutorials on the web.
Check out this one for starters.

I finally got my Jenkins Job up and running after toiling away for longer than I wanted using the only tutorials that I could find which all happened to be from 2015 or earlier unfortunately. So I posted a real quick checklist of stuff I did to successfully setup the Mac slave on a local Mac mini within my company. Similar to you #lifeisfoo my organization currently has a Jenkins instance running on an outside server.
The link for setting up a Mac slave as per 2018 is seen here.
Setting up jenkins slave on Mac OS
In terms of setting up a Jenkins Job after the node is successfully created and Launch Agent connects properly to your Mac slave from your Jenkins instance see below:
For the most part setting up a New Item a.k.a. New Job from the Manage Jenkins section is self explanatory
Most of the older tutorials are accurate in that you need some plugins Github, Keychains and Provisioning Profiles Management (still not 100% that you need this plugin though but still good to have and set it up) and others I downloaded and installed but never used including I did not use the Xcode plugin in the Build section of the Job setup.
Make up a project name, check Github project and add the url ending in .git/, restrict this project to the Node you created for the Mac slave, in Source Code Management we used Git and I added the url again (ending in .git without the "/" this time, created new credentials with my username and password, */main in the branches to build section, added Github hook trigger url for GITScm polling to my organization's Github account web hooks section
In Build I only used Execute Shell and cd into /Users/jenkins/path/to/file
Currently it is NOT a workspace so the commands are as follows in Execute Shell
xcrun xcodebuild -project ProjectName.xcodeproj \
-configuration Release \
-destination 'platform=iOS Simulator,name=iPhone 6s' \
-allowProvisioningUpdates \
CODE_SIGN_STYLE='Automatic'
PROVISIONING_PROFILE_SPECIFIER=${PROVISIONING_PROFILE}
CODE_SIGN_IDENTITY=${CODE_SIGNING_IDENTITY}
As of February 2018, I have changed it to workspace because of the need to include some cocoa pod SDKs hence I now use the below combination of "Execute Shell"s.
The below script is to run a pod install every time (because I added Pods/ to the gitignore file only pushing Podfile and Podfile.lock to the repository which Jenkins pulls from)
cd /Users/jenkins/Desktop/projectFileWhere.xcworkspaceExists
/usr/local/bin/pod install
The below is to run the project build in another "Execute Shell"
xcrun xcodebuild -workspace ProjectName.xcworkspace \
-scheme NameOfScheme \
-configuration Release \
-destination 'platform=iOS Simulator,name=iPhone 6s' \
-allowProvisioningUpdates \
CODE_SIGN_STYLE='Automatic'
PROVISIONING_PROFILE_SPECIFIER=${PROVISIONING_PROFILE}
CODE_SIGN_IDENTITY=${CODE_SIGNING_IDENTITY}
Note:
- I wasn't sure whether it was absolutely necessary but I made sure to clone the latest GitHub repo into my Mac slave machine into the same project directory where the .xcodeproj existed before.
- I also foolishly didn't realize at first that .xcworkspace was NOT getting pushed to my GitHub repo because build/*.xcworkspace was still in my gitignore file. Removed it, re-pushed to repo and cloned to Mac slave and it was all gravy baby
I saw many variations of CODE_SIGN_IDENTITY and some that specifically told me to add parameters like DEVELOPMENT_TEAM= and DISTRIBUTION_TEAM= but those weren't necessary.
Frankly speaking I don't know if -allowProvisioningUpdates nor CODE_SIGN_STYLE='Automatic' is necessary but its working for me.
I ended up going with the Execute Shell Build step and not the Xcode Plugin for Build parameters because I was able to more easily manipulate build parameters and test it against the errors I was getting in the console output of each build in my Jenkins instance. In the end there was also more and better documentation and help in trying to understand Xcodebuild with command line and that is essentially what Execute shell is doing hence I liked it better.
I wanted to write this post to point out what I finally did to make the job build and my issues in getting it to build were very easy to fix until this last one which was in that code signing couldn't find my provisioning profile for the certificate/team that I was using in Xcode's project file target and project:
I didn't use Fastlane or any other program. Just SSH connection into Mac slave.
Setup Xcode command line tools: xcode-select active developer directory error
1) In this Wiki I did what is stated in the paragraph directly under the title "Xcode project setup".
https://github.com/cyupa/JenkinsCI-iOS
2) You need to have both private and public key for a dev and distribution certificate on the Mac Slave in order to build through Jenkins to the Mac Slave. Need Provisioning Profiles on the Mac Slave for each of these accounts with the proper Bundle ID as well.
https://blog.noser.com/streamlining-ios-development-with-jenkins-and-wireless-app-distribution-2/
3) Move the keychains and certificates for both dev and distribution to Login or whatever other unique keychain you created but for each private key, right click (two finger tap) the private key and Get Info -> Access Control -> allow /usr/bin/codesign or all applications to access this item
4) In Build settings of the Xcode project on the Mac slave (make sure you've downloaded from your repo to the Mac slave and opened it once on the Mac Slave's Xcode app), change build settings to be automatic and/or just change it in General of the Target App and testing if you want.
5) The last piece of the puzzle to solve the problem that took me 2 days was to simply add my keychains to the security list so that Xcode could use the provisioning profiles for the certificates that it needed.
Not sure if what I suggested above regarding Access Control is necessary if you add the keychains to the security list but I kept it and its working for me. Maybe I'll experiment later and see what is actually needed and not needed but for now, this was the key. You may get "codesign failed with exit code 1" which is all the same thing. The terminal command to unlock is:
security list-keychains -s ~/Library/Keychains/{login, "any other keychains you want added to security list"}.keychain
Sooooo if you are seeing any build errors in Jenkins like.......
No profiles for 'com.organization.Target' were found: Xcode couldn't find any iOS App Development provisioning profiles matching 'com.organization.Target'
Code Signing Error: Code signing is required for product type 'Application' in SDK 'iOS 11.2'
.......then you know most likely its a keychain access thing and nothing else.
In hindsight I realize now that I saw this same advice in some other Stack posts and one or two other blog posts as linked below, but that wasn't my issue at the time so I totally forgot about it and now hate myself for not reading slower over these posts. Oh well. At least I'm getting a green circle now.
"User interaction is not allowed" trying to sign an OSX app using codesign
https://blog.noser.com/streamlining-ios-development-with-jenkins-and-wireless-app-distribution-2/

Related

command fails on jenkins, but works on terminal

I'm working on using fastlane screengrab/snapshot to take screenshots of my android and ios app. When I run them locally on terminal, they work perfectly, but when I run them from jenkins, they fail. I'm using macOS.
Android:
/Users/shared/Library/Android/sdk/tools/emulator -avd Pixel_API_22 &
fastlane screengrab
(These 2 are in a .sh)
The first line failed: PANIC: Cannot find AVD system path. Please
define ANDROID_SDK_ROOT
iOS:
fastlane snapshot
it failed while trying to build a test because of an provisioning profile error:
xcodebuild -showBuildSettings -scheme UITests -project ./abc.xcodeproj
(this is a command that fastlane snapshot execute automatically)
Again, they both run smoothly on terminal (I ran them in the same workspace as junkins)
Double-check the environment settings after executing your job in Jenkins: you might see differences with the same environment settings as seen with your user account in command-line (where it is working)
The username might be different (if your Jenkins server/agent runs with another account).
The OP Son Nguyen confirms the PATH issue:
the developer who set up jenkins put a wrong path to android sdk, so I was able to run the android part by fixing the path.
And the OP adds:
fastlane was installed in /usr/local/bin while jenkins was in /User/myUser: So, somehow they didn't work well together.
I reinstalled fastlane in /User/myUser and it worked.
This got it working for me.
I had to include this at the top of my script :
#!/bin/zsh
source ~/.zshrc
and my .zshrc had this:
export PATH="$PATH:"/usr/local/bin/
export SSL_CERT_FILE=/etc/ssl/cert.pem # for openssl error
export ANDROID_HOME=/Users/jenkins/Library/Android/sdk

Jenkins iOS builds on Mac Sierra failing during xcodebuild 8.2 code signing (SecKey API returned -25308)

I have Jenkins CI set up on Mac Sierra to build iOS apps using Xcode 8.2 with automatic signing. All works well when building using Xcode as the developer. However, Jenkins using xcodebuild is failing with the following:
SecKey API returned: -25308, (null)/Users/Shared/Jenkins/Home/workspace/App/build/Build/Intermediates/ArchiveIntermediates/App/InstallationBuildProductsLocation/Applications/App.app/Frameworks/GTMSessionFetcher.framework: unknown error -1=ffffffffffffffff
I have followed the advice in security / codesign in Sierra: Keychain ignores access control settings and UI-prompts for permission, to no avail.
I have tried putting both private keys and certs into the System keychain, to no avail.
If I log in as the Jenkins user and run the codesign command manually, I "Always Allow" access to the keychain, and it works, repeatedly. However, running as invoked by the Jenkins CI does not. (The Jenkins master is the Mac, and I'm using this same Mac to build.)
The error is mentioning the CocoaPod GTMSessionFetcher. Is this something to do with CocoaPods?
Any ideas would be appreciated.
I was experiencing exactly the same issue and I am quite sure that it has nothing to do with CocoaPods, its a codesigning issue. Some of the things I did:
Check that I do not have duplicate Keychain Entries. This post was useful for that. It turned out that I had one entry duplicated.
Check that private keys are allowed to all applications, as explained here
Try this (be aware that since macOS Sierra login.keychain has changed to login.keychain-db), which is the second answer in the advice you mention, but didn't work.
Move both private keys and certs to System keychain (leaving only the certificates on login keychain). This last step was the one that made things work.
In case this is not helpful you can try to unlock the login keychain manually in your Jenkins job (that did the trick for me before I moved keys an certs to System keychain):
node("macOS-sierra") {
.........
stage("Build"){
sh 'security unlock-keychain -p KEYCHAIN_PASS "/Users/YOUR-CI-USER/Library/Keychains/login.keychain-db" && fastlane beta'
}
You can check your keychains with this:
$ security list-keychains

Jenkins - command line build iOS project

I have an iOS project cloned from repo into my jenkins account. Xcode is not yet installed. I know command line scripts to build an iOS project including targets/configurations/profiles etc. Certificate and provisioning profile is installed in jenkins account. I am wondering if there is a way to build and create ipa without installing Xcode in jankins account. Does apple provide any developer tools for building and creating IPA through command line only?
Advance thanks
Every building option for iOS apps requires Xcode, but apple does provide tools for building via CLI. A ton has changed in the most recent iOS OS upgrade and there are incredible tools out there for CI/CD app delivery. What you end up using should really depend on what you want to maintain over time and how advanced your system needs to be.
To get Builds working in Jenkins
Step 1 : Install Xcode on the Jenkins node that will be doing the builds. You wont be using the Xcode UI but you will need it installed, there is currently no way to build IPAs without Xcode.
Step 2: Choose your build tool
You could write your own build scipts and manage provisioning profiles on the machine. xcodebuild is the CLI tool you are looking for. If you end up going down this route make sure to use xcpretty or you will loose your mind with giant build logs.
Fastlane is an amazing toolset for building mobile apps, it might change your life. Check out these examples and how to get started.
Apple has an xcode build server that Jenkins could possibly talk to.
The first two in this list do a good job of managing provisioning profiles out of the box, and that can save you major headaches down the road if you need to scale

Is it possible to set up Crashlytics on iOS without having to install the app on each developer's workstation?

Crashlytics looks like the best crash reporting solution on iOS, but app is noisy and it dirties commits.
Since our Ad-Hoc and App-Store builds come from a CI server we don't need each developer's workstation to upload .dSYM files to the server.
Is it possible to configure it so that only the CI server has to deal with Crashlytics?
We do this in our Run Script phase:
if [ ${CONFIGURATION} == "Release" ]
then
./Fabric.framework/run <magic> <number>
fi
That way, devs use the Debug build normally, but if they want a production-ready build then they can do one.
If you really want it to be only for your CI build, then you can pass additional variables on the xcodebuild command line, call it something like USE_CRASHLYTICS and otherwise it's the same.
Nope. You'll have to have each developer install it. It's the same principle with anything with Cocoapods. Just because a project has pods on it doesn't mean that when another developer pulls it from Git they too have access to the pods.

Can I sign the iOS app with an AdHoc profile wihtout using XCode?

Preferably using Linux, Windows is also OK.
Something like openssh and zip?
If you can remotely shell into the Mac (ssh), then you should be able to build and sign your project from the command line. It may require some setup beforehand, but xcodebuild and xcrun should get you where you need to go. (This is the same kind of thing folks do to get automated continuous integration builds set up.)
Doesn't get you out of using Xcode or a Mac, but maybe gets you out of having to be physically sitting in front of that Mac to get work done.
Further reading:
Xcode “Build and Archive” from command line
xcodebuild man page
xcrun man page
I would use TeamViewer ( payed version) or other remote desktop software to connect tom office mac mini. Otherwise you will break up the signing license too, beside it is hard to configure the keychain.
It will be very hard to figure out after you have signed a build why it doesn't install at client's PC, because no error messages there.

Resources