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

  1. Homebrew

    brew cask install fastlane
    Copy the code
  2. Setup script

    Download the ZIP file. Double-click the shell script

  3. 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
  1. Automate screenshots
  2. Automate beta distribution to TestFlight
  3. Automate App Store distribution: Automate release to App Store
  4. 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

    1. Download the latest Jenkins war pack and double click to install it

    2. 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

  1. 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
  1. 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
  1. 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

  1. Get the IP address of the github/gitlab.global.ssl.fastly.Net

    nslookup github.global.ssl.fastly.Net
    Copy the code

  2. Get the IP address of github.com

    nslookup github.com 
    Copy the code

  3. 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
  4. 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.