目錄
一、什么是持續集成?
二、我們為什么要用持續集成?
三、安裝環境配置
四、iOS 項目配置
五、Android 項目配置
六、寫在最后
一、什么是持續集成?
持續集成指的是頻繁主動的將代碼集合并到代碼倉庫當中,方便產品保持高質量的快速迭代。持續集成的好處主要有:
1)快速發現錯誤。每完成一點更新,就集成到主干,可以快速發現錯誤,定位錯誤也比較容易。
2)防止分支大幅偏離主干。如果不是經常集成,主干又在不斷更新,會導致以后集成的難度變大,甚至難以集成。
在一次的集成都必須通過自動化的構建(包括編譯、打包、發布、自動化測試等)來驗證,從而盡早的發現集成當中的錯誤。
與持續集成相關的,還有兩個概念,分別是持續交付和持續部署:
持續交付(Continuous delivery)指的是,頻繁地將軟件的新版本,交付給質量團隊或者用戶,以供測試。如果測試通過,代碼就進入生產階段。
持續部署(continuous deployment)是持續交付的下一步,指的是代碼通過評審以后,自動部署到生產環境。
二、我們為什么要用持續集成?
團隊中目前最大的痛點就是開發的時間被碎片化。隨著產品種類越來越多,也冒出來了各種各樣的測試Case,特定的環境、特定的跳轉、特定的需求,開發同學在打包上花費的時間也是越來越多。任務經常性的被打斷,還有可能分心導致代碼質量的下降等等。為了解決這種問題,我們打算為內部同學提供一套簡單自動的開發者環境,引入了Jenkins 持續集成。前期主要的目的就是提供一套可以動態配置常用參數、自動構建安裝包、自動分發下載的平臺。后期會接入QA 相關的自動化測試、靜態代碼檢測,安裝包內也會加大對開發者功能的支持。
三、安裝環境配置
由于要支持iOS 與Android 兩種不同系統,最終選擇Mac 系統當做服務器系統,版本10.12.4。Jenkins 版本2.46.2,這里就不贅述Jenkins 的安裝方法與登錄方法了。
以下列舉了目前使用到的Jenkins 插件和版本號,吐槽一下,配置過程中發現有些以前教程里的插件現在根本搜不到,無奈只能用其他方式解決:
Android Emulator Plugin ? ? ? ? ? ? ? ? ? ?2.15
Android Lint Plugin ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2.4
build-name-setter ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1.6.5
description setter plugin ? ? ? ? ? ? ? ? ? ? 1.10
GitHub Organization Folder Plugin ? ? 1.6
Gitlab Hook Plugin ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1.4.2
GitLab Plugin ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1.4.5
Global Post Script Plugin ? ? ? ? ? ? ? ? ? ?1.1.3
Gradle Plugin ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1.26
Keychains and Provisioning Profiles Management ? ? ? ? ?1.0.0
Publish Over FTP ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1.12
Xcode integration ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1.4.11
四、iOS 項目配置
這里最主要使用的兩個Jenkins 插件是Xcode integration和Keychains and Provisioning Profiles Management。
1. 配置Keychains and Provisioning Profiles Management
安裝好本插件后,進入Jenkins--系統管理會多出來一個“Keychains and Provisioning Profiles Management” 選項。
首先進行上傳login.keychain 文件,查找地址是
/Users/用戶名/Library/keychains/login.keychain
接下來指定Code Signing Identity,可以從Xcode 里的Signing 選項中或者通過命令行查看login.keychain 內包含的:
security find-identity -p codesigning 地址/login.keychain
比如這里我選擇了正式打包時使用的,
iPhone Distribution: XXXXX (Beijing) Network Technology Co., Ltd (3GEKQMXXXX)
配置Provisioning Profiles 目錄,這里最好將整個開發機上的鑰匙串和配置文件目錄都拷貝到Jenkins/Library 目錄下,
/User/用戶/Library/Keychains
/User/用戶/Library/MobileDevice/Provisioning Profiles
所以配置Jenkins 的Provisioning Profiles Directory Path為:
/Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profiles
3. 配置iOS Jobs
1)新建--構建一個自由風格的軟件項目
2)選中“丟棄舊的構建”,普遍選擇保留3天,30個構建個數。
3)選擇“參數化構建過程”,可根據業務配置動態參數,使用${NAME} 可得到選擇的值。
4)源碼管理選擇Git,填寫Repository URL 代碼倉庫地址,Credentials 新建這里我選擇了username 和password 的方式進行訪問。
這里需要注意下系統Git 的版本號,如果Git 版本低于1.8 可能會一直出現401 權限問題,需要升級Git 版本到1.8 以上。
5)構建觸發器
可以配置定時任務、觸發式任務等,觸發式任務可定期檢測代碼倉庫是否有更新,并自動執行構建操作。配置規則Jenkins 的幫助寫的很詳細,這里就簡單列一下:
第一個參數代表的是分鐘 minute,取值 0~59;
第二個參數代表的是小時 hour,取值 0~23;
第三個參數代表的是天 day,取值 1~31;
第四個參數代表的是月 month,取值 1~12;
最后一個參數代表的是星期 week,取值 0~7,0 和 7 都是表示星期天。
如H/15 * * * * 表示的就是每15分鐘檢查一次源碼變化。
6)構建環境,選中Keychains and Code Signing Identities,Keychain 行選擇之前配置的login.keychain 即可。
彈出的選擇框中可能無法選擇Keychain,這個時候先選中Keychain and Code Singing Identities 選項,先保存一下當前配置,重新進入Jobs 配置頁面就可以正常選擇了。
7)構建
由于要執行pod 和動態參數改變,構建前先執行我們自己的腳本文件。增加構建步驟,選擇Execute shell,注意位置要放在“構建”模塊的第一位。
#bin/bsah - l
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LC_ALL=en_US.UTF-8
cd $WORKSPACE/你的項目文件
/usr/local/bin/pod update --verbose --no-repo-update
#這里可以做一些動態參數的替換,例如:
oldParm="www.baidu.com"
newParm="www.sina.com"
parmSed="sed -i \"\" \"s/$oldParm/$newParm/g\" main.pch"
eval $parmSed
再次增加構建步驟,選擇Xcode 插件。General build settings:
如果當前有Target ,就填寫;我們項目因為用到了Today 插件,不止一個Target,就不填寫。
選中Clean before build?,每次編譯前Clean 一下。
選中Generate Archive?
通過Configuration 可以選擇當前是Release 版本還是Debug 版本。
選中Pack application and build .ipa?,指定生成ipa 包,.ipa filename pattern 包名規則自定義,這里為app_${VERSION}_${BUILD_DATE}。
Output directory 目錄為${WORKSPACE}/build/ ,指定打包后的ipa 文件輸出目錄。
Code signing & OS X keychain options:
選中sign IPA at build time,選中unlock keychain,Keychain Path 填寫${KEYCHAIN_PATH},鑰匙串密碼這里為系統用戶登錄密碼。
Advanced Xcode build options:
配置Xcode Schema File,可以通過Xcode 的Manage Schemas... 查看現有的Schema。
Custom xcodebuild arguments 配置為PROVISIONING_PROFILE=${項目Target_PROVISIONING_PROFILE}。
Xcode Workspace File 配置為${HOME}/Home/workspace/AppForiOS/xxxx,這里指向的是項目的xcworkspace文件,但是在構建過程中Jenkins 會自動追加.xcworkspace 后綴名,填寫時需要注意。注意:這個參數配置了,下面的Xcode Project File 參數配置就無效了。
Xcode Project Directory 配置為包含了xcodeproj 文件的目錄,只需要單獨一個目錄名就可以,這里是相對路徑從$workspace 開始。
Xcode Project File 如果要配置的話指向xcodeproj 文件即可。
Build output directory 輸出指向${WORKSPACE}/build/,這里的輸出不止包括.ipa 安裝包。
8)構建后操作
構建后的流程是上傳至蒲公英后在Jenkins 的構建歷史中顯示下載地址、二維碼等,或者可以FTP 上傳到內部服務器、發送郵件等,根據需求選擇。
增加構建后操作步驟選擇Post build task,勾選Run script only if all previous steps were successful,腳本執行蒲公英上傳功能:
#蒲公英上的User Key
uKey="3f9526ca10b8d43f3fa881b98xxxxx"
#蒲公英上的API Key
apiKey="95f337f90fe42dad8bb84xxxxxxx"
cd build
name="$(find . -maxdepth 1 -name '*.ipa')"
#要上傳的ipa文件路徑
IPA_PATH="${WORKSPACE}/build/$name"
#執行上傳至蒲公英的命令
curl -F "file=@$IPA_PATH" -F "uKey=$uKey" -F "_api_key=$apiKey" https://qiniu-storage.pgyer.com/apiv1/app/upload
再次增加構建后操作步驟,選擇Set build description(注意上下順序),
Regular expression 配置"appQRCodeURL":"(.*)",這里可以根據正則從日志中匹配到想獲得的值,在Description 里使用\1、\2等展示正則匹配的值,這里就自由發揮了。如果要以HTML 的方式(顯示圖片等)展示描述信息,需要將Jenkins--系統管理--Configure Global Security--Markup Formatter 選項改為“Safe HTML”。
4. 配置中的問題
由于Jenkins 是以“Jenkins”用戶的身份進行操作,構建過程中會出現各種的權限問題,我都是比較暴力的直接修改文件的權限進行解決。
構建出現錯誤:xcrun: error: unable to find utility "PackageApplication", not a developer tool or in PATH。
解決方法:發現Xcode 8.3 以后已經廢棄了PackageApplication,所以解決方式就是從舊版上復制一份來使用。
https://pan.baidu.com/s/1kVqP8xx 下載PackageApplication
拷貝至/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ 目錄下
執行命令 sudo xcode-select -switch/Applications/Xcode.app/Contents/Developer/
chmod +x/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication
執行pod 命令時出現ERROR: SSL verification error at depth 1: unable to get local issuer certificate (20)
解決方法:出現這個問題的原因主要是Ruby環境需要2.2版本以上,所以要更新Ruby環境。
1.安裝rvm:$ curl -L get.rvm.io | bash -s stable
2.裝載rvm:$ source ~/.rvm/scripts/rvm
3.安裝2.3.0版本ruby:$ rvm install 2.3.0
4.將2.3.0設為默認:$ rvm use 2.3.0 --default
執行pod 時出現env: ruby_executable_hooks: No such file or directory
解決方法:嘗試升級ruby、嘗試安裝executable_hooks、嘗試修改命令腳本引用、嘗試修改Jenkins 環境變量PATH。
這個卡的時間比較長,也是各種資料查。因為在服務器機器上執行pod,或者配置Path 后終端都可以正常使用,但是在執行Jenkins 構建的時候卻一直失敗。一開始以為是環境版本太低,能升級的都升了。后來還嘗試安裝了executable_hooks(命令sudo gem install --user-install executable-hooks)。嘗試過去修改pod 命令里的引用,直接指到安裝后的ruby 目錄(引用!#/Users/Shared/Jenkins/.rvm/rubies/ruby-2.3.0/bin ruby_executable_hooks)或者修改GEM_PATH(/Users/Shared/Jenkins/.rvm/gems/ruby-2.3.0/environment)等等。最后看到有可能是Jenkins 執行Shell 腳本時的環境與服務器的系統環境不相同,嘗試在Shell 腳本中輸出一些變量值進行觀察,因為對Shell 腳本不是很熟悉,最后去Jenkins--系統管理--系統設置--全局屬性中,新增鍵值對PATH,值指向新版本ruby(/Users/Shared/Jenkins/.rvm/rubies/ruby-2.3.0/bin:$PATH)
五、Android 項目配置
配置好iOS 項目后,再進行Android 的配置就簡單很多,這里主要是對Android 的開發環境進行配置,主要使用的Jenkins 插件是Gradle Plugin。
1. 環境配置
Jenkins--系統管理--系統設置
選中Environment variables,新增鍵值對ANDROID_HOME,指向Android 的SDK目錄。
Jenkins--系統管理--Global Tool Configuration
Gradle 安裝,隨便起一個Gradle 配置名稱,GRADLE_HOME 配置/Applications/Android Studio.app/Contents/gradle/gradle-x.x。
2. Jobs 配置
其他部分與iOS 配置類似,只需要增加構建步驟從Xcode 切換成Invoke Gradle script 插件,
選中Invoke Gradle,Gradle Version 選擇剛才已經配置好的Gradle 名稱。
Task 任務內填入clean build,表示執行clean 和build 兩個操作。這里需要注意build 操作會將項目中build.gralde 配置文件中buildTypes 下所有的配置都執行一遍,第一次時沒有注意就執行了build,結果10+個配置一共執行了45分鐘。如果想打單獨配置的包,填入assemblerelease 包,根據buildTypes 內的定義即可。
Root Build script,配置${workspace}/app/,這里指向的是項目使用的build.gradle 文件目錄。如果build.gradle 文件就在項目根目錄,則不用填寫。
Post build task,增加APK 簽名命令,jarsigner -verbose -keystore keystore地址 -signedjar 簽名后的文件名 -digestalg SHA1 -sigalg MD5withRSA 未簽名的安裝包地址 keystore的alias -storepass keystore的密碼
3. 配置中的問題
Jenkins構建Android 出現/Users/Shared/Jenkins/.android/analytics.settings(No such file or directory)
解決:創建.android 目錄
SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID_HOME environment variable
解決:項目中缺少local.properties文件,主動創建,填寫內容sdk.dir=“sdk目錄”
Jenkins A problem occurred configuring project‘:app’. > The SDK directory‘/User/用戶/Library/Android/sdk' does not exist
解決:將改目錄的權限全部設置成了777
六、寫在最后
目前只是實現了簡單的基礎功能,發現坑確實不少,但不得不說Jenkins 的日志真的很詳細,定位問題很方便。以上就是Jenkins 的一些經驗,特此記錄總結一下。
參考鏈接
阮一峰 http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html
七、補充匯總
在新復制一個帶有“Git Parameter”插件的項目后,點擊“Build with Parameters” 時,選擇分支的選擇框內提示“null Please look at the log”。
解決:由于在Jenkins workspace 目錄下沒有任何相關的代碼,只需要直接進行構建,拉取一次遠程代碼到本地,再次點擊就會正常顯示分支信息了。?
在配置iOS 靜態代碼掃描時,使用sonar-objective-c-plugin-0.5.0-SNAPSHOT.jar 插件進行掃描,該插件版本與sonarQube 系統版本相關,需要注意。目前遺留問題是OC 的掃描規則太少,掃描結果只能掃出壞味道,Bug 和漏洞都無法掃到。配置文件增加了如下配置也沒有效果:
sonar.objectivec.oclint.report=oclint.xml
sonar.objectivec.oclint.reportPath=sonar-reports/oclint.xml