Jenkins(二)自動化打包(iOS)

前言

從前文Jenkins(一)初步認識我們已經初步認識了Jenkins。接下來我們將通過一些配置來實現利用Jenkins自動化打包的目的。

摘要
一、進入Jenkins頁面
二、創建自由風格的項目并配置源碼管理
三、安裝自動化打包構建時候所需的插件
四、上傳構建過程所需的文件
五、配置構建方式(這里我們選擇Xcode構建方式)
六、構建過程中的其他問題
附:直接跳過本篇文章,查看下篇文章:Jenkins(三)其他錯誤

其他文章
Jenkins(一)初步認識
Jenkins(二)自動化打包(iOS)
Jenkins(三)自動化打包其他錯誤(iOS)
Jenkins(四)自動化打包幫助(iOS)
iOS 再談打包(證書、自動化、持續集成等)從開始到結束(精簡)

一、進入Jenkins頁面

雙擊jenkins.war,啟動jenkins

image.png

隨后輸入完整地址http://localhost:8080即可進入Jenkins這個就不用重復提了。

二、創建自由風格的項目并配置源碼管理

配置完源碼管理后,點擊“立即構建”,所構建的項目的源碼會從所選擇的SVN或Git上默認被下載到/Users/Shared/Jenkins/Home/workspace/里。

如果你發現代碼一直沒下載下來,那原因可能是你本身并沒有裝Git工具,安裝后,重新點擊“立即構建”即可下載Git上的代碼到/Users/Shared/Jenkins/Home/workspace/里。

詳細的請參見Jenkins(一)初步認識中的《二、創建項目并配置源碼管理》部分。

三、安裝自動化打包構建時候所需的插件

  • 1、安裝管理發布證書及相關簽名文件的插件。安裝完該插件后,才可以將我們的"發布證書及相關簽名文件"利用該插件上傳,并將它們配置在我們的構建環境中。
  • 2、安裝構建方式所選的插件
    下面會依次說明。如已安裝請跳過此步。
1、安裝管理發布證書及相關簽名文件的插件。安裝完該插件后,才可以將我們的"發布證書及相關簽名文件"利用該插件上傳,并將它們配置在我們的構建環境中。

打包內測版時,需要發布證書及相關簽名文件,而這些發布證書及相關簽名文件的管理需要通過“Keychains and Provisioning Profiles Management”插件管理。
所以我們在系統管理->管理插件,在“可選插件”中選中“Credentials Plugin”和“Keychains and Provisioning Profiles Management”安裝管理簽名證書的插件。

選擇安裝管理簽名證書的插件.png

安裝完之后,刷新界面在構建環境中,會且才會有如下選項
860EC768-234E-4856-BF84-AFE5EE16B1E3.png

這兩個選項需要填寫的東西如下:
image.png

上圖中的這些選項是iOS打包需要的簽名文件和證書。如果沒有的話,需要進入Keychains and Provisioning Profiles Management頁面添加。怎么添加下面會介紹。

2、安裝構建方式所選的插件

下載Xcode integration,并安裝后,構建選項中才會有Xcode方式。

構建的方式有編寫腳本和Xcode兩種常用方式。

Xcode構建方式.png

兩者構建方式相比,編寫腳本的話會更加靈活,但是腳本寫起來比較麻煩。這里我選擇用Xcode的方式進行構建。 所以需要選擇系統管理->管理插件,在“可選插件”中選中“Xcode integration”安裝。


安裝構建方式所選的插件.png

安裝完后,構建配置頁面如下:

image.png

如果未設置編譯輸出目錄Build output directory,其默認會在$WORKSPACE中對應項目里的bulids文件夾。

四、上傳構建過程所需的文件

1、將我們的"發布證書及相關簽名文件"利用該插件上傳,這些文件之后在構建的時候需要使用。

①、上傳工具在哪?
image.png

82E49797-9B62-40DD-8D69-EA65C1043C7E.png
②、要上傳的文件在哪、應該放哪?

常識補充:我們要明白mac系統的彈出框無法顯示隱藏的文件,所以如果要上傳文件的話,必須將那些隱藏的文件復制一份到另外一個可見的文件夾下。

回歸正題:要上傳的"發布證書及相關簽名文件"位于/Users/用戶名/Library下的keychains文件夾MobileDevice文件夾,該路徑為隱藏不可見的路徑。所以這里我們需要將放在隱藏不可見路徑/Users/用戶名/Library下的keychains文件夾MobileDevice文件夾,如圖

354C8FC4-0697-4238-ADAE-08835D1F8D3D.png

分別復制一份拷貝到另外一個可見的文件夾(如/Users/Shared/Jenkins/Library/)下,以確保可以顯示在上傳彈出框中,以用來上傳。拷貝后的結構,如圖:

71EAB25A-689E-4F8D-BD09-F060C6EFD185.png

③、了解文件上傳后,會被放到什么位置。答:上傳的文件將會被放到/Users/Shared/Jenkins/Home/kpp_upload下。

舉例
如上傳前:


上傳前.png

點擊“選取文件”按鈕,彈出上傳文件框,分別選取自己的keychain和證書。點擊upload進行上傳。


image.png

上傳后:
上傳后.png
④、開始正式上傳鑰匙串login.keychain(是因為鑰匙串中包含簽名的證書?),上傳過程中需正確設置它的Code Signing Identity填寫
616DA338-53DE-4D89-A5A6-4EC00B80C51D.png

這里添加login.keychain的時候要填寫的Code Signing Identity是什么呢,它的值又是從哪來呢?答如下圖:


Code Signing Identity的值從這來.png
⑤、正式上傳描述文件Provisioning Profiles,上傳過程中需正確設置它的Provisioning Profiles Directory Path。

說明:在項目中配置.mobileprovision文件后,執行構建,其會從我們這里填寫的路徑里找以該文件的UUID為文件名的.mobileprovision文件。所以該路徑的作用是讓構建的時候來查找的。

所以,這里我們填寫上面系統描述文件被復制到的路徑,即/Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profiles

完善Provisioning Profiles的Provisioning Profiles Directory Path的填寫.png

附:如果未填寫會出現如下錯誤:
FATAL: The path to store mobile provisioning profile files on the master is not configured. Go the plugin main configuration page and give the path.

Provisioning Profiles的Provisioning Profiles Directory Path未填寫而導致的錯誤.png

所以,我們必須得確保我們填的那個目錄下有以該文件的UUID為文件名的.mobileprovision文件。要不然會出現如下錯誤
FATAL: Failed to copy /Users/Shared/Jenkins/Home/kpp_upload/com.dvlproad.CJUIKitDemo.mobileprovision to /Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profiles/9265146f-df67-4c87-9136-22b09dbfa47b.mobileprovision java.nio.file.AccessDeniedException: /Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profiles/9265146f-df67-4c87-9136-22b09dbfa47b.mobileprovision

60A2C9FB-6C78-45D0-844D-5CE4FD9CEC4F.png

這里雖然提示我們是copy失敗,但是實際上/Users/Shared/Jenkins/Home/kpp_upload下的文件只是用于配置的時候選擇使用,并不會真的執行Copy使其到我們填的那個目錄里。所以,還是那句話,必須得確保我們填的那個目錄下有以該文件的UUID為文件名的.mobileprovision文件。否則會出現錯誤。

五、配置構建方式(這里我們選擇Xcode構建方式)

所需進行的配置項有

配置構建方式所需進行的配置項.png

1、配置構建方式之General build settings選項

①、了解 General build settings 選項需要配置的大概內容,結論是:這里我們需要配置Development Team ID,如果是xcworkspace,還必須在此設置Xcode Schema File。

該選項需要配置的大概內容,如圖:


image.png
②、如何獲取 Development Team ID ,以用來配置 Code signing & OS X keychain options 選項。

Development Team ID如何獲取的方式為可在Keychain找到開發者證書iPhone Distribution: **** (329***),括號內的就是Team ID。舉例如下圖:

Development Team ID的獲取.png
③、為 Code signing & OS X keychain options 選項配置Development Team ID。

即在 構建->Code signing & OS X keychain options,中的Development Team ID輸入Development Team ID。如下圖:


輸入Development Team ID.png

如果未配置則會在構建的時候出現
FATAL: No global development team or local team ID was configured.問題,如圖

448A351B-9543-4A0A-9CCD-5EFF1EA7C252.png

④、獲取mobileprovision文件的UUID

在Terminal下輸入下面的命令并回車::

curl https://raw.githubusercontent.com/0xc010d/mobileprovision-read/master/main.m | clang -framework Foundation -framework Security -o /usr/local/bin/mobileprovision-read -x objective-c -

這條命令的作用是下載mobileprovision-read的源碼,然后編譯,最后把生成的二進制文件mobileprovision-read放入到/usr/local/bin/路徑下。

查看UUID的命令是:

mobileprovision-read -f test.mobileprovision-o UUID

測試可用。

詳情查看:命令行獲取mobileprovision文件的UUID

從apple網下載的描述文件通過本命令可查看到該UUID,通過進入描述文件的系統存放路徑/Users/lichaoqian/Library/MobileDevice/Provisioning Profiles可以檢驗該UUID的描述文件有沒有被添加進來。

2、配置構建方式之Code signing & OS X keychain options選項

image.png

如果為Unlock Keychain,則會出現如下錯誤
......
.....(省略號代表省略很多)
/Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app: errSecInternalComponent
Command /usr/bin/codesign failed with exit code 1

** BUILD FAILED **

The following build commands failed:
CodeSign /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app
(1 failure)
Build step 'Xcode' marked build as failure
Finished: FAILURE

3、配置構建方式之Advanced Xcode build options選項

Jenkins Xcode新版本

ia

以下是舊版本的
需要設置的選項有如下圖兩處,如果未設置,或者設置成下圖這樣子會造成錯誤

Advanced Xcode build options設置錯誤.png
所以,配置`Advanced Xcode build options`我們需要
①、配置項目文件`Xcode Workspace File`(必須)
②、配置`Xcode Schema File`(必須)
③、配置`Build output directory`(可填默認的 `${WORKSPACE}/build`)
①、配置項目文件Xcode Workspace File

上圖的錯誤1:使用用cocoapods時候,Workspace File因多填寫了個后綴名而造成了找不到文件的錯誤

使用用cocoapods時候,Workspace File因多填寫了個后綴名而造成了找不到文件的錯誤.png

Xcode Workspace File的正確填寫
這里Xcode Workspace File 填寫就不多說了,填的是xcworkspace文件所在的目錄,所以這里去掉后綴名即可,
即最后為$WORKSPACE/CJUIKitDemo/CJUIKit

②、配置Xcode Schema File

上圖的錯誤2:使用用cocoapods時候,Schema File未填寫而造成的錯誤

使用用cocoapods時候,Schema File未填寫而造成的錯誤.png

Xcode Schema File的正確填寫
Xcode Schema File的填寫一般也為項目名,具體可自己查看Schema。

Xcode Schema File 填寫了,但填寫錯誤的常見情況
如果發現補充填寫完后,還是有問題,如發現有如下問題,如圖:

40348F8F-C546-46F8-90C5-6CB8F069B2F6.png

即錯誤為xcodebuild: error: The workspace named "CJUIKitDemo" does not contain a scheme named "CJUIKitDemo".這是因為沒找到指定scheme引起。工程代碼提交時,未將.xcodeproj中的xcschemes提交。

解決辦法:將Manage Scheme后面工程的分享框勾上即可。

5209490F-E95E-403B-AFCE-2C47420C28D3.png

勾選Shared后,在.xcodeproj中就會產生xcshareddata目錄

A2B8198C-F2FE-48B5-BC21-2BAE195F5683.png

隨后,將xcshareddata目錄提交到SVN/Git上,重新構建即可。(補充:.xcodeproj中的xcuserdata目錄可不提交到SVN/Git上,因為這個目錄是臨時生成的,沒什么用。)

③、配置Build output directory(可填默認的 ${WORKSPACE}/build

=== BUILD TARGET MBProgressHUD OF PROJECT Pods WITH CONFIGURATION Release ===

Check dependencies

CreateUniversalBinary /Users/lichaoqian/Project/jenkinsWorkspace/Release-iphoneos/MBProgressHUD/libMBProgressHUD.a normal armv7\ arm64
cd /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/CJUIKitDemo/Pods
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/CJUIKitDemo-gqrgqeoigrvayahkawwllwksjemk/Build/Intermediates.noindex/Pods.build/Release-iphoneos/MBProgressHUD.build/Objects-normal/armv7/libMBProgressHUD.a /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/CJUIKitDemo-gqrgqeoigrvayahkawwllwksjemk/Build/Intermediates.noindex/Pods.build/Release-iphoneos/MBProgressHUD.build/Objects-normal/arm64/libMBProgressHUD.a -o /Users/lichaoqian/Project/jenkinsWorkspace/Release-iphoneos/MBProgressHUD/libMBProgressHUD.a
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't create output file: /Users/lichaoqian/Project/jenkinsWorkspace/Release-iphoneos/MBProgressHUD/libMBProgressHUD.a (No such file or directory)

=== BUILD TARGET CJFile OF PROJECT Pods WITH CONFIGURATION Release ===

Check dependencies
.......
(以下省略,直接跳到結果)
.......
** BUILD FAILED **

The following build commands failed:
CreateUniversalBinary /Users/lichaoqian/Project/jenkinsWorkspace/Release-iphoneos/MBProgressHUD/libMBProgressHUD.a normal armv7\ arm64
CreateUniversalBinary /Users/lichaoqian/Project/jenkinsWorkspace/Release-iphoneos/CJFile/libCJFile.a normal armv7\ arm64
(2 failures)
Build step 'Xcode' marked build as failure
Finished: FAILURE

從描述中的error:可知是我們在Build output directory中填寫/Users/lichaoqian/Project/jenkinsWorkspace 錯了。將其改為默認的 ${WORKSPACE}/build重新構建即可解決本錯誤。
附:此操作會在該項目中創建一個build目錄存放編譯的輸出內容,如圖:

image.png

如此,基本大部分的問題都已解決了。

構建成功的樣子為

Check dependencies

=== BUILD TARGET Pods-CJUIKitDemo OF PROJECT Pods WITH CONFIGURATION Release ===

Check dependencies

=== BUILD TARGET CJUIKitDemo OF PROJECT CJUIKitDemo WITH CONFIGURATION Release ===

Check dependencies

Validate /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app
cd /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/CJUIKitDemo
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
export PRODUCT_TYPE=com.apple.product-type.application
builtin-validationUtility /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app

** BUILD SUCCEEDED **

Finished: SUCCESS

此時你去上面的路徑/Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app中即可看到有.app生成了。

六、ipa的輸出

上面只是BUILD SUCCEEDED,要輸出ipa還要打開Pack application, build and sign .ipa?,該選項按默認即可。

image.png

但是如果只是單純的打開,就去構建會出現如下錯誤:

Touch /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app.dSYM
cd /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/CJUIKitDemo
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/usr/bin/touch -c /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app.dSYM

** ARCHIVE SUCCEEDED **

Cleaning up previously generated .ipa files
Cleaning up previously generated .dSYM.zip files
Packaging IPA
[CJUIKitDemo] /usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleVersion" /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/CJUIKitDemo.xcarchive/Info.plist [CJUIKitDemo] /usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleShortVersionString" /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/CJUIKitDemo.xcarchive/Info.plist
Packaging CJUIKitDemo.xcarchive => /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/CJUIKitDemo-1.0-1.ipa
[CJUIKitDemo] $ /usr/bin/xcodebuild -exportArchive -archivePath /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/CJUIKitDemo.xcarchive -exportPath /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build -exportOptionsPlist /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/ad-hocFZ5YDHE5JZExportOptions.plist -allowProvisioningUpdates
2018-06-21 02:14:51.320 xcodebuild[7671:202008] [MT] IDEDistribution: -[IDEDistributionLogging _createLoggingBundleAtPath:]: Created bundle at path '/var/folders/4j/wvf5xqh93631jch00c4qwkrw00008b/T/CJUIKitDemo_2018-06-21_02-14-51.316.xcdistributionlogs'.
2018-06-21 02:14:51.863 xcodebuild[7671:202008] [MT] IDEDistribution: Step failed: <IDEDistributionSigningAssetsStep: 0x7f879484e5d0>: Error Domain=IDEDistributionSigningAssetStepErrorDomain Code=0 "Locating signing assets failed." UserInfo={NSLocalizedDescription=Locating signing assets failed., IDEDistributionSigningAssetStepUnderlyingErrors=(
"Error Domain=IDEProvisioningErrorDomain Code=9 ""CJUIKitDemo.app" requires a provisioning profile." UserInfo={NSLocalizedDescription="CJUIKitDemo.app" requires a provisioning profile., NSLocalizedRecoverySuggestion=Add a profile to the "provisioningProfiles" dictionary in your Export Options property list.}"
)}
error: exportArchive: "CJUIKitDemo.app" requires a provisioning profile.

Error Domain=IDEProvisioningErrorDomain Code=9 ""CJUIKitDemo.app" requires a provisioning profile." UserInfo={NSLocalizedDescription="CJUIKitDemo.app" requires a provisioning profile., NSLocalizedRecoverySuggestion=Add a profile to the "provisioningProfiles" dictionary in your Export Options property list.}

** EXPORT FAILED **

Failed to build /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/CJUIKitDemo-1.0-1.ipa
Build step 'Xcode' marked build as failure
Finished: FAILURE

六、構建過程中的其他問題

No profiles for 'com.dvlproad.CJUIKitDemo' were found: Xcode couldn't find a provisioning profile matching 'com.dvlproad.CJUIKitDemo'. Code signing is required for product type 'Application' in SDK 'iOS 10.3'

0CB98B45-021E-45CF-B692-40E479BE6331.png

其他參考:[iOS 通過Jenkins 自動構建ipa]
搭建iOS自動化打包平臺(利用Jenkins持續集成iOS項目)
學會使用 Jenkins 搭建 iOS 持續集成環境
Jenkins

七、常見問題參考

Jenkins整合XCode詳解
Jenkins問題

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容