iOS持續整合jenkins+xcode+svn+七牛
吐個槽:隨著程式碼的不斷累積每次iOS打包都要焦急等待小十分鐘,Xcode卡爆了有沒有,Archives有時證書都無法驗證,上傳20M的.ipa檔案一定要看網路給不給力。
jenkins實現目標:
- 生成ipa檔案
- 生成plist檔案
- ipa、plist七牛自動上傳
- 郵件反饋,生成下載連結、連結二維碼等
思路:將生成的.ipa檔案放在${WORKSPACE}/build/${BUILD_NUMBER}/
下,通過Execute shell生成.plist檔案(讓plist與ipa檔名稱保持一致),Inject environment variables
將ipa檔名稱定義全域性變數,構建成功後通過
一、jenkins安裝以及系統配置
jenkins安裝配置
- brew install jenkins(安裝)
- jenkins (啟動)
/Users/apple(電腦使用者名稱)/.jenkins
(brew安裝jenkins位置,${WORKSPACE} 值為/Users/apple(電腦使用者名稱)/.jenkins/jobs/qiniuTest(job名稱)/workspace/
)
管理外掛(系統管理–管理外掛)
- Subversion Plug-in(svn)
- Xcode integration(Xcode)
- Environment Injector Plugin(自定義全域性變數)
- Email Extension Plugin(郵件)
系統設定(系統管理–系統設定)
Xcode Builder(鑰匙串設定)
需填寫的內容:
- Keychain Name:iPhone Distribution: *(dis證書常用名)
- Keychain path:${HOME}/Library/Keychains/login.keychain(dis證書路徑)
- Keychain password:*
- Add to keychain search path after build:Yes
- Default keychain:iPhone Distribution: *
Extended E-mail Notification(郵件配置)
- 點選“高階”
需填寫的內容:
- SMTP server:smtp.exmail.qq.com(我用的是QQ郵箱)
- Default Subject:構建通知:${PROJECT_NAME}${SVN_REVISION}${BUILD_NUMBER}持續整合${BUILD_STATUS}
- Default Content: 後文有寫到
- 點選“高階”
七牛設定項(七牛Accesskey/Secretkey配置)
Accesskey/Secretkey 值可在七牛中檢視
二、job構建
jenkins–新建
“新建”–“構建一個自由風格的軟體專案”–“OK”
- Item名稱(job名稱)
原始碼管理(svn配置)
選擇的Subversion,倉庫路徑:svn打包的程式碼路徑(一般是trunk上吧)
xcode配置
新增構建步驟:
General build settings:
Advanced Xcode build options:
需填寫的內容:
General build settings:
Target:為整合的Target名稱 targetName
勾選“Clean before build?”
Configution:Release(Debug/Release按需求可選)勾選“Pack application and build ipa?”
ipa filename pattern:targetName_${SHORT_VERSION}(target名稱_version版本)
Output directory:${WORKSPACE}/build/${BUILD_NUMBER}/Code signing & OS X keychain options:
在系統Xcode Builder(鑰匙串設定)已配置Advanced Xcode build options:
勾選“Clean test reports?”
Build output directory:${WORKSPACE}/build/${BUILD_NUMBER}/
Execute shell
需填寫的內容:(獲取生成的ipa檔名稱,寫入全域性變數,生成plist檔案)
Command:"${WORKSPACE}/build/${BUILD_NUMBER}" for file in "*.ipa" do PLIST_NAME=`echo $file` done PLIST_NAME=${PLIST_NAME%.*} cd "${WORKSPACE}/build" echo "PLIST_NAME=$PLIST_NAME" > jenkinsUserGlobal.properties cat << EOF > ${WORKSPACE}/build/${BUILD_NUMBER}/$PLIST_NAME.plist <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>items</key> <array> <dict> <key>assets</key> <array> <dict> <key>kind</key> <string>software-package</string> <key>url</key> <string>https://******/$PLIST_NAME.ipa</string> </dict> </array> <key>metadata</key> <dict> <key>bundle-identifier</key> <string>***.***.***</string> <key>bundle-version</key> <string>1</string> <key>kind</key> <string>software</string> <key>title</key> <string>***</string> </dict> </dict> </array> </dict> </plist> EOF
Inject environment variables
需填寫的內容:(將在Execute shell中生成的全域性變數檔案地址放入 Properties File Path中)
Properties File Path:${WORKSPACE}/build/jenkinsUserGlobal.propertiesEditable Email Notification(郵件配置)
郵件配置
郵件基本配置:
觸發器:構建成功、失敗觸發(擴充套件一下:失敗點“高階”設定只發送給自己)
需填寫的內容:
Project Recipient List: 郵件接收人(多個時用”,“分割)
Project Reply-To List:$DEFAULT_REPLYTO
Content Type:選擇”HTML(text/html)“
Default Subject:${PROJECT_NAME}構建通知:第${BUILD_NUMBER}次持續整合${PLIST_NAME}構建${BUILD_STATUS}
- Default Content:(將ipa全域性變數傳遞到郵件生成下載連結和連結二維碼)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次構建日誌</title> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" ffset="0"> <table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif"> <tr> <td><h2> <font color="#0000FF">構建結果 - ${BUILD_STATUS}</font> </h2></td> </tr> <tr> <td><h2> <font color="#FF0000">App下載連結:<a href="itms-services://?action=download-manifest&url=https://******/${PLIST_NAME}.plist">itms-services://?action=download-manifest&url=https://******/${PLIST_NAME}.plist</a></font> </h2></td> </tr> <tr> <td><h2> <font color="#FF0000">二維碼圖片:</font> </h2></td> </tr> <tr> <td> <img src="http://qr.liantu.com/api.php?text=itms-services://?action=download-manifest%26url=https://******/${PLIST_NAME}.plist" height="300" width="300"> </td> </tr> <tr> <td><br /> <b><font color="#0B610B">構建資訊</font></b> <hr size="2" width="100%" align="center" /></td> </tr> <tr> <td> <ul> <li>專案名稱 : ${PROJECT_NAME}</li> <li>構建編號 : 第${BUILD_NUMBER}次構建</li> <li>SVN 版本: ${SVN_REVISION}</li> <li>觸發原因: ${CAUSE}</li> <li>構建日誌: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li> <li>構建 Url : <a href="${BUILD_URL}">${BUILD_URL}</a></li> <li>工作目錄 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li> <li>專案 Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li> </ul> </td> </tr> <tr> <td><b><font color="#0B610B">Changes Since Last Successful Build:</font></b> <hr size="2" width="100%" align="center" /></td> </tr> <tr> <td> <ul> <li>歷史變更記錄 : <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li> </ul> ${CHANGES_SINCE_LAST_SUCCESS,reverse=true, format="Changes for Build #%n:<br />%c<br />",showPaths=true,changesFormat="<pre>[%a]<br />%m</pre>",pathFormat=" %p"} </td> </tr> <tr> <td><b>Failed Test Results</b> <hr size="2" width="100%" align="center" /></td> </tr> <tr> <td><pre style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">$FAILED_TESTS</pre> <br /></td> </tr> <tr> <td><b><font color="#0B610B">構建日誌 (最後 100行):</font></b> <hr size="2" width="100%" align="center" /></td> </tr> <tr> <td><textarea cols="80" rows="30" readonly="readonly" style="font-family: Courier New">${BUILD_LOG, maxLines=100}</textarea> </td> </tr> </table> </body> </html>
郵件截圖
截圖1:
截圖2:
上傳到七牛
上傳到七牛配置
需填寫的內容:
- 七牛配置項:系統設定-七牛-設定項名稱
- 檔案路徑:
**/build/${BUILD_NUMBER}/*.ipa,**/build/${BUILD_NUMBER}/*.plist
- 要上傳到的 bucke:上傳到七牛的 空間 名稱
- 勾選“構建失敗則不上傳”
-
1、編譯過程中發現在我的mac上會報錯,檢視原始碼發現
System.console().printf(profile.getName() + "\n");
是這個引起的(System.console returns the unique Console object associated with the current Java virtual machine, if any.
可能電腦上麼有java虛擬機器吧,so就遮蔽這行程式碼吧或者使用前進行判斷一下Console c = System.console();
(這個還未驗證))
if (c == null) {
System.out.println("No console available");
} else {
// Use the returned Console.
}構建日誌: Failed控制檯輸出 Started by user admin Building in workspace /Users/apple/.jenkins/jobs/qiniuTest/workspace 開始上傳到七牛... ERROR: Build step failed with exception java.lang.NullPointerException at net.zouxin.lab.qiniuplugin.QiniuPublisher$DescriptorImpl.getProfileByName(QiniuPublisher.java:183) at net.zouxin.lab.qiniuplugin.QiniuPublisher.perform(QiniuPublisher.java:89) at hudson.tasks.BuildStepMonitor$2.perform(BuildStepMonitor.java:32) at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:782) at hudson.model.AbstractBuild$AbstractBuildExecution.performAllBuildSteps(AbstractBuild.java:723) at hudson.model.Build$BuildExecution.post2(Build.java:185) at hudson.model.AbstractBuild$AbstractBuildExecution.post(AbstractBuild.java:668) at hudson.model.Run.execute(Run.java:1763) at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43) at hudson.model.ResourceController.execute(ResourceController.java:98) at hudson.model.Executor.run(Executor.java:410) Build step '上傳到七牛' marked build as failure Finished: FAILURE
2、上傳到七牛的bucket中的檔案路徑對我來說可能有點多餘,作者傳遞的
"key":"build/${BUILD_NUMBER}/*.plist"
這樣的,生成的路徑會成https://***/build/${BUILD_NUMBER}/*.plist
,在原始碼107行進行替換,這樣生成的連結就會變成https://***/*.plist
。//String keyPath = path.getRemote().replace(wsPath, ""); //String key = keyPath.replace(File.separator, "/"); String fileName = path.getName();
jenkins外掛是.hpi檔案(可以在這下載我已編譯好的hpi檔案),編譯需要安裝maven,然後package,具體流程如下:
1、首先在網上下載qiniu-plugin,我就放在Downloads下。按需修改QiniuPublisher.java檔案
2、brew install maven
3、雙擊執行qiniu-plugin-master下Debug檔案
(export MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n"
)
mvn hpi:run
4、cd /Users/apple/Downloads/qiniu-plugin-master
5、man clean
//刪除target,第一次無需執行這個
6、man package
//打包生成Tagret,新生成的.hpi檔案就在target下 安裝jenkins外掛
系統管理–管理外掛–高階–上傳外掛
三、多Target擴充套件
對多Target的工程我們可在”開始構建“前手工選擇Target,然後將這target名稱在xcode編譯時傳遞過去。
配置引數化構建過程:
需填寫的內容:(擴充套件一下:還可以自定義郵件標題,郵件正文新增一段ipa升級資訊等)
- 新增引數–選擇”Choicce“
- Name為引數名,會在下面xcode配置時用到
- Choices為Target名稱,將工程的Targets名稱全放進去
- Description為描述:請選擇一個Target。
Xcode配置:
xcode使用target:
- Target:${targetName} (xcode打包對應得target名稱)
- .ipa filename pattern:${targetName}_${SHORT_VERSION}(ipa生成的包名)
配置引數化構建效果圖: