Preface:
As an iOS developer, one of the most essential phases is packaged testing. While Xcode can implement packaging, it can be frustrating to have testers constantly urging you to test new packages during the testing phase, and packaging is a very repetitive and time-consuming process. Therefore, I studied the automatic packaging process of Jenkins and Fastlane, hoping to be helpful to everyone, but also encountered many problems and pits on the way.
Please be direct if you need helpTo contact me
preparation
-
Ruby:
Fastlane installation requires ruby 2.0 or higher, although The MAC comes with Ruby, but the version may be lower and have fewer permissions, so it is recommended to use RVM to manage ruby versions.
Follow this article to install Ruby version manager RVM for Mac
-
Xcode command line tool
xcode-select --install Copy the code
It will prompt you if it is already installed
Will appear if not installed
Xcode-select –install — xcode-select –install
-
Java JDK (this is the Jenkins installation, if you do not need Jenkins can be ignored)
You can check the current Java version first
java -version Copy the code
If not, go to the JDK download link to download it
Since Jenkins is written in the Java language, Java support is required and JDK version 1.8 is recommended
You need to accept the agreement before you can download
After the download is complete, you can directly install, here will not repeat.
The preparatory work is finished here
Fastlane
Fastlane is the easiest way to automate beta deployment and release for iOS and Android applications. 🚀 can handle tedious tasks such as generating screenshots, handling code signing, and publishing the app. Fastlane integrates a number of mobile development tools for signing, compiling, and publishing, making it a great packaging tool.
Fastlane initialization
There are three ways to install Fastlane
-
Homebrew
brew cask install fastlane Copy the code
-
Setup script
Download the ZIP file. Double-click the shell script
-
RubyGems
gem install fastlane -NV Copy the code
Dandelion plugin
Here we use Jenkins to upload dandelion at the end, in order to obtain the download QR code.
This article also includes an introduction to using Fastlane to upload dandelions
Install the dandelion plugin after the Fastlane installation is successful
fastlane add_plugin pgyer
Copy the code
What if nothing happens and it just works
At first I used native Ruby and it failed. Then you use Ruby managed by RVM and it works.
If you encounter other questions, please Google it, or contact me and we will discuss.
Initialize the
CD/To your own project directoryCopy the code
Initialize the fastlane
fastlane init
Copy the code
The following options appear if none of the previous ones have any problems
! [](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/9/6/16d04e00a64a304d~tplv-t2oaga2asx-image.image)Copy the code
- Automate screenshots
- Automate beta distribution to TestFlight
- Automate App Store distribution: Automate release to App Store
- Manual setup: indicates Manual Settings
Here we’re picking number three, and then there are some options
1. 📸 Automate screenshots
2👩✈️ Automate beta distribution to TestFlight3🚀 Automate App Store Distribution4🛠 Manual setup - manually setup your project to automate your tasks?3
[10:37:53] : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -10:37:53]: --- Setting up fastlane for iOS App Store distribution ---
[10:37:53] : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -10:37:53]: Parsing your local Xcode project to find the available schemes and the app identifier
[10:37:53] :$ xcodebuild -showBuildSettings -workspace FastlaneDev.xcworkspace -scheme FastlaneDev
[10:37:55] :$ cd 'Path to your project' && agvtool what-version -terse
[10:37:55] : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -10:37:55]: --- Login with your Apple ID ---
[10:37:55] : -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -10:37:55]: To use App Store Connect and Apple Developer Portal features as part of fastlane,
[10:37:55]: we will ask you for your Apple ID username and password
[10:37:55]: This is necessary for certain fastlane features, for example:
[10:37:55] : [10:37:55]: - Create and manage your provisioning profiles on the Developer Portal
[10:37:55]: - Upload and manage TestFlight and App Store builds on App Store Connect
[10:37:55]: - Manage your App Store Connect app metadata and screenshots
[10:37:55] : [10:37:55]: Your Apple ID credentials will only be stored in your Keychain, on your local machine
[10:37:55]: For more information, check out
[10:37:55] :https://github.com/fastlane/fastlane/tree/master/credentials_manager
[10:37:55] : [10:37:55]: Please enter your Apple ID developer credentials
[10:37:55]: Apple ID Username:
'Your Apple ID'
[10:38:16]: Logging in.Copy the code
! [](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/9/6/16d04e0a8d184c86~tplv-t2oaga2asx-image.image)Copy the code
If you have more than one team under your account, you will be given a choice
And wait for the installation
In the meantime, I ran into this bundle update and it didn't work, so I just re-init it
After success, open our project directory and find this file
Congratulations on your successful initialization!!
Configuration Fastlane
The file name | describe |
---|---|
Appfile | Get details about the project from the Apple Developer Portal |
Fastfile | Core file, store lane tasks |
Deliverfile | The Deliver configuration file, which gets details about the project from iTunes Connect |
metadata | Example Synchronize metadata in the iTC |
screenshots | Example Synchronize iTC snapshots |
Here to call home recommended a configuration article Fastfile reference configuration
The following is my configuration for reference only, not fastlane upload dandelion, because want to get the QR code in Jenkins inside the temporary solution to use Jenkins upload dandelion if you need fastlane upload directly open the comments carried out
# export path
$ipa_output_directory = "/Users/xx/xx/fastlaneBuild"
# upload dandelion package path
$ipa_output_upload_directory = "/Users/xx/.jenkins/workspace/xx/ipa"
# Jenkins matches the package name
$jenkins_name = "Project name"
default_platform(:ios)
# Application noun
scheme_name = "Project Name"
# get version
version = get_info_plist_value(path: ". /#{scheme_name}/Info.plist".key: "CFBundleShortVersionString")
Get build number
build = get_info_plist_value(path: ". /#{scheme_name}/Info.plist".key: "CFBundleVersion")
We need to use xcode 10.1 for our project
xcode_select("/ Applications/Xcode_10. 1. The app")
# Default in-beta packaging, currently support app-Store, Package, ad-Hoc, Enterprise, development
ipa_exportMethod = "ad-hoc"
ipa_exportMethod_appStore = "app-store"
# calculation buildNumber
def updateProjectBuildNumber
currentTime = Time.new.strftime("%Y%m%d")
scheme_name = "Project Name"
build = get_info_plist_value(path: ". /#{scheme_name}/Info.plist".key: "CFBundleVersion").to_s
if build.include?"#{currentTime}."
Calculate the iteration version number for the current version
lastStr = build[build.length-2..build.length-1]
lastNum = lastStr.to_i
lastNum = lastNum + 1
lastStr = lastNum.to_s
if lastNum < 10
lastStr = lastStr.insert(0."0")
end
build = "#{currentTime}.#{lastStr}"
else
Reset the build number of the current version
build = "#{currentTime}.01. ""
end
puts("* * * * * * * * * * * * * | update build#{build}| * * * * * * * * * * * * *")
# change the project build number
increment_build_number(
build_number: "#{build}"
)
end
Jenkins started asking to upload the log
You can't get the QR code display, so use Jenkins to upload dandelions
def archiveSuccessLog(outputName,buildConfig)
# Move the package to Jenkins' workspace directory for Jenkins to upload the content of the dandelion matching package. Always keep one copy
# FileUtils.cp_r("#{$ipa_output_directory}" + "/#{outputName}", "#{$ipa_output_upload_directory}" + "/#{$jenkins_name}.ipa")
puts"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -"
puts"| |"
puts"| |"
puts"| 🎉 🎉 🎉 -- -- -- -- -- -- -- -- - > > > > >#{buildConfig}Version _ packaging success < < < < < -- -- -- -- -- -- -- -- -- -- -- 🎉 🎉 🎉 |"
puts"| |"
puts"| 🎉 🎉 🎉 -- -- -- -- -- -- -- -- - > > > > > Jenkins can start uploading the dandelion < < < < < -- -- -- -- -- -- -- -- -- -- -- 🎉 🎉 🎉 |"
puts"| |"
puts"| |"
puts"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -"
end
#
# All task scripts
#
platform :ios do
#
# * * * * * * * * * * * * * | uploaded to test version to the dandelion _ test package | * * * * * * * * * * * * *
#
desc "Upload test version to Dandelion _ Test Pack"
lane :topgyer_debug do|option|
puts "* * * * * * * * * * * * * | start packing. Ipa file... | * * * * * * * * * * * * *"
# Automatically add builds
updateProjectBuildNumber
Automatic certificate generation
cert
# export name
output_name = "#{scheme_name}_#{version}_#{build}_#{option[:desc]}_#{Time.now.strftime('%Y%m%d%H%M%S')}.ipa"
gym(
Specifies the ipA name for the output
output_name: "#{output_name}".# Specify scheme for the project
scheme: "xxx".# Whether to clear previous compilation information true: Yes
clean: true.export_method: "#{ipa_exportMethod}".export_options: {iCloudContainerEnvironment: 'Development'},
# Specify how to package, Release or Debug as needed
configuration:"Debug".# package export location
output_directory: "# {$ipa_output_directory}".)You can't get the QR code display, so use Jenkins to upload dandelions
archiveSuccessLog(output_name," Debug ")
# Here is fastlane direct upload dandelion
# Open archiveSuccessLog(output_name," Debug ")
# puts "* * * * * * * * * * * * * | began to upload the beta (the dandelion... | * * * * * * * * * * * * *"
Configure the dandelion API_key and user_key
# pgyer(api_key: "your api_key", user_key:" your user_key", update_description: "#{option[:desc]}")
# puts "* * * * * * * * * * * * * | beta (uploading to a dandelion 🎉 🎉 🎉 successful 🎉 🎉 🎉 | * * * * * * * * * * * * *"
end
#
# * * * * * * * * * * * * * | upload App Store | * * * * * * * * * * * * *
#
lane :toappstore do
project_identifier = ""
puts "* * * * * * * * * * * * * | started uploading AppStore... | * * * * * * * * * * * * *"
# Automatically add builds
updateProjectBuildNumber
Automatic certificate generation
# cert
# export name
codesigning_identity = "Certificate Name"
output_name = "#{scheme_name}_#{version}_#{build}_#{ipa_exportMethod_appStore}_#{Time.now.strftime('%Y%m%d%H%M%S')}.ipa"
gym(
Specifies the ipA name for the output
output_name:output_name,
# Specify scheme for the project
scheme:"xxx".# Whether to clear previous compilation information true: Yes
clean:true.Specify the packaging method, Release or Debug
configuration:"Release".Support app store, Package, ad-hoc, Enterprise, and Development
export_method:"app-store".# Upload environment
export_options: {iCloudContainerEnvironment: 'Production'},
# specify the output folder
output_directory:"# {$ipa_output_directory}",
)
deliver(
Choose to skip image and metadata uploads and configure them yourself
skip_screenshots:true.skip_metadata:true.Submit the new version for review after uploading
submit_for_review: false.force:true,
)
puts "* * * * * * * * * * * * * | upload the success 🎉 | * * * * * * * * * * * * *"
puts "* * * * * * * * * * * * * | began to upload the beta (the dandelion... | * * * * * * * * * * * * *"
Configure the dandelion API_key and user_key
pgyer(api_key: "Your api_key".user_key: "Your user_key".update_description: "#{option[:desc]}")
puts "* * * * * * * * * * * * * | beta (uploading to a dandelion 🎉 🎉 🎉 successful 🎉 🎉 🎉 | * * * * * * * * * * * * *"
Publish testFlight tests
# pilot
end
end
Copy the code
Execute in your own project directory
Fastlane Topgyer_DEBUG desc: TestsCopy the code
This sentence according to your own lane: topgyer_debug do | option | modified
After success, you can see that if there is an operation to upload dandelion, it will inform dandelion upload success, go to dandelion to view the new version.
17:58:59: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -17:58:59: | |
17:58:59: | |
17:58:59: | 🎉 🎉 🎉 -- -- -- -- -- -- -- -- - > > > > > the Debug version _ packaging success < < < < < -- -- -- -- -- -- -- -- -- -- -- 🎉 🎉 🎉 |
17:58:59: | |
17:58:59: | 🎉 🎉 🎉 -- -- -- -- -- -- -- -- - > > > > > Jenkins can start uploading the dandelion < < < < < -- -- -- -- -- -- -- -- -- -- -- 🎉 🎉 🎉 |
17:58:59: | |
17:58:59: | |
17:58:59: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -Copy the code
The next thing to think about is this: we developers can’t still execute script tasks to package and upload dandelions.
Is there a way to get testers to pack their own? So the next thing we need to do is have Jenkins execute our Fastlane script
And automatically generate two-dimensional code display. When a tester needs a test package, the developer simply uploads the code to the appropriate branch.
I chose a dedicated machine as the server to do this, after all, on my own computer will have some impact.
Jenkins
Jenkins is an independent open source software project. It is a Continuous integration tool developed based on Java for monitoring continuous repetitive work. It aims to provide an open and easy to use software platform to make continuous integration of software possible. Formerly Hudson is an extensible continuous integration engine. Can be used to automate a variety of tasks, such as building, testing, and deploying software. Jenkins can be installed via the native system package Docker, or even run independently from any machine with the Java Runtime Environment installed.
- Mainly used for:
- Continuously and automatically build/test software projects, such as CruiseControl and DamageControl.
- Monitor some scheduled tasks.
JAVA JDK
The Java JDK has been installed. If not, please go to the top to see the installation steps
Jenkins installation
-
installation
-
Download the latest Jenkins war pack and double click to install it
-
Brew Installation
// Use brew install Jenkins // Start service Jenkins by running Jenkins directly after installationCopy the code
-
Initialize the Jenkins
By default, visit http://localhost:8080/ to enter the Jenkins configuration page. Don’t turn off the terminal or Jenkins will shut it down
The following screen appears when it is first run
Enter the password as prompted and click Continue
To enter:
! [](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/9/6/16d04e1dbd432a95~tplv-t2oaga2asx-image.image)Copy the code
Just pick the first one
! [](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/9/6/16d04e20166a9dca~tplv-t2oaga2asx-image.image)Copy the code
Waiting for installation to complete
! [](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/9/6/16d04e246e5072ca~tplv-t2oaga2asx-image.image)Copy the code
Set your own password
Jenkins configuration
Choose Manage Jenkins -> Manage Plugins from the home page to download the plugin
Download the required plugins from this option. Some basic plugins were already installed when Jenkins was installed. Now you just need to download the required plugins
Ruby GitLab Xcode Integration Keychains and Provisioning Profiles Management ruby GitLab Xcode Integration Keychains and Provisioning Profiles Management Upload to pgyer Build Name and Description Setter // Set the Name of the package Description Setter // Set the pictureCopy the code
Once the plug-in is installed, start creating the project
Create a project
Go back to the home page and click New Item Choose: Free style projects
General –> Discard old builds the maximum number of days that can be retained.General –> This project is parameterized –> Add Parameter –> Choice Parameter
This is why you can choose build environments and branches first when building (add as needed!).
Name: BUILD_TYPE options: debug release description: packaging environment -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- name: GIT_BRANCH options: Description: Git branch of pull codeCopy the code
Source control –> Git
I use Git management source code here is gitlab SSH management ruby */${GIT_BRANCH}
Git management is all about letting Jenkins know where our source code is when he goes back and puts it in… Jenkins’ workspace during the first build
After filling in the project address, we click the Add button. (Branch Specifier don’t forget to modify the selection parameter set above here, pull the branch code) click the Add button
Key acquisition: First we need to ensure that git has configured our own secret key. Configuration Method -> Mac Configure the SSH key
-
Type SSH
-
Git userName is the name in git
-
PrivateKey PrivateKey in SSH, /Users/ username /.ssh/id_rsa
-
Passphrase Git password.
-
Click Add.
If your project is very large and requires a long clone time, you need to set the timeout time. Jenkins’ default timeout time is 10 minutes.
Git Clone is too Slow. Build environment –> Set Build Name Sets the display Name of the printed package. This option is not available if no plug-ins are added ruby iOS_XXX_${GIT_BRANCH}_${BUILD_TYPE}_build(${BUILD_NUMBER})
Build –> Add build steps –> Execute Shell
CD /Users/ Your project directory Fastlane Topgyer_DEBUG desc: beta _DebugCopy the code
Then save and exit
Go back to the home page –> Build with Paramters –> Select environment and branch and start building The first build requires pulling code from Git and changing it if it times out, as described above
If “fastlaneCommand not found” is displayed, click this link fastlaneCommand not found)
Look forward to hearing from Jenkins!!
After packing successfully, I found that I still had to click on the link to go to Dandelion every time before downloading
After studying how to directly put the dandelion link in the construction after digging
Such as: sauce ~
Generate dandelion QR code
At first, I used Fastlane to upload dandelions, but it was not easy to get the QR code
Finally, I figured out where to get Jenkins to fastlane bag and upload dandelions, and it worked!
Here are the steps
-
Upload dandelions
Go to the configuration of our current project -> go to the final post-build action -> add post-build action steps
Pgyer API_key: your elion api_key is the same as the ipa_output_upload_directory in the fastfile file. API package address file wildcard: Open ##### FileUtils. Cp_r ("#{$ipa_output_directory}" + "/#{outputName}", "#{$ipa_output_upload_directory}" + "/#{$jenkins_name}. Ensure that the ipA folder has only one up-to-date package. This package is used to upload dandelionsCopy the code
-
Obtain the QR code operation:
Post-build operations –> Add post-build operations –>Set Build Description
<a href="${appBuildURL}"><img SRC ="${appQRCodeURL}" width="118" height="118"/></aCopy the code
- The last step is back to the home page –> Manager Jenkins –> Configure Floable Security
The tag formatter is set to Safe HTML
OK!!!!! Done!! Go to the home page and build! !!!!!
conclusion
The combination of Fastlane and Jenkins is introduced. More assembly line, if there is something wrong, please point out,
And then we get our computer’s IP address http://computer’S IP address :8080/ and we’ll just give it to the test and we’ll go ahead and click build,
You are advised to use network cables to prevent IP addresses from changing.
I have studied the process of using Jenkins to package and upload, but Jenkins needs to configure a lot of things, such as certificates, Xcode and a series of operations. If the configuration is wrong, it will fail and it is not easy to find out the problems, so I choose Fastlane to package and upload Dandelion. Later, in order to obtain the QR code, Jenkins was selected to upload dandelion.
Temporary solution If there is a better way to point out, I will continue to research a better way.
Thank you!
Problems encountered in the later period
1. The Pod error occurs
If the following error occurs when you enter the POD command
/Library/Ruby/Site/2.3.0/rubygems.rb:289:in `find_spec_for_exe': can't find gem cocoapods (>= 0.a) with executable pod (Gem::GemNotFoundException) from / Library/Ruby/Site / 2.3.0 / rubygems rb: 308: in `activate_bin_path' from /usr/local/bin/pod:23:in `
'
Copy the code
-
Reason 1:
- The Ruby version is faulty. Please upgrade Ruby to the latest version first
-
Reason 2:
-
If you are sure nothing is wrong then execute the command
gem install cocoapods Copy the code
pod install Copy the code
You will find that the POD is ready to work
-
Git clone is too slow
Find the IP address of the domain name and modify the host file
-
Get the IP address of the github/gitlab.global.ssl.fastly.Net
nslookup github.global.ssl.fastly.Net Copy the code
-
Get the IP address of github.com
nslookup github.com Copy the code
-
Add it to the /etc/hosts file
151.101.76.249 github.global.ssl.fastly.net 192.30.253.112 github.com Copy the code
-
Force update of DNS cache
-
windows
ipconfig /flushdns Copy the code
-
linux
sudo /etc/init.d/networking restart Copy the code
-
mac
sudo killall -HUP mDNSResponder Copy the code
-
3. “fastlaneCommand not found” is displayed when Jenkins executes shell script
Fastlane XXX desc: XXX can successfully package the shell script executed in Jenkins cannot execute the following error
16:20:30 xxx/xxx/xxx/xxx.sh: line 4: fastlane: command not found
16:20:30 Build step 'Execute shell' marked build as failure
16:20:30 New run name is 'iOS_xxx_develop_debug_build(17)'
16:20:30 [UPLOAD TO PGYER] - The build FAILURE, so the file was not uploaded.
16:20:30 [description-setter] Description set:
16:20:30 Finished: FAILURE
Copy the code
Solutions:
Add #! Before Jenkins’ shell script command /bin/bash-ilex command eg:
#! /bin/bash -ilexCD /Users/ XXXX/XXXX # Your project address fastlane Topgyer_DEBUG desc: beta _DebugCopy the code
** then perform the build. 支那Copy the code
Reference:
jenkins.io/zh/
fastlane.tools/
www.jianshu.com/p/656756920…
www.jianshu.com/p/c44ef74d9…
Juejin. Cn/post / 684490…
Thanks again!!
Xiao Li xiao Li has you all the way
Dian.