preface

As we all know, the competition of App has come to the white-hot stage where user experience is king and quality is top. Users are picky. If a company’s marketing team, very not easy to hit the heavily promoted a APP, very not easy with some users, due to a bug, leading to a group of online users in use have to flash back bugs, light, probably early promotion of money were wasted, or, word of mouth is not good, also can’t afford to improve future users. Calm down to analyze the cause of the problem, nothing more than quality is not pass the line. In addition to some subjective factors, a large part of the objective factors I think we can be prevented. According to a set of development specifications proposed by the gods, CI + FDD, can help us solve the objective factors to a great extent. Continuous Integration (CI)

directory

  • 1. Why do we need continuous integration
  • 2. Continuous integration tool — Jenkins
  • 3. IOS automatic packaging commands — xcodebuild + xcrun and Fastlane-gym commands
  • 4. Package complete automatic 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 to start with what is. So what is continuous integration.

Continuous integration is a software development practice: many teams integrate their work frequently, and each member usually integrates on a daily basis, leading to multiple integrations per day. Each integration is automated with builds (including tests) to detect errors as quickly as possible. Many teams find that this approach can significantly reduce integration problems and make team development faster.

CI is a development practice. The practice should consist of three basic modules, a process that can be built automatically, code that can be compiled automatically, and code that can be distributed, deployed, and tested automatically. A repository, SVN or Git. The last one is a continuous integration server. Continuous integration allows us to get product feedback and respond to the feedback process at a high frequency through automation and other means.

So what are the benefits of continuous integration? Here is a recommended article that breaks down Continuous Integration (CI) and test-Driven Development (TDD) into 12 steps. However, the benefits are multiplied by 24 points.

Let me talk about some profound advantages brought by using CI.

1. Shorten the development cycle and iterate quickly

Each release starts with an estimated development cycle, but it’s always delayed by a variety of things. There are some objective factors involved. As the number of product lines increases, the speed of iteration becomes faster and the pressure of testing becomes greater. If the tests are tested after the development is complete, it will affect you for a long time. At this point, late integration will seriously slow down the project. If continuous integration can be carried out as early as possible, and the 12-step iterative loop shown in the figure can be entered as soon as possible, problems can be exposed as early as possible, solved as early as possible, and tasks can be completed within the specified time.

2. Efficiency brought by automated assembly line operation

Packaging can be a time-consuming, low-skill job for developers. If there are many developers, the chances of conflicting code changes are greater, and there is no production line management mechanism, the code quality of the code warehouse is difficult to guarantee. The team will take some time to resolve conflicts, and once they are resolved, you will need to manually pack them yourself. If the certificate is wrong at this time, it will take a long time. This time could be saved by continuous integration. Two days a day may not seem like much, but in terms of annual units, it can save a lot of time!

3. Can be deployed at any time

With continuous integration, we can package on a daily basis, and the biggest advantage of this high frequency integration is that it can be deployed online at any time. In this way, it will not lead to the imminent launch, full of bugs, full of bugs, scrambling to finish can not deploy, seriously affect the online time.

4. Avoid silly mistakes to a large extent

We can make mistakes, but it is not right to make elementary ones. Low-level errors include compilation errors, installation problems, interface problems, and performance problems. Continuous integration, measured in days, can quickly find compilation problems, and automatic packaging can not pass directly. After the package is finished, the test sweep cannot be installed and this problem is immediately exposed. Interface problems and performance problems are found in automated test scripts. These low-level problems are exposed by continuous integration to remind us to avoid low-level errors.

Two. Continuous integration tool — Jenkins

Jenkins is an open source project that provides an easy-to-use continuous integration system that frees developers from the complexity of integration to focus on the more important implementation of business logic. Jenkins can also monitor integration errors, provide detailed log files and reminders, and visually show the trend and stability of project construction in the form of charts.

According to the official definition, Jenkins serves the following purposes:

  1. Build the project
  2. Run test cases to detect bugs
  3. Static code detection
  4. The deployment of

As for the four points, it is relatively convenient to use in practice: 1. Automatic packaging of construction projects can save developers a lot of time. Importantly, Jenkins has maintained a set of high quality usable code for us, and ensured a pure environment. It is not uncommon for packaging to fail due to local configuration errors. Now Jenkins is a fair judge, he doesn’t compile ipA correctly, that’s a compilation error or configuration problem. There is no need for developers to argue that local is working and that they can’t run when they pull someone’s code. Jointly maintain the normal compilation of Jenkins, because the compilation environment of Jenkins is much simpler than our local environment, and it is the purest and pollution-free compilation environment. Developers just have to focus on coding. This is a convenience for developers.

2. This can be used to automate tests. Generate a number of test cases locally. Run these use cases daily using the server. Run every interface every day. It may seem unnecessary, but in reality a system that works well today can be broken tomorrow because of a code change today. With Jenkins, regression tests could be carried out on a daily basis. As long as the code was changed, Jenkins would run all regression test cases. In the case of tight project deadlines, regression testing is often ignored, as it is likely to be a “dead end” after a test run. However, because the regression test was not timely, the system was not available when the final version was released. At this time, it was time-consuming to go back to find the reason. It was also a headache to check the submission records and see hundreds of submission records. Regression testing on a daily basis immediately detects problems. Testers can focus on unit testing every day and do regression testing manually once a week. This is a convenience for testers.

3. This is static code analysis, which can detect many code problems, such as potential memory leaks. Due to the purity of Jenkins’ environment, we can still find some problems that cannot be found in our local complex environment, and further improve the code quality. This is to bring convenience to quality control.

4. Deploy at any time. After Jenkins completes the packaging, he can set the following operation, which is usually to submit the APP to the system of running test cases, or deploy it to the internal test platform to generate two-dimensional code. Low-level problems such as failure to install in deployment are immediately exposed. Testers only need to scan the QR code to install, very convenient. This is also a convenience for testing.

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

Let’s start installing Jenkins. Download the latest PKG installation package from Jenkins. IO /.

You can also download jenkins.war and run java-jar jenkins.war to install it.

Once the installation is complete, Safari will probably open automatically. If it doesn’t, open your browser and type http://localhost:8080

An error may be reported at this point. If there’s a problem with that. The cause of this problem is that the Java environment is faulty.

At this point, if you reboot your computer, you’ll find that Jenkins has given you a new user name, Jenkins, but you don’t know the password. You might try the password, but it must be wrong, because the initial password is very complicated. The correct way to open http://localhost:8080 is to reset the initial password as shown in the following figure.

According to clew, find/Users/Shared/Jenkins/Home/the directory, this directory is Shared directory, but there are permissions, the Jenkins user/secrets/directory is not to read and write access.

Open the initialAdminPassword file and copy the password to a web page to reset the password. The following figure

Install it all the way through, enter your username, password, email, etc., and call it complete.

Again, go to localhost:8080 and choose “System Administration” — “Manage plug-ins”. We need to install some auxiliary plug-ins first.

Since we use GitLab to manage the source code, Jenkins doesn’t have the GitLab plugin, so we need to go to System Administration -> Manage Plugins, Select “GitLab Plugin” and “GitLab Hook Plugin” in the “Optional Plug-ins”, and then install.

To install the Xcode plug-in, follow the same steps as to install the GitLab plug-in. Choose System Administration -> Manage Plug-ins and select “Xcode Integration” in the “Optional Plug-ins” to install.

With this installed, we are ready to configure a build project.

Click on the new project to configure the General parameter.

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

Then set up source control.

Since I am using GitLab now, first configure SSH Key and add SSH to Jenkins certificate Management. On the Jenkins Management page, select “Credentials”, then select “Global Unrestricted”, and click “Add Credentials”, as shown in the picture below. We fill in our SSH information and click “Save”. This adds SSH to Jenkins’ global domain.

If the normal configuration is correct, the red warning in the figure below will not appear. If Jenkins is not connected to GitLab or SVN, please check whether the SSH Key is configured correctly.

Build Trigger Settings This is where you set up automated tests. There’s a lot of stuff involved here, and I haven’t gone into it yet, so I’m not going to set it up here. Those with automated testing needs should study this setup.

But there are two configurations that need to be configured

Poll SOURCE Code Management (Poll SCM) Poll source management You need to set the source code path to implement Poll. Result: 0/5 Periodically poll Build (periodic Build) every 5 minutes. The periodically Build is periodically set to 00 20 * Periodically Build is performed at 20:00 every day. Of course, both Settings are the same and can be used universally.

Here’s the format

Minutes (0-59) hours (0-23) Days (1-31) Months (1-12) Days of the week (0-7,0 and 7 are both Sundays) see here for more details on Settings

Build environment setup iOS packaging requires signature files and certificates, so for this part we check “Keychains and Code Signing” and “Mobile Provisioning Profiles”. In the System Management page, select “Keychains and Provisioning Profiles Management”.

Go to the Keychains and Provisioning Profiles Management page and click the browse button to upload your Keychain and certificate, respectively. After the file is successfully uploaded, specify the name of the signature file for the keychain. Click “Add Code Signing Identity” and finally Add the Code Signing Identity as shown below:

Note: The first time I imported the certificate and Provisioning Profiles file, I ran into a glitch. I thought I needed a certificate, but the Keychain file was not a CER certificate file. The Keychain is in/Users/administrator username/Library/keychains/login Keychain, when the Keychain after set up, Jenkins would put the Keychain copied to/Users/Shared/Jenkins/Library/keychains, here (Library file is “hidden”). Provisioning Profiles files are directly copied to/Users/Shared/Jenkins/Library/MobileDevice file directory.

Now that the Adhoc certificate and signature file are configured in Jenkins, all we need to do is specify the relevant file in the item setting. Go back to our new item, find the build environment, and select your certificate and signature file as shown below.

Next, set up the build

We chose to execute a package script here. The script is explained in detail in the next section.

Post-build operation

Here we select Execute a set of scripts, which is also a script used to upload automatically packaged IPA files. The script is explained in detail in Chapter 4.

At this point, our Jenkins setup is complete. Click Build to start building the project.

Construct once, each color represents the following meaning:

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

If the build fails, you can go to Console Output and you can look at the log.

IOS automatic packaging commands — xcodebuild + xcrun and Fastlane-gym commands

In daily development, packaging is an indispensable part of the final launch. If the project needs to be packaged into an IPA file, the usual way is to click “Product -> Archive” in Xcode. After the entire project is Archive, Then select from the automatically pop-up “Organizer” to export the AD Hoc, Enterprise type IPA package as needed. Xcode does a pretty good job of packing, but it still requires five or six clicks manually. Coupled with our current need for continuous integration, automating execution with packaging commands becomes a natural necessity.

1. Run xcodebuild + xcrun

Xcode provides a set of build packages for us developers, the XcodeBuild and xcrun commands. Xcodebuild packages our specified project into an.app file, and xcRun converts the specified.app file into the corresponding.ipa file.

The specific documents are as follows: XcodeBuild official documents and XCRUN official documents

NAME xcodeBuild - build Xcode projects and workspaces SYNOPSIS 1. xcodebuild [-project name.xcodeproj] [[-target Targetname]... | - alltargets] [- configuration configurationname] [- SDK [sdkfullpath | sdkname]], [action]... [buildsetting = value... [- userdefault = value... Xcodebuild [-project name. Xcodeproj] -scheme schemename [[-destination DestinationSpecifier]... [destination - a timeout value] [- configuration configurationname] [- SDK [sdkfullpath | sdkname]], [action]... [buildsetting = value... [- userdefault = value... Xcodebuild-workspace name. Xcworkspace -scheme schemename [[-destination destinationspecifier]...] [destination - a timeout value] [- configuration configurationname] [- SDK [sdkfullpath | 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] 8. xcodebuild -exportArchive -archivePath xcarchivepath -exportPath destinationpath -exportOptionsPlist path 9. xcodebuild -exportLocalizations -project name.xcodeproj -localizationPath path [[-exportLanguage language]...]  10. xcodebuild -importLocalizations -project name.xcodeproj -localizationPath pathCopy the code

The first three of the 10 commands are the most important.

-project-workspace: This corresponds to the name of the project. If there are multiple projects and they are not specified here, the default is the first project. -target: packages the target. If no target is specified, the first target is used. – Configuration: If the configuration is not modified, the Debug and Release versions are used by default. The default Release version is not specified. -buildsetting=value … : Use this command to modify project configurations. -scheme: specifies the package scheme.

These are the most basic commands.

The -target and -configuration parameters can be obtained using xcodebuild-list, the -sdk parameters can be obtained by xcodebuild-showsdks, and the -sdk parameters can be obtained by xcodebuild-showsdks. [buildsetting=value …] Used to override existing configurations in the project. For parameters that can be overridden, see the 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 requires specifying a scheme. archive Archive a scheme from the build root (SYMROOT). This requires specifying a scheme.  test Test a scheme from the build root (SYMROOT). This requires specifying a scheme and optionally a destination. installsrc Copy the source of the project to the source root (SRCROOT). install Build the target and install it into the Target's installation directory in the distribution root (DSTROOT). Clean Remove build products and intermediate files from the build root (SYMROOT).Copy the code

The third command above is specifically used to type projects with Cocopods, because the project file is no longer XcodeProj, but xcworkspace.

Now, 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]: specify output filename
[-plugin plugin]: specify an optional plugin
-help: brief help message
-man: full documentation
-v[erbose]: provide details during operationCopy the code

Xcrun – SDK iphoneOS -V PackageApplication +

Now that we know the parameters, let’s see how we can use them. Here is an automated packaging script written using the xcodebuild + xcrun command

CODE_SIGN_DISTRIBUTION="iPhone Distribution: Shanghai ******* Co., Plist path project_infoplist_path="./${APP_NAME}/ info.plist BundleShortVersion = $(/ usr/libexec/PlistBuddy - "print CFBundleShortVersionString" c "${project_infoplist_path}") # build value  bundleVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleVersion" "${project_infoplist_path}") DATE="$(date +%Y%m%d)" IPANAME="${APP_NAME}_V${bundleShortVersion}_${DATE}. Ipa "# IPA_PATH="$HOME/${IPANAME}" echo ${IPA_PATH} echo "${IPA_PATH}" > > text. TXT / / the use of the below 2 lines are not Cocopods echo "= = = = = = = = = = = = = = = = = clean = = = = = = = = = = = = = = = = =" xcodebuild - target "${APP_NAME}" -configuration 'Release' clean echo "+++++++++++++++++build+++++++++++++++++" xcodebuild -target "${APP_NAME}" -sdk iphoneos -configuration 'Release' CODE_SIGN_IDENTITY="${CODE_SIGN_DISTRIBUTION}" SYMROOT='$(PWD)' / / the use of the below 2 lines are integrated with Cocopods echo "= = = = = = = = = = = = = = = = = the 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}"Copy the code
2. The gym command

Speaking of gym, we must talk about Fastlane first. Fastlane is an automated packaging tool set, written in Ruby, for iOS and Android automated packaging and publishing. Gym is the pack command.

The fastlane website is here, and the Fastlane Github website is here

To use the GYM, install Fastlane.

sudo gem install fastlane --verboseCopy the code

Fastlane contains all the commands we need to do when we go live after coding.

The device framework pem automatically generates and updates the app push notification description file sigh. Create a new iOS app in iTunes Connect using the command line. Cert: automatically create iOS certificate. Easy ways to invite beta tests gym: build a new release, package Match: Use Git to synchronize developer credentials and file configurations between your members Scan: Execute test cases on iOS and Mac appsCopy the code

The whole publishing process can be described by Fastlane as follows

lane :appstore do
  increment_build_number
  cocoapods
  xctool
  snapshot
  sigh
  deliver
  frameit
  sh "./customScript.sh"

  slack
endCopy the code

Xctool is an enhanced implementation of the official XcodeBuild command. The output is much more intuitive and readable than that of XcodeBuild. Install via BREW.

brew install xctoolCopy the code

Use gym automatic packaging, the script is as follows

Project_path =$(PWD) # Take the current time string to the end of the file Now =$(date +"%Y_%m_%d_%H_% m_% S") # Specify the scheme name of the project Scheme ="DemoScheme" # specify the configuration name to be packaged. Configuration ="Adhoc" # specify the output method to be used for packaging. Currently supports app-Store, Package, ad-hoc, Enterprise, Development, and Developer-ID, The xcodeBuild method parameter export_method='ad-hoc' # specifies the project address workspace_path="$project_path/ demo.xcworkspace Archive_path ="$output_path/Demo_${now}. Xcarchive "# specify ipA address Ipa_path ="$output_path/Demo_${now}. Ipa "ipa_name="Demo_${now}. Ipa" ${workspace_path}=== workspace path: ${workspace_path}===" echo "===archive path: ${archive_path}===" echo "===ipa path: ${ipa_path}===" echo "===export method: ${export_method}===" echo "===commit msg: Build gym --workspace ${workspace_path} --scheme ${scheme} --clean --configuration ${configuration} --archive_path ${archive_path} --export_method ${export_method} --output_directory ${output_path} --output_name Echo "===Finished. Total time: ${SECONDS}s===Copy the code

Iv. Package complete automatic upload fir/dandelion third party platform

To upload to FIR/Dandelion third-party platform, you need to register an account and obtain a token before scripting operation.

1. Automatically upload FIR

To install the fir- Clifir command line tool, you need to install Ruby first

gem install fir-cliCopy the code
Fir publish ${ipa_path} -t fir_token -c "${commit_msg}"Copy the code
2. Upload dandelions automatically
# User Key uKey="7381f97070***** c01FAe439fb8b24e "# API Key apiKey=" 0b27b5C145 ***** 718508f2AD0409EF4" # to upload the ipa file path IPA_PATH = $(cat text. TXT) rm - rf text. TXT # uploaded to the dandelion of command echo "+ + + + + + + + + + + + + + upload++ + + + + + + + + + + +" curl - F "file=@${IPA_PATH}" -F "uKey=${uKey}" -F "_api_key=${apiKey}" http://www.pgyer.com/apiv1/app/uploadCopy the code

Complete continuous integration process

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

Jenkins + Docker

Jenkins deployment can be divided into the following two types: Single-node (Master) deployment This kind of deployment is suitable for most projects, and its construction tasks are light and the number is small. A single node is enough to meet the needs of daily development. Multi-node master-slave deployments are typically large in scale, with frequent code commits (meaning frequent builds), and are often used on projects with high automation test pressures. In this deployment structure, the Master usually only acts as a manager, responsible for task scheduling, slave node management, and task status collection, while specific build tasks are assigned to the slave nodes. Theoretically, there is no upper limit to the number of slave nodes a Master node can manage. However, as the number of slave nodes increases, the performance and stability of the slave node will decrease to varying degrees, depending on the performance of the Master hardware.

However, multi-node deployment has some drawbacks, which can cause problems when test cases become massive, so someone designed the following deployment structure, Jenkins + Docker

Since the author’s current project is still in single-node master-slave deployment, he has no practical experience in multi-node master-slave deployment, let alone the improved version of Docker. However, if there are such massive test cases and a large number of complex regression tests with high pressure, I recommend you to read this article.

The last

The above is my practical experience about Jenkins continuous integration. Share with you, if there is any mistake, welcome to comment more. Halfrost on Sina Weibo