后續(xù)文章:Jenkins二:參數(shù)化構(gòu)建iOS自動(dòng)打包
快捷記錄:如果jenkins是用dmg安裝,因?yàn)闄?quán)限問題不能訪問keychain時(shí),每次新添加一個(gè)p12文件都要如此,
/Users/管理員用戶名/Library/keychains/login.keychain-db
將login.keychain-db復(fù)制一份并命名為login.keyain復(fù)制到
/Users/Shared/Jenkins/Library/Keychains/login.keychain
同時(shí)要在
前言 :
因團(tuán)隊(duì)發(fā)展涉及到需要把打包工作配置好自動(dòng)打包后移交給測(cè)試團(tuán)隊(duì),網(wǎng)上資料很多,找了幾篇文章在我自己的MacBook Pro上跟著一步步安裝下來,雖然也遇到幾個(gè)問題,但很快就找到了解決方案最后成功自動(dòng)打包成功,于是就在一臺(tái)專門的打包電腦Mac mini上安裝環(huán)境,因?yàn)槎际请S機(jī)在網(wǎng)上找的資料,結(jié)果兩次安裝環(huán)境步驟稍微不一樣,第一次是使用
homebrew安裝的,安裝在默認(rèn)賬戶下,沒遇到什么權(quán)限問題,第二次在mac mini上安裝使用的是安裝包的方式,遇到一系列問題,大部分問題跟權(quán)限有關(guān)。陸陸續(xù)續(xù)查找解決構(gòu)建了200多次,持續(xù)了2個(gè)周
參考資料:
強(qiáng)烈建議使用homedrew安裝會(huì)省卻很多權(quán)限問題,如果用pkg安裝包安裝,會(huì)被權(quán)限問題折騰掉半條命
強(qiáng)烈建議二:通過在做Master-Slave配置節(jié)點(diǎn)打包時(shí)發(fā)現(xiàn)使用Tomcat里安裝war包的方式安裝Jenkins的方式更方便快捷
Jenkins十:Mac通過 Tomcat里安裝Jenkins配置Master-Slave打包iOS并上傳到svn服務(wù)器
一、安裝jenkins
前提條件:已經(jīng)安裝homedrew、Java
- Mac終端軟件安裝利器:Homebrew
-
如何在mac上安裝java1.8
通過homedrew安裝jenkins命令
brew install jenkins
通過homedrew安裝后jenkins安裝好后所在的位置:
實(shí)際安裝位置:/usr/local/Cellar/jenkins/
配置文件所在位置:/usr/local/opt/jenkins/
工作空間位置:/Users/用戶/.jenkins
進(jìn)入工作空間位置:cd ~/.jenkins
二、設(shè)置開機(jī)自啟動(dòng):
方式一、將啟動(dòng)plist在LaunchAgents創(chuàng)建一個(gè)鏈接鏡像(ln是創(chuàng)建一個(gè)link的意思)
1.1,創(chuàng)建一個(gè)鏈接到開機(jī)啟動(dòng)文件家里
ln -sfv /usr/local/opt/jenkins/*.plist ~/Library/LaunchAgents
1.2:手動(dòng)啟動(dòng)jenkins
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.jenkins.plist
1.3 手動(dòng)關(guān)閉jenkins
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.jenkins.plist
1.4 根據(jù)需求修改jenkins的啟動(dòng)端口,修改/usr/local/Cellar/jenkins/2.149/homebrew.mxcl.jenkins.plist即可
修改后重新啟動(dòng)可能會(huì)報(bào)如下錯(cuò)誤:
/usr/local/Cellar/jenkins/2.149/homebrew.mxcl.jenkins.plist: Path had bad ownership/permissions
執(zhí)行以下的兩個(gè)命令行:
sudo chown root /usr/local/Cellar/jenkins/2.149/homebrew.mxcl.jenkins.plist
sudo chgrp wheel /usr/local/Cellar/jenkins/2.149/homebrew.mxcl.jenkins.plist
方式二(缺點(diǎn):執(zhí)行shell的termenal一直在前臺(tái)運(yùn)行,不小心關(guān)掉了就會(huì)停止,有強(qiáng)迫癥愛干凈的人也不喜歡多一個(gè)不能關(guān)掉的termenal窗口)
添加一個(gè)啟動(dòng)執(zhí)行的shell文件
2.1:在/usr/local/opt/jenkins創(chuàng)建一個(gè)jenkinsBoot.sh文件,內(nèi)容如下
#!/bin/sh
#默認(rèn)是8080端口,這里指定為8888端口啟動(dòng)
jenkins --httpPort=8888
2.2:打開系統(tǒng)偏好設(shè)置->用戶與群組->當(dāng)前管理員->登錄項(xiàng)->+將/usr/local/opt/jenkins/jenkinsBoot.sh加入到這里來
常用默認(rèn)參數(shù):${WORKSPACE}、${HOME}
查找正在運(yùn)行的jenkins并關(guān)閉:
#查找正在運(yùn)行的jenkins服務(wù),查看jenkins.war那一行的端口號(hào)
ps -ef | grep jenkins
501 82363 22132 0 12:33PM ttys000 0:00.00 grep jenkins
501 926 855 0 Fri06PM ttys002 0:00.00 /bin/sh /usr/local/Cellar/jenkins/2.149/jenkinsBoot.sh
501 xxxx 926 0 Fri06PM ttys002 6:58.53 /usr/bin/java -jar /usr/local/Cellar/jenkins/2.149/libexec/jenkins.war
#關(guān)閉jenkins.war那一行的端口號(hào)對(duì)應(yīng)的服務(wù)
kill -int xxxx
應(yīng)注意一個(gè)讀者在配置jenkins環(huán)境時(shí),配置keychain時(shí)的問題
說明:要jenkins打包iOS的ipa需要蘋果系統(tǒng)支持,也就是說安裝jenkins的機(jī)器是蘋果系統(tǒng)或能用jenkins配置一臺(tái)能訪問的蘋果系統(tǒng)的電腦作為master機(jī)器(本文以默認(rèn)jenkins所在的機(jī)器就是蘋果系統(tǒng))
1、下載發(fā)布證書或從開發(fā)人員那里拿到導(dǎo)出的發(fā)布證書p12
-
一個(gè)蘋果證書怎么多次使用——導(dǎo)出p12文件
雙擊安裝證書后,jenkins所在的機(jī)器就有發(fā)布證書了
login.keychain位置:
/Users/管理員用戶名/Library/keychains/login.keychain-db
將login.keychain-db復(fù)制一份并命名為login.keyain
描述文件位置:
/Users/管理員用戶名/Library/MobileDevice/Provisioning Profiles
(不建議從這里找,因?yàn)樯蟼鬟@里的描述文件之后看到的標(biāo)題也是UUID格式,所以最好單獨(dú)上傳從蘋果開發(fā)網(wǎng)站下載的描述文件,或者把下面的描述證書拷貝出來改個(gè)名再上傳)
2、將證書上傳到j(luò)enkins里
將1中復(fù)制的login.keychain上傳到這里,如下圖所示,
identities:找keychain里這個(gè)發(fā)布證書的內(nèi)容


【Mac】解決jenkins執(zhí)行shell腳本等場(chǎng)景中遇見的權(quán)限不足問題
******以上解決權(quán)限問題的方式會(huì)有異常問題,不能這樣做
實(shí)際的過程,以要使用git為例
#1、切換到j(luò)enkins用戶下
#[mac終端切換用戶](https://blog.csdn.net/doudou19930614/article/details/81410823)
su - Jenkins
#2、創(chuàng)建一個(gè)文件夾
mkdir xxx
#3、clone對(duì)應(yīng)的git
git clone xxxxxx
#4、為了不用在每次push到GitHub上時(shí)都輸入用戶名密碼
#[mac下git push避免每次都輸入用戶名和密碼的配置](https://www.cnblogs.com/zhaoshunjie/p/6306927.html)
#5、如果有提示需要輸入全局的賬號(hào)和郵箱
# 設(shè)置提交代碼時(shí)的用戶信息
git config --global user.name "[name]"
git config --global user.email "[email address]"
#后續(xù)其他以jenkins賬號(hào)操作都正常了
一、使用Jenkins自動(dòng)打iOS安裝包前提條件
1、Mac OS系統(tǒng)(我所使用的是MacBook Pro 和Mac mini)
2、Xcode
3、cocoapods(非必須,如果使用cocoapod管理第三方庫才需要)
4、Java
5、sourcetree(git管理工具非必須,我主要用來看代碼有沒有問題)
6、cornerstone(svn管理工具非必須,我主要用來講打包的ipa文件上傳到SVN上,而不是通常的放到第三方服務(wù)器)
7、Jenkins(homebrew安裝方式和安裝包安裝方式兩種)
二、使用Jenkins安裝包安裝方式遇到的問題
1、提示
Failed to connect to repository : Command "git -c core.askpass=true ls-remote -h git@XXXXX:XXXX/XXXX.git HEAD" returned status code 128:
image.png
原因:
由于使用Jenkins安裝包安裝,不能直接使用http的方式為git地址(why?),需要切換成ssh地址,ssh地址需要配置秘鑰
解決辦法:
配置ssh秘鑰參考文章解決在Mac下搭建Jenkins+GitLab持續(xù)集成環(huán)境踩到的坑(一)
2、提示
Code Signing Error: No certificate for team 'xxxxx' matching 'iPhone Distribution: xxxxx.' found: Select a different signing certificate for CODE_SIGN_IDENTITY, a team that matches your selected certificate, or switch to automatic provisioning.
原因:
由于使用Jenkins安裝包安裝,在安裝時(shí)創(chuàng)建了一個(gè)新的用戶,默認(rèn)放在鑰匙串里的證書Jenkins這個(gè)用戶訪問不了
解決辦法:
將鑰匙串下的 登錄里的相關(guān)證書拷貝到 鑰匙串下的 系統(tǒng)里面
3、提示
Run custom shell script '[cp] embed pods frameworks ..... errSecInternalComponent.
/usr/bin/codesign --force --sign DC8791E5F036D9BAAFEC8E347093A20EB435BF0F --preserve-metadata=identifier,entitlements '/Users/Shared/Jenkins/Home/workspace/iOSDev/Release-iphoneos/xxx.app/Frameworks/AFNetworking.framework'
/Users/Shared/Jenkins/Home/workspace/iOSDev/Release-iphoneos/xxx.app/Frameworks/AFNetworking.framework: errSecInternalComponent
Command /bin/sh failed with exit code 1
** BUILD FAILED **
The following build commands failed:
PhaseScriptExecution [CP]\ Embed\ Pods\ Frameworks /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/Lottery-dubolgbhbwxukkfsjmthrywdixge/Build/Intermediates.noindex/Lottery.build/Release-iphoneos/xxx.build/Script-79402CD10148DF169F37FF35.sh
(1 failure)
Build step '執(zhí)行 shell' marked build as failure
[OS X] restore keychains as defined in global configuration
[iOSDev] $ /usr/bin/security list-keychains -s /Users/Shared/Jenkins/Library/Keychains/login.keychain
Finished: FAILURE
image.png
原因一:
看了一篇文章Run custom shell script '[cp] embed pods frameworks ..... errSecInternalComponent,按著里面的操作后并沒解決問題,
解決辦法:
看到--force --sign的字樣猜測(cè)還是權(quán)限的問題,于是我把拷貝到鑰匙串->系統(tǒng) 下的那個(gè)證書設(shè)置為 始終信任,順利解決問題
如果還不可以則:
在xcodebuild -workspace .....前添加一行解鎖login.keychain的命令
security unlock-keychain -p 個(gè)人的賬號(hào)登錄密碼 /Users/Shared/Jenkins/Library/Keychains/login.keychain
原因二:
在要用一個(gè)新appleID開發(fā)者賬號(hào)創(chuàng)建一個(gè)新target時(shí),電腦的login.kechain-db已經(jīng)重新生成或者說修改了,但之前配置在Jenkins里的還是舊的,所以需要重新將login.keychain-db復(fù)制一份并重命名為login.kehchain上傳到Jenkins里忘了在Jenkins配置時(shí)Keychains and Provisioning Profiles Management->Keychains
,同時(shí)將login.keychain-db、login.keychain拷貝到Jenkins的對(duì)應(yīng)目錄下,我的目錄為:/Users/xxxx/Library/Keychains -> /Users/Shared/Jenkins/Library/Keychains
4、提示
xcrun: error: unable to find utility "PackageApplication", not a developer tool or in PATH
原因:
新版的Xcode里沒有想過的工具庫
解決辦法:
參考:xcrun: error: unable to find utility "PackageApplication", not a developer tool or in PATH
順便由于提示warning: PackageApplication is deprecated, use ``xcodebuild -exportArchive`` instead.,這個(gè)根據(jù)提示替換修改下就好了
5、提示
Build step '執(zhí)行 shell' marked build as failure
[OS X] restore keychains as defined in global configuration
原因:
Jenkins用戶權(quán)限比較低,不能使用login.keychain
解決辦法:
在xcodebuild -workspace .....前添加一行解鎖login.keychain的命令
security unlock-keychain -p 個(gè)人的賬號(hào)登錄密碼 /Users/Shared/Jenkins/Library/Keychains/login.keychain
6、提示
=== BUILD TARGET xxxx OF PROJECT Lottery WITH CONFIGURATION Release ===
Check dependencies
Code Signing Error: "xxxx" requires a provisioning profile with the Push Notifications feature. Select a provisioning profile for the "Release" build configuration in the project editor.
Code Signing Error: Code signing is required for product type 'Application' in SDK 'iOS 11.4'** BUILD FAILED **
原因一:
該target的build setting配置不正確,之前是將Code Signing Identity統(tǒng)一配置成iOS Distribution了,這種方式在xcode里手動(dòng)點(diǎn)擊archive打包時(shí)沒問題,但使用Jenkins自動(dòng)打包就出報(bào)上面的錯(cuò)

解決辦法:
將報(bào)錯(cuò)的這個(gè)target的build setting設(shè)置為精確的描述證書,比如iPhone Distribution: xxxxx,如下圖:

另外之前查找資料時(shí)發(fā)現(xiàn)一些相關(guān)的資料,但沒有解決我的問題
Jenkins+XCode9自動(dòng)打包錯(cuò)誤處理
最全Jenkins+SVN+iOS+cocoapods環(huán)境搭建及其錯(cuò)誤匯總
7、提示
error: Unable to create '/Users/admin/Documents/svn/docs/xxxx.ipa'
原因:
這個(gè)路徑是為了設(shè)置將打包出來的ipa安裝包自動(dòng)放到SVN路徑下然后自動(dòng)上傳到SVN服務(wù)器,但還是由于打包Jenkins用的是一個(gè)獨(dú)立的用戶導(dǎo)致的權(quán)限問題
解決辦法:
將/Users/admin/Documents/svn/docs/這個(gè)路徑的每一個(gè)文件夾都設(shè)置為所有用戶有讀寫權(quán)限
花了兩個(gè)周構(gòu)建幾百次的血的教訓(xùn),建議還是都用homebrew的方式安裝少些權(quán)限問題
end
配置的參數(shù):




完整構(gòu)建腳本:
# 工程名
APP_NAME="xxxx"
#***************動(dòng)態(tài)配置部分*********************
# 不勾上自動(dòng)管理證書
CODE_SIGN_DISTRIBUTION="iPhone Distribution: xxxxx"
# 代碼文件夾名稱,這是由于源碼并不在git項(xiàng)目的根目錄下
code_folder="xxxx"
#scheme#Info文件名稱#保存ipa文件夾
platformParams=(${iOS_PLATFORM//\#/ })
# schema名稱
SCHEMECA=${platformParams[0]}
#info.plist文件名稱
INFO_FILENAME=${platformParams[1]}
# 輸出到svn的文件夾名稱
OUT_SVN_FOLDER=${platformParams[2]}
#*************************************
project_path=""
project_infoplist_path="./${code_folder}/Resource/platforms/${INFO_FILENAME}.plist"
#取版本號(hào)
bundleShortVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleShortVersionString" "${project_infoplist_path}")
#取build值
bundleVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleVersion" "${project_infoplist_path}")
#取bundleId
bundleId=$(/usr/libexec/PlistBuddy -c "print CFBundleIdentifier" "${project_infoplist_path}")
DATE="$(date +%Y%m%d-%H%M%S)"
#唯一名稱ipa、dsYM文件名
UNIQUE_NAME="${APP_NAME}_${SCHEMECA}_${iOS_Release}_V${bundleShortVersion}_${DATE}"
IPANAME="${UNIQUE_NAME}.ipa"
#根據(jù)需求定義輸入ipa的文件夾位置
PARENT_FOLDER="$HOME/testJenkins/test/study/${OUT_SVN_FOLDER}"
if [ ! -d $PARENT_FOLDER ];then
mkdir -p $PARENT_FOLDER
else
echo dir exist
fi
#要上傳的ipa文件路徑
IPA_PATH="$PARENT_FOLDER/${IPANAME}"
echo ${IPA_PATH}
echo "${IPA_PATH}">> text.txt
#下面2行是沒有Cocopods的用法
#echo "=================clean================="
#xcodebuild -target "${TARGET_NAME}" -configuration 'Release' clean
#
#echo "+++++++++++++++++build+++++++++++++++++"
#xcodebuild -target "${TARGET_NAME}" -sdk iphoneos -configuration 'Release' CODE_SIGN_IDENTITY="${CODE_SIGN_DISTRIBUTION}" SYMROOT='$(PWD)'
#下面2行是集成有Cocopods的用法
echo "=================clean================="
xcodebuild -workspace "./${code_folder}/${APP_NAME}.xcworkspace" -scheme ${SCHEMECA} -configuration "${iOS_Release}" clean
echo "+++++++++++++++++build+++++++++++++++++"
xcodebuild -workspace "./${code_folder}/${APP_NAME}.xcworkspace" -scheme ${SCHEMECA} -sdk iphoneos -configuration "${iOS_Release}" CODE_SIGN_IDENTITY="${CODE_SIGN_DISTRIBUTION}" SYMROOT='$(PWD)' -allowProvisioningUpdates
xcrun -sdk iphoneos PackageApplication "./${iOS_Release}-iphoneos/${SCHEMECA}.app" -o ${IPA_PATH}
#生成dsYM文件
dsymutil "./${iOS_Release}-iphoneos/${SCHEMECA}.app/${SCHEMECA}" -o "${PARENT_FOLDER}/${UNIQUE_NAME}.app.dSYM"
cd "${PARENT_FOLDER}"
if [ ! -d "${UNIQUE_NAME}.app.dSYM" ];then
echo "沒有可以壓縮的dsYM文件"
else
#壓縮dsYM文件
zip -q -r -m -o "${UNIQUE_NAME}.app.dSYM.zip" "${UNIQUE_NAME}.app.dSYM"
#上傳dsYM文件到解析平臺(tái)
#curl -k "https://api.bugly.qq.com/openapi/file/upload/symbol?app_key=xxxxxx&app_id=xxxxxx" --form "api_version=1" --form "app_id=xxxxxx" --form "app_key=xxxxxx" --form "symbolType=2" --form "bundleId=${bundleId}" --form "productVersion=${bundleShortVersion}" --form "channel=xxx" --form "fileName=${UNIQUE_NAME}.app.dSYM.zip" --form "file=@${UNIQUE_NAME}.app.dSYM.zip" --verbose
fi
# 將生成的ipa上傳到SVN
#cd "/Users/tony/Documents/svn/docs/svn/"
#svn upgrade
#svn add ${IPA_PATH}
#svn commit -m "add test" ${IPA_PATH}
三、使用homebrew安裝方式遇到的問題
自動(dòng)打包實(shí)踐:
一、Jenkins自動(dòng)打包管理,參考教程如下:
手把手教你利用Jenkins持續(xù)集成iOS項(xiàng)目
iOS開發(fā)-自動(dòng)化打包Jenkins集成
jenkins - iOS自動(dòng)化打包分發(fā)
iOS自動(dòng)化打包實(shí)戰(zhàn)(Jenkins)
Jenkins安裝、配置、構(gòu)建、腳本、配置郵箱、上傳fir
Mac下Jenkins+SVN(Git)+Xcode搭建持續(xù)構(gòu)建環(huán)境
Mac jenkins 開機(jī)啟動(dòng)設(shè)置
選擇指定的tag自動(dòng)腳本打包
Confluence-Documention
二、遇到問題
FATAL: String index out of range: 15
java.lang.StringIndexOutOfBoundsException: String index out of range: 15
at java.lang.String.substring(String.java:1963)
at com.sic.plugins.kpp.provider.KPPBaseProvisioningProfilesProvider.removeUUIDFromFileName(KPPBaseProvisioningProfilesProvider.java:171)
at com.sic.plugins.kpp.model.KPPProvisioningProfile.getProvisioningProfileFilePath(KPPProvisioningProfile.java:76)
at com.sic.plugins.kpp.KPPProvisioningProfilesBuildWrapper.copyProvisioningProfiles(KPPProvisioningProfilesBuildWrapper.java:157)
at com.sic.plugins.kpp.KPPProvisioningProfilesBuildWrapper.setUp(KPPProvisioningProfilesBuildWrapper.java:99)
at hudson.model.BuildAbstractBuildExecution.run(AbstractBuild.java:504)
at hudson.model.Run.execute(Run.java:1794)
at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
at hudson.model.ResourceController.execute(ResourceController.java:97)
at hudson.model.Executor.run(Executor.java:429)
Finished: FAILURE
這是因?yàn)楫?dāng)時(shí)沒有在Keychains and Provisioning Profiles Management里面上傳配置文件導(dǎo)致的,
上傳配置文件的方法和上傳login.keychain一樣,
選擇那個(gè)配置文件,點(diǎn)擊upload,
配置文件存在你電腦的
`/Users/‘電腦用戶名稱’/Library/MobileDevice/Provisioning Profiles`目錄下。
xcrun: error: unable to find utility "PackageApplication", not a developer tool or in PATH
后面根據(jù)對(duì)比發(fā)現(xiàn)新版的Xcode少了這個(gè)PackageApplication
先去找個(gè)舊版的Xcode里面copy一份過來
放到下面這個(gè)目錄:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/
然后執(zhí)行命令
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer/
再執(zhí)行
chmod +x /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication
最后附上PackageApplication下載地址:
https://pan.baidu.com/s/1jHJF2Lo
遇到問題
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_XXXX", referenced from:
objc-class-ref in XXXX.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
** BUILD FAILED **
原因:
當(dāng)前target沒有把XXXX這個(gè)文件的.m文件沒有勾選到Target MemberShip中
這種問題特別容易出現(xiàn)在一個(gè)項(xiàng)目有多個(gè)target的時(shí)候
如下:

解決辦法:
將提示的文件勾選到
Target MemberShip中
問題:
Warning: unable to build chain to self-signed root for signer "iPhone Distribution: "/Users/Shared/Jenkins/Home/workspace/xxx/Release-iphoneos/xxx.app/Frameworks/AFNetworking.framework: errSecInternalComponent
Command /bin/sh failed with exit code 1
** BUILD FAILED **
如果沒有這個(gè)插件,先安裝插件
Jenkins->Jenkins管理->插件管理->可選插件 輸入:Keychains and Provisioning Profiles Management,找到這個(gè)插件,然后點(diǎn)擊直接安裝

原因:
忘記把新添加的p12證書對(duì)應(yīng)的Identity添加到Jenkins->系統(tǒng)管理->Keychains and Provisioning Profiles Management->Add code Signing Identity里,

點(diǎn)擊:選取文件->Upload->保存
依次將Jenkins所在的機(jī)器的login.keychain(/Users/管理員用戶名/Library/keychains/login.keychain-db 復(fù)制一份改名成成login.keychain),
需要管理的描述文件xxx.mobileprovision上傳保存
Mac 開啟Apache服務(wù)器及PHP環(huán)境
Mac下配置Apache服務(wù)器
搭建企業(yè)賬號(hào)ipa包分發(fā)下載平臺(tái)
Mac中開啟Apache的Https功能
Mac Security工具使用總結(jié)find-identity

