Teach you how to continuously integrate iOS projects using Jenkins

Teach you how to continuously integrate iOS projects using Jenkins


As we all know, now App competition has come to the user experience is king, the quality of the white hot stage. Users are very picky. If a company’s marketing team finally hit heavily promoted a APP, not easy to have some users, due to a line of bug led to a number of users have flash back bug, in the use of light, is likely to hit the early promotion of money have been wasted, not heavy, reputation well, the future can not afford to increase the user. Calm down to analyze the reasons for the problem, no matter the quality is not on the line. Apart from subjective factors, most of the objective factors, I think we can guard against. According to a set of development norms proposed by the great God, CI + FDD can help us to solve the objective factors to a great extent. This article is followed by a discussion of Continuous Integration continuous integration (CI)


  • 1. why do we need continuous integration?
  • 2. continuous integration tool – Jenkins
  • 3.iOS automation packaging commands — xcodebuild + xcrun and Fastlane – Gym commands
  • 4. packaging complete automated upload fir / dandelion third party platform
  • 5. complete continuous integration process
  • 6.Jenkins + Docker

Why do we need continuous integration?

When it comes to why we need problems, we need to start with what. So what is continuous integration?.

Continuous integration is a software development practice: many teams frequently integrate their work; each member usually performs daily integration, and then there is a variety of integration every day. Each integration will detect errors automatically as quickly as possible, including tests. Many teams have found that this approach can significantly reduce integration problems and make team development more efficient.

CI is a development practice. The practice should contain 3 basic modules, a process that can be built automatically, and automatically compiled code that can be automatically distributed, deployed and tested. A code repository, SVN, or Git. The last one is a continuously integrated server. Through continuous integration, it allows us to obtain product feedback and respond to feedback through high-frequency means such as automation.

So what benefits can continuous integration bring us? I recommend an article in which the Continuous integration (CI) and test-driven development (TDD) is divided into 12 steps. However, the benefits are multiplied, with 24 advantages.

Teach you how to continuously integrate iOS projects using Jenkins

Let me talk about some of the advantages of using CI later.

1. reduce development cycles, fast iteration versions

Each version starts with a good estimate of the development cycle, but it’s always postponed for a variety of things. This includes some objective factors. As the product line increases, the iterations become faster and faster, and the pressure on testing increases. If the tests are tested after the development has been fully developed, it will take a long time. At this time due to late integration will seriously slow down the rhythm of the project. If you can continue to integrate as soon as possible, as soon as you enter the iteration loop of the 12 step above, you can expose problems as soon as possible, early settlement, as far as possible within the specified time to complete the task.

2. automation assembly line operation brings high efficiency

In fact, packaging for developers is a very time-consuming, and there is no technical content of the work. If the developer is more than one, the odds of conflicting code changes with each other, and with no line management mechanism, the code quality of the code warehouse is difficult to guarantee. Teams will take some time to resolve conflicts and resolve conflicts before they need to be manually packaged. If the certificate is wrong this time, it will be delayed for a long time. These times can actually be saved by continuous integration. Two days a day doesn’t seem much, but it can save a lot of time by year!

3. can be deployed at any time

With continuous integration, we can pack in days, and the greatest advantage of this high frequency integration is the ability to deploy on-line at any time. This will not lead to the upcoming on-line, there are loopholes everywhere, bug everywhere, confused, can not be deployed after the completion of the serious impact on the line time.

4. greatly avoid low-level errors

We can make mistakes, but we should not make mistakes. Low level errors here include compile errors, installation issues, interface issues, performance issues.
continuous integration of days, you can quickly find the compiler problem, automatically packaged, can not be passed directly. After the package is finished, the test scan code cannot be installed, and this problem will be exposed immediately. Interface issues and performance issues are detected by automated test scripts. These low-level problems are exposed by continuous integration, which reminds us to avoid low-level mistakes.

Two. Continuous integration tool – Jenkins

Jenkins is an open source project that provides an easy to use, continuous integration system that frees developers from complex integration and focuses on more important business logic implementations. At the same time, Jenkins can monitor the errors in the integration, provide detailed log files and reminders, and also graphically display the trend and stability of the project construction.

According to the official definition, Jenkins has the following uses:

  1. Build project
  2. Run test case detection bug
  3. Static code detection
  4. deploy

On the 4 point, the actual use is quite convenient:
1 construction project automation package can save developers a lot of time, it is important for Jenkins, we maintain a high quality of the available code, and ensure a clean environment. We often fail to package because of a local configuration error. Now, Jenkins is a fair judge, and it can’t compile IPA correctly, that is, there are compile errors or configuration problems. Developers don’t have to argue that the local can run, and whoever pulls the code will not be able to run. Work together to maintain the normal compilation of Jenkins, because the Jenkins compiler environment is much simpler than ours, and it is the most clean and pollution-free compilation environment. Developers only focus on coding. This is for developers to bring convenience.

2. this can be used for automated testing. Generate a large number of test cases locally. Use the server to run these use cases every day. Run every interface every day. It doesn’t seem necessary, but in fact the system that works today is likely to have problems tomorrow because of changes in today’s code. With Jenkins, you can do regression testing in days. As soon as the code changes, Jenkins runs all the regression test cases. In the case of tight project schedule, many cases do not attach great importance to the regression test, after all, it is possible to test again is futile, “no effort.””. However, regression testing is not timely, it leads to a final version of the system is not available, then back to find the reasons is time-consuming, check the submitted records, see hundreds of records submitted, the investigation is also a headache. A daily regression test can immediately detect problems. Testers can concentrate on unit tests every day, and do manual regression tests once a week. This is a convenience for testers.

3., this is static code analysis that can detect a lot of code problems, such as potential memory leaks. Because of the purity of the Jenkins environment, we can still find some problems that can not be found in our local complex environment to further improve the quality of the code. This is a convenience for quality inspection.

4. deploy at any time. After the package is complete, Jenkins can set up the following operations, which are often the systems that submit app to run test cases, or deploy them to an internal test platform to generate two-dimensional code. Low-level issues such as not being installed in the deployment were immediately exposed. Testers also only need to sweep the two-dimensional code can be installed, very convenient. That would be a great convenience for testing.

Teach you how to continuously integrate iOS projects using Jenkins

The following example takes the 2016-07-24 version of Weekly Release 2.15 at 22:35.

Let’s start installing Jenkins. Download the latest PKG installation kit from the official website https://jenkins.io/.

Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins

You can also download jenkins.war, and then run Java -jar jenkins.war to install.

When the installation is complete, the Safari may automatically open. If you do not open it automatically, open the browser and enter http://localhost:8080

Teach you how to continuously integrate iOS projects using Jenkins

There may be a mistake at this time. If there’s a problem. The reason for this problem is that the Java environment has problems, and the new Java environment is available.

This time, if you restart the computer, you will find Jenkins added a new user, the name is called Jenkins, but this time you do not know the password. You might try the password, and it must be wrong, because the initial password is complex. At this point, the correct way is to open the http://localhost:8080 will appear in the following picture to reset the initial password interface.

Teach you how to continuously integrate iOS projects using Jenkins

According to the prompt, find /Users/Shared/Jenkins/Home/ in this directory, although this directory is shared directory, but there are permissions, non Jenkins user /secrets/ directory is not read and write permissions.

Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins

open the initialAdminPassword file, copy the password, you can fill in the page to reset the password. Following chart

Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins

All the way to install, enter the user name, password, mail these, even if the installation is complete.

Or continue to login localhost:8080, select system management – management plug-in, we have to install some secondary plug-ins.

Install the GitLab plugin
because we are using GitLab to manage source code, Jenkins itself does not own the GitLab plug-ins, so we need to select a -&gt system management; management plug-in, in the “optional plug-in” select “GitLab Plugin” and “Gitlab Hook Plugin” of the two, and then install.

Installing the Xcode plug-in
, like the steps for installing the GitLab plug-in, we select system management -&gt in turn, manage plug-ins, and select “Xcode integration” installation in the optional plug-in.

With this installed, we can configure a build project.

Teach you how to continuously integrate iOS projects using Jenkins
Teach you how to continuously integrate iOS projects using Jenkins

Click the new good project to come in and configure the General parameter.

Teach you how to continuously integrate iOS projects using Jenkins

Here you can set the number of days and days of the package.

Next, set source management.

Since I’m using GitLab now, I’ll configure SSH Key first and add SSH in the certificate management of Jenkins. In the Jenkins management page, select the “Credentials”, then select “Global credentials (unrestricted)”, click “Add Credentials”, as shown below, we fill in their SSH information, and then click “Save”, so as to add SSH to Jenkins in the global scope.

Teach you how to continuously integrate iOS projects using Jenkins

If the normal configuration is correct, the red warning will not appear in the picture below. If there is a hint from the figure below, the Jenkins is not connected to GitLab or SVN, so check that the SSH Key is properly configured.

Teach you how to continuously integrate iOS projects using Jenkins

Build the trigger settings here to set up automated tests. There is a lot of content involved here, and I haven’t studied it for the time being. I don’t want to set it up for the time being. There are automated testing requirements, you can study and study the settings here.

However, there are two configurations or need to be configured?

Poll SCM (poll source code management) polling source management,
need to set the source path, in order to play the effect of polling. Generally set to similar results: 0/5 polling every 5 minutes,
Build periodically (timed build),
is generally set to the similar: 0020 * 20 every day, the implementation of timed build. Of course, both settings are the same, can be common.

The format is like this

Minutes (0-59) hours (0-23), dates (1-31), months (1-12) weeks, weeks (0-7,0 and 7 are all Sunday), more detailed settings see here

Teach you how to continuously integrate iOS projects using Jenkins

Building environment settings,
, iOS packaging requires signing documents and certificates, so this section we tick “Keychains, and, Signing, Identities,” and “Mobile Provisioning Profiles” Code”.
here we need to use Jenkins plug-in, in the system management page, select “Keychains and Provisioning Profiles Management””.

Teach you how to continuously integrate iOS projects using Jenkins

Go to the Keychains and Provisioning Profiles Management page and click the Browse button to upload your own keychain and certificates, respectively. When the upload is successful, we then specify the name of the signature file for keychain. Click on “Add Code Signing Identity”, and finally add success, as shown in the following figure:

Teach you how to continuously integrate iOS projects using Jenkins

note: the first time I import the certificate and Provisioning Profiles files, we met a little “pit”, I thought it was a need certificate, but here you need to Keychain, and not cer certificate file. This Keychain is in the /Users/ administrator username /Library/keychains/login.keychain, when the Keychain is set, Jenkins will keep a copy of the Keychain to /Users/Shared/Jenkins/Library/keychains (here, Library is a hidden file). The Provisioning Profiles file is also copied directly to the /Users/Shared/Jenkins/Library/MobileDevice file directory.

In this way, the Adhoc certificates and signature files are configured in Jenkins, and then we only need to specify the relevant files in the item settings.
go back to our new item, find the build environment, and select your relevant certificates and signature files from the following figure.

Teach you how to continuously integrate iOS projects using Jenkins

Next, the settings for the build are

Teach you how to continuously integrate iOS projects using Jenkins

We choose to execute a package script here. The script will be explained in detail in the next chapter.

Post construction operation

Teach you how to continuously integrate iOS projects using Jenkins

Here we select the Execute a set of scripts, and here is also a script that uploads the automatically packaged IPA files. The script is explained in detail in the fourth chapter.

At this point, our Jenkins setup is complete. Click build, and you will start building the project.

Once constructed, each color represents the following meanings:

Teach you how to continuously integrate iOS projects using Jenkins

The barometer of the weather represents the quality of the project, which is a feature of Jenkins.

Teach you how to continuously integrate iOS projects using Jenkins

If the build fails, you can go to the Console Output to view the log log.

Teach you how to continuously integrate iOS projects using Jenkins

Three. IOS automated packaging commands – xcodebuild + xcrun and Fastlane – Gym commands

In the daily development, packaging is an indispensable link finally on the line, if you need to package the project as a IPA file, the usual practice is in Xcode, click “Product -&gt”; Archive, when the Archive Project, and then choose from the pop-up “Organizer”, according to the ad hoc enterprise type is derived. IPA package. Although Xcode has been perfect for packaging, we still need to manually click 5 or 6. Coupled with the fact that we now need to continue integration, it’s necessary to automate the implementation with packaged instructions.

1. xcodebuild + xcrun command

Xcode provides our developers with a set of build package commands, namely, xcodebuild,
, and xcrun commands. Xcodebuild packages our specified project into a.App file, and xcrun converts the specified.App file to the corresponding.Ipa file.

Specific documents are as follows, xcodebuild official documents, xcrun official documents

NAME xcodebuild - build, Xcode, projects, and, workspaces, SYNOPSIS,, xcodebuild,, [-project, name.xcodeproj], [[-target, targetname]... -alltargets] [-configuration configurationname] [-sdk [sdkfullpath | | sdkname]] [action... [[buildsetting=value]... [[-userdefault=value]... 2., xcodebuild, [-project, name.xcodeproj], -scheme, schemename, [[-destination, destinationspecifier]... Value] [-configuration configurationname] [-sdk [sdkfullpath [-destination-timeout sdkname]] [action |... [[buildsetting=value]... [[-userdefault=value]... 3., xcodebuild, -workspace, name.xcworkspace, -scheme, schemename, [[-destination, destinationspecifier]... Value] [-configuration configurationname] [-sdk [sdkfullpath [-destination-timeout sdkname]] [action |... [[buildsetting=value]... [[-userdefault=value]... 4 xcodebuild -version [-sdk [sdkfullpath |] sdkname]] [infoitem] 5 xcodebuild -showsdks 6 xcodebuild -showBuildSettings [-project name.xcodeproj [-workspace name.xcworkspace -scheme | schemename]] 7 xcodebuild -list [-project name.xcodeproj -workspace name.xcworkspace] xcodebuild -exportArchive | 8 -archivePath xcarchivepath -exportPath destinationpath -exportOptionsPlist path xcodebuild -exportLocalizations -project name.xcodeproj -localizationPath 9 path [[-exportLanguage language]... [10., xcodebuild, -importLocalizations, -project, name.xcodeproj, -localizationPath, path

Of the 10 commands above, the first is the first 3.

Next, explain the parameters:
, -project, -workspace: these two correspond to the name of the project. If there are more than one project and no more specified here, the default is the first project.
-target: packaging the corresponding targets, if not specified, this defaults to the first.
-configuration: if you do not modify this configuration, the default is the two versions of Debug and Release, and the default version of Release is not specified.
-buildsetting=value: use this command to modify the configuration of the project.
-scheme: Specifies the packaged scheme.

These are the most basic commands.

The above 10 orders of the first and the second the parameters of which -target
and -configuration -list
parameters can be obtained using xcodebuild, -sdk parameters can be obtained by the xcodebuild -showsdks
, [buildsetting=value…] to have coverage in engineering configuration. Coverage parameter reference official document Xcode, Build, Setting, Reference.

Build Build the target in the build root (SYMROOT). This is the default action, and is used if no action is given. analyze Build and analyze a target or scheme from the build root (SYMROOT) This specifying a scheme.. Requires archive Archive a scheme from the build root (SYMROOT) This requires specifying a scheme.. Test Test a scheme from the build root (SYMROOT) This specifying a scheme. Requires and optionally a destination. installsrc Copy the source of the project to the source root (SRCROOT) install the target and. Build install it into the target installation directory in the distribution s root (DSTROOT) clean Remove build products and intermediate. Files from the build root (SYMROOT).

The above third commands are used exclusively for projects with Cocopods, because at this point the project project file is no longer xcodeproj, but instead it is xcworkspace.

Let’s talk about the xcrun command.

Usage: PackageApplication [-s signature] application [-o output_directory] [-verbose] [-plugin plugin] -man -help Options: [-s signature] || ||: certificate name to resign application before packaging [-o output_directory] output filename: specify [-plugin plugin] an optional plugin -help: specify brief help message -man: full documentation -v[erbose] details during operation: provide

The parameter is not many, the use method is also very simple, xcrun, -sdk, IPhoneOS, -v, PackageApplication + some of these parameters.

After the parameters are understood, let’s see how it works. Here is an automated package script written using the xcodebuild + xcrun command

# project name APP_NAME= "YourProjectName" CODE_SIGN_DISTRIBUTION= "iPhone Distribution: # certificate Shanghai Co. Ltd. * * * * * * *," # info.plist path project_infoplist_path= "./${APP_NAME}/Info.plist" # Edition (/usr/libexec/ bundleShortVersion=$PlistBuddy -c "print CFBundleShortVersionString" and "${project_infoplist_path}") # build value bundleVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleVersion" "${project_infoplist_path}" "$(date) DATE= +%Y%m%d)" IPANAME= "a. APP_NAME}_V${bundleShortVersion}_${DATE}.ipa" to "IPA_PATH= # IPA file upload $HOME/${IPANAME}" echo ${IPA_PATH} echo "${IPA_PATH}" > > text.txt / / 2 lines below is the usage of echo "no Cocopods =================clean=================" xcodebuild -target "${APP_NAME}" -configur Ation'Release'clean echo "+++++++++++++++++build+++++++++++++++++" xcodebuild -target "${APP_NAME}" -sdk IPhoneOS -configuration'Release' CODE_SIGN_IDENTITY= "${CODE_SIGN_DISTRIBUTION}" SYMROOT='$(PWD) '/ / 2 lines below is integrated with the use of Cocopods echo "=================clean=================" xcodebuild -workspace "${APP_NAME}.xcworkspace" -scheme "${APP_NAME}" -configuration'Release' clean echo "+++++++++++++++++build+++++++++++++++++" xcodebuild "-workspace ${APP_NAME}.xcworkspace" -scheme "${APP_NAME}" -sdk IPhoneOS -configuration'Release'CODE_SIGN_IDENTITY= "${CODE_SIGN_DISTRIBUTION}" SYMROOT='$(PWD) xcrun -sdk IPhoneOS PackageApplication' "./Release-iphoneos/${APP_NAME}.app -o" / "${IPANAME}"
2. gym command

When it comes to gym, you have to say “Fastlane” first.
Fastlane is a set of automated packaging tools, written in Ruby, for automated packaging and distribution of iOS and Android. Gym is one of the package commands.

Here’s Fastlane’s official website. Look at Fastlane’s GitHub

To use gym, you need to install Fastlane first.

Sudo, gem, install, Fastlane, --verbose

Fastlane contains all the commands that we need to perform on the line after our daily coding.

Deliver: upload screenshots, binary data and applications to AppStore snapshot: automatic interception of your program in each picture on the device frameit: application screenshots adding PEM framework: equipment can be automated to generate and update the application description file: sigh push notification generation Download Development shop configuration file produce: create a new the iOS app Cert in iTunes Connect using the command line: iOS automatically creates a pilot certificate: the best established in the terminal management test and file boarding: the easy way to invite beta to test Gym: the establishment of the released version, the new package match: using git synchronization you among the members of the developer certificate and file configuration scan: test execution in the case of iOS and Mac app

The entire release process can be described in Fastlane as follows

Lane: Appstore, do, increment_build_number, cocoapods, xctool, snapshot, sigh, deliver, frameit, SH,./customScript.sh, end, slack,...

Ps: here, you might have heard a command called xctool
xctool. It’s an enhanced implementation of the official xcodebuild command, and the output is much more intuitive and readable than xcodebuild. You can install it through brew.

Brew install xctool

Using gym automation packaging, the script reads as follows

# chronograph SECONDS=0 # script placed project_path=$in the path and projects under the same # (PWD) from the current time string is added to the end of the file now=$(date +%Y_%m_%d_%H_%M_%S) # scheme specifies the project name scheme= "DemoScheme" configuration= "to specify the configuration # packaged Adhoc" # packaged using the specified output at present, support app-store, package, ad-hoc, enterprise, development, and developer-id, xcodebuild method export_method='ad-hoc'workspace_path= # parameters specified project address "$project_path/Demo.xcworkspace" output_path= "/Users/your_username/Documents/ # specifies the output path specified" # output file "$output_path/Demo_${now}.xcarchive" specified archive_path= address # output IPA address ipa_path= "$output_path/Demo_${now}.ipa" # specified Output IPA name ipa_name= "Demo_${now}.ipa" # obtained during the execution of the command commit message commit_msg= "$1" # output variables "===workspace path: ${workspace_path}===" echo echo "===archive path: ${archive_path}===" echo "===ipa path: echo" ===export method: a. ipa_path}=== "${export_method}===" echo "===commit msg: $1===" # first empty before a build gym --workspace ${workspace_path} --scheme ${scheme} --clean --configuration ${configuration} --archive_path ${archive_path} --export_method ${export_method} --output_directory ${output_path} --output_name ${ipa_name} # output in echo "===Finished. Total time: ${SECONDS}s==="

Four. Packaging complete automation, upload fir / dandelion third party platform

To upload to the fir / dandelion third party platform, you need to register an account and get token, then you can script it.

1. upload fir automatically

The command line tool
that installs fir-clifir needs to be loaded with ruby before it is executed

Gem install fir-cli
Fir fir publish ${ipa_path} # uploaded to -T fir_token -c ${commit_msg} ""
2. automate dandelion uploads
The path of the IPA file on the User Key IPA_PATH=$# dandelion uKey= "7381f97070*****c01fae439fb8b24e" API Key apiKey= # dandelion on "0b27b5c145*****718508f2ad0409ef4" # to upload (cat text.txt) rm -rf text.txt # executive uploaded to the dandelion command echo "+ + ++++++++++++upload+++++++++++++" curl -F "file=@${IPA_PATH}" -F "uKey=${uKey}" -F "_api_key=${apiKey}" http://www.pgyer.com/apiv1/app/upload

Five. Complete continuous integration process

After the continuous integration above, we now have the following complete, continuous integration process

Teach you how to continuously integrate iOS projects using Jenkins

Six. Jenkins + Docker

About the deployment of Jenkins, is divided into the following two types: single node
deployment this deployment is applicable to most projects, the task of building a lighter, less number of single node is sufficient to meet the everyday needs of development.
multi node (Master-Slave) deployment of
is usually larger, frequent code submission (meaning frequent construction), and automated test stress projects take this deployment structure. In this deployment, Master usually acts as the role of managers, responsible for task scheduling, slave node management, collection task state, and the establishment of specific tasks will be assigned to the slave node. Slave node, a Master node can theoretically there is no limit to the number of management, but usually with the increase of the quantity, the performance and stability will have different degrees of decline, the specific effects due to Master performance is different.

However, there are some drawbacks to multi node deployment. When the test cases become massive, they cause some problems, so someone designed the following deployment structure, Jenkins + Docker

Teach you how to continuously integrate iOS projects using Jenkins

Because of the current project is still in the single node (Master) deployed on multiple nodes (Master-Slave) deployment of no practical experience, an improved version of the Docker is not contacted, but if there is such a massive test case, a large number of high pressure and complicated regression testing needs, then we recommend reading this article.


That’s my hands-on experience with Jenkins continuous integration. To share with you, if there are any errors, welcome to exhibitions.