Jenkins+TestFlight is used to have Continuous Integration (CI) for iOS apps. Here is my experience with Jenkins:

I. Geting Jenkins running on my computer:

http://www.uvd.co.uk/blog/labs/configuring-jenkins-continuous-integration-server-to-work-with-git/

  • ssh-keygen  -t  rsa             (-t specifies type)
    • The command used to generate key for SSH connection: RSA (version 1), RSA or DSA (version 2)
    • stores private key in $HOME/.ssh/id_rsa and public key in $HOME/.ssh/id_rsa.pub in the user’s home directory
    • then copy contents of id_rsa.pub to the $HOME/.ssh/authorized_keys file in home directory on the remote machine
  • ssh is a protocol that replaces  rloginTELNET and rsh protocols (more secure). ssh has 2 uses:
    • 1 is using a password to login to a connection, protected by AUTOMATICALLY generated public-private key
    • 2 is distributing MANUALLY generated public key to all the computers needed to allow user with matching private key
  • SSH config for user: (inside ~/.ssh of that user do: touch config)- create config file to point to key
    • HostName github.com
    • User git
    • IdentityFile ~/.ssh/id_rsa
    • IdentitiesOnly  yes

II. Connecting to Git project:

We can install this plugin https://wiki.jenkins-ci.org/display/JENKINS/GitHub+Plugin to create webhooks (every GitHub repository has the option to communicate with a web server whenever the repository is pushed to.) Follow this URL to create webhook.

Remember to enter username/password in Global config/Github Web hooks section to allow Jenkins to trigger build automatically.

Stack resource : 

III. iOS Plugins:

Jenkins has over 600 plugins. Here we will only install some plugins needed for iOS development.

The first plugin to allow Jenkins to call Xcode command lines, so to build, package, sign and even run OCUnit tests!

    • Variables can be used:
      BUILD_NUMBER
      The current build number, such as “153”
      BUILD_ID
      The current build id, such as “2005-08-22_23-59-59” (YYYY-MM-DD_hh-mm-ss)
      BUILD_DISPLAY_NAME
      The display name of the current build, which is something like “#153” by default.
      JOB_NAME
      Name of the project of this build, such as “foo” or “foo/bar”. (To strip off folder paths from a Bourne shell script, try: ${JOB_NAME##*/})
      BUILD_TAG
      String of “jenkins-${JOB_NAME}${BUILD_NUMBER}“. Convenient to put into a resource file, a jar file, etc for easier identification.
      EXECUTOR_NUMBER
      The unique number that identifies the current executor (among executors of the same machine) that’s carrying out this build. This is the number you see in the “build executor status”, except that the number starts from 0, not 1.
      NODE_NAME
      Name of the slave if the build is on a slave, or “master” if run on master
      NODE_LABELS
      Whitespace-separated list of labels that the node is assigned.
      WORKSPACE
      The absolute path of the directory assigned to the build as a workspace.
      JENKINS_HOME
      The absolute path of the directory assigned on the master node for Jenkins to store data.
      JENKINS_URL
      Full URL of Jenkins, like http://server:port/jenkins/ (note: only available if Jenkins URL set in system configuration)
      BUILD_URL
      Full URL of this build, like http://server:port/jenkins/job/foo/15/ (Jenkins URL must be set)
      JOB_URL
      Full URL of this job, like http://server:port/jenkins/job/foo/ (Jenkins URL must be set)
      SVN_REVISION
      Subversion revision number that’s currently checked out to the workspace, such as “12345”
      SVN_URL
      Subversion URL that’s currently checked out to the workspace.

This plugin is very important. I used to upload keychain files and provisioning-profiles files for Jenkins to build.

    • Setting up keychain: see Wiki for details!
    • Use this value for provisioning directory path:

/User/<USERNAME>/Library/MobileDevice/Provisioning Profiles


 

Troubleshooting

IV. Other problems:

  • “Code Sign error: Provisioning profile ‘xxxxx-xxxx-xxxx-xxxxx’ can’t be found”  (Mobile provisioning problem): if your Jenkins can’t build because of lacking provisioning profiles, even after you have uploaded them – just login as jenkins user (on your Mac) and import the provisioning profiles. Another way is to copy the provisioning profiles to the jenkins directory: /Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profile
  • “Code Sign error: There are no valid certificate/private key pairs in the default keychain” (Keychain access) The Jenkins user cannot access your iPhone developer certificate. One way to solve it is to open Keychain, copy the certificate from login to System (iPhone Developer and iPhone Distribution).
  • “Code Sign error: No matching provisioning profiles found: No provisioning profiles with a valid signing identity (i.e. certificate and private key pair) matching both the team ID ‚ and the bundle identifier‚ were found”.The issue is the Team ID (which is stored in the .pbxproj file) – to change this, we need to change General – Identity – Team (same section, just below Bundle Identifier/ Version / Build)  to the correct team in the provisioning profile. Leaving a Team as None is also an option.
  • Code Sign error: No codesigning identities found: No codesigning identities (i.e. certificate and private key pairs) that match the provisioning profile specified in your build settings (‘…v28’) were found.This is a case of duplicate iPhoneDeveloper certificate – while the provisioning profile appears to belong to FelixHa, but actually there are 2 FelixHa certificates in the database.
  • Code Sign error: No matching provisioning profiles found: No provisioning profiles matching the bundle identifier ‘…’ were found. 

    Just need to go to Manage Jenkins – Keychain & Prov.Profiles Mngmt – upload the above provisioning profiles – and remove the old ones (Save after removing). Then go in Job Config – Build Environment & choose the correct prov.profile:Screen Shot 2014-10-16 at 4.53.14 pm

  • When Jenkins could not build the Scheme with a linking error (ld error), the first thing we should try is to use Xcode to build it first.
  • When a library is not found for example -lPods-AFNetworking etc., we should check the following issues:
    1. Check if we are building from the correct workspace file,
    2. Check if we are building a Release or Debug one (can also test them on Xcode first)
    3. Library Search Path – if a pod install is successful, it will bind the pods to the workspace, so checking
    4. Check the Build directories to see if the Pods are being built in there – the Build directories are often in the DerivedData folder. We can clear the DerivedData folder and then build to observe the result of the operation.
    5. Run the Xcodebuild command line on Terminal, or copy other commands from Jenkins to run on Terminal to test. Usually the commands need to be run from correct folder, running them in the wrong folder will Fail.
    6. Recreate the Workspace file – by deleting it and File > New > Workspace. Workspace is the container used to manage many related projects. It specifically manage the implicit and explicit dependencies among the included projects and targets. So, when Xcode builds 1 app, it has to build any product the app depends on, like pods/library…