Mac+Jenkins+Git+參數(shù)化構(gòu)建+Shell+iOS+蒲公英+釘釘自動(dòng)打包

作為iOS開(kāi)發(fā),每次打包都特別麻煩,需要耗費(fèi)不少時(shí)間。于是我們可以采用Jenkins來(lái)做持續(xù)化集成,自動(dòng)打包。

這里采用的是在Mac上安裝Jenkins環(huán)境,拉取Git上的代碼,通過(guò)參數(shù)化配置,編寫(xiě)shell腳本,打包Xcode工程iOS代碼,自動(dòng)發(fā)布到蒲公英上,同時(shí)通過(guò)釘釘來(lái)推送打包的狀態(tài)

一、Jenkins環(huán)境的安裝配置

首先我們需要安裝Jenkins的運(yùn)行環(huán)境,安裝Java 8。
配置好Java環(huán)境后,我們?cè)龠M(jìn)行安裝Jenkins,這里我們采用的是war包安裝的方式。

  1. 我們需要從Jenkins官網(wǎng)下載war包
  2. 將war包拷貝相應(yīng)的目錄,這里我放在了用戶目錄下,然后執(zhí)行安裝命令java -jar jenkins.war
  3. 安裝完成后,會(huì)顯示如下界面,其中有一串Jenkins的登錄密碼,然后打開(kāi)http://localhost:8080即可顯示Jenkins頁(yè)面
    安裝

期間我們可能需要稍等一會(huì)兒,首次啟動(dòng)Jenkins會(huì)進(jìn)行一些相關(guān)配置。
然后我們就可以看到如下界面。


Snip20200714_4.png

另外如果你有裝tomcat,你也可以將Jenkins.war包放在tomcat的webapps目錄下,然后啟動(dòng)tomcat服務(wù)器:sudo sh startup.sh(如果你沒(méi)有在.bash_profile環(huán)境變量下配置tomcat的啟動(dòng)路徑,那么你需要到tomcat的bin目錄下執(zhí)行該命令)
當(dāng)看到tomcat啟動(dòng)完成后,在瀏覽器輸入http://localhost:8080/jenkins,即可看到Jenkins啟動(dòng)頁(yè)。
關(guān)閉tomcat的命令是:sh ./shutdown.sh

  1. 將剛剛看到的密碼復(fù)制到啟動(dòng)頁(yè)的管理員密碼處,就解鎖了Jenkins
    然后進(jìn)入下一步,選擇安裝推薦的插件,接著會(huì)自動(dòng)安裝相關(guān)插件。


    Snip20200714_7.png
Snip20200714_6.png
  1. 接著我們創(chuàng)建一個(gè)管理員用戶
  2. 配置Jenkins的地址,就完成了Jenkins的安裝配置

二、配置

接下來(lái)我們就開(kāi)始配置自動(dòng)打包Xcode工程

1.首先我們創(chuàng)建一個(gè)新的構(gòu)建任務(wù)

image.png

點(diǎn)擊新建Item,輸入任務(wù)名稱,選擇FreeStyle project,即可完成創(chuàng)建構(gòu)建任務(wù)。
創(chuàng)建完成后如上圖所示,這里我建了一個(gè)叫newProject的任務(wù)。

2. 安裝相關(guān)插件

回到Jenkins首頁(yè),選擇進(jìn)入Jenkins的管理配置頁(yè)


image.png

選擇Manager Plugins,管理插件,在可選插件頁(yè)搜索并安裝
1)DingTalk插件,這是為了來(lái)做構(gòu)建后釘釘通知的
2)GitLab Plugin和Gitlab Hook Plugin,用GitLab管理源代碼的
3)Xcode integration,用來(lái)使用Xcode命令打包工程的
4)Git parameter,用來(lái)進(jìn)行參數(shù)化構(gòu)建的
安裝完釘釘插件后對(duì)釘釘做一些相關(guān)配置
先在釘釘上建一個(gè)群,然后在群里添加一個(gè)自定義的webhook機(jī)器人,拿到webHook地址和加密的字串


Snip20200714_3.png

然后進(jìn)入到Jenkins的配置頁(yè),對(duì)釘釘做一些配置,填入上面的webhook地址和加密字串,id是系統(tǒng)自動(dòng)生成的,選擇通知時(shí)機(jī)。然后測(cè)試一下,看到群里收到釘釘消息就成功了。保存退出
image.png

3.然后進(jìn)入到構(gòu)建任務(wù)的設(shè)置界面

image.png

1)General

首先我們可以看到一個(gè)釘釘配置,這里我們勾選上釘釘機(jī)器人即可,另外我們還可以自定定義通知人和消息內(nèi)容,到這里,我們就完成了釘釘?shù)南⑼扑团渲谩?/p>

image.png

接著我們進(jìn)行參數(shù)化構(gòu)建,可以根據(jù)自己需求選擇是否需要參數(shù)化構(gòu)建,這里參數(shù)化構(gòu)建指的我們可以在構(gòu)建打包工程之前通過(guò)這里配置的參數(shù),來(lái)打不同的包,這里我們可以設(shè)置Jenkins的內(nèi)置參數(shù),也可以自定義參數(shù),自定義的參數(shù)可以通過(guò)腳本修改Xcode工程中的配置文件,從而達(dá)到工程讀取不同的配置文件內(nèi)容展現(xiàn)不同的功能,這里兩種方式都有演示。


QQ20200710-162104.png

這里我配置了一個(gè)Jenkins的參數(shù)和一個(gè)自定義參數(shù),其中iOS_Branch_Tag可以用來(lái)區(qū)分構(gòu)建不同分支上的代碼,iOS_Code_Params是用來(lái)演示配置文件的參數(shù),后面會(huì)講到

2)源碼管理

我們這里是采用的git方式管理代碼,因此我們選擇Git,然后配置好URL和身份信息,沒(méi)有身份信息點(diǎn)擊添加,填寫(xiě)用戶名和密碼即可。
然后選擇我們進(jìn)行構(gòu)建的分支,由于我們是采用參數(shù)化配置構(gòu)建分支的,因此這里我們填入上面配置的參數(shù)。

image.png
image.png

3)構(gòu)建觸發(fā)器

這里可以根據(jù)自己的需求進(jìn)行配置:可以選擇當(dāng)有Git操作時(shí)就構(gòu)建,也可以自己設(shè)置定時(shí)任務(wù)等。。。,這里我選擇當(dāng)有Git操作就執(zhí)行打包任務(wù).

image.png

4)構(gòu)建環(huán)境

這里我們沒(méi)有什么需要進(jìn)行配置的

5)構(gòu)建

這里我們選擇使用shell腳本進(jìn)行構(gòu)建,直接執(zhí)行腳本就可以。這里建了一個(gè)shell腳本文件,用來(lái)執(zhí)行

image.png

這一步是最重要也是最復(fù)雜的一步
我們需要編寫(xiě)構(gòu)建的腳本代碼,在這之前我先列舉一下常用的環(huán)境變量

Jenkins常用內(nèi)置參數(shù):

echo $HOME:MAC下用戶目錄。例如:$HOME表示:/Users/用戶名

echo $WORKSPACE:Jenkins的工作目錄。例如你創(chuàng)建了一個(gè)newProject的工作空間,那么對(duì)應(yīng)的路徑就是: /Users/用戶名/.jenkins/workspace/newProject

echo $JOB_NAME:Jenkins的工作目錄名稱。例如你創(chuàng)建了一個(gè)newProject的工作空間,那么對(duì)應(yīng)的名稱為:newProject

echo $BUILD_NUMBER:Jenkins的構(gòu)建版本號(hào)。例如:43

echo $HUDSON_URL/ echo $JENKINS_URL:jenkins的url。例如:http://localhost:8080/

echo $BUILD_URL:build的url。例如:[http://localhost:8080/job/newProject/43/](http://localhost:8080/job/newProject/43/)

echo $JOB_URL:job的url。例如:[http://localhost:8080/job/newProject/](http://localhost:8080/job/newProject/)

echo $BUILD_DISPLAY_NAME:當(dāng)前版本的顯示名稱,默認(rèn)為“#153”。例如:#43

echo $BUILD_TAG:“jenkins- $ {JOB_NAME} - $ {BUILD_NUMBER} ”的字符串。JOB_NAME中的所有正斜杠(/)都會(huì)用破折號(hào)( - )替換。方便放入資源文件,jar文件等,以方便識(shí)別。例如:jenkins-newProject-43

echo $EXECUTOR_NUMBER:識(shí)別執(zhí)行此構(gòu)建的當(dāng)前執(zhí)行程序(在同一臺(tái)計(jì)算機(jī)的執(zhí)行程序中)的唯一編號(hào)。這是您在“構(gòu)建執(zhí)行者狀態(tài)”中看到的數(shù)字,但數(shù)字從0開(kāi)始,而不是1。例如:1

echo $NODE_NAME:代理的名稱,如果構(gòu)建是代理,或者“主”,如果在主機(jī)上運(yùn)行。例如:master

echo $NODE_LABELS:空格分隔的節(jié)點(diǎn)分配的標(biāo)簽列表。例如:master

echo $JENKINS_HOME:Jenkins在硬盤(pán)上存儲(chǔ)路徑。例如:/Users/meme/.jenkins

下面使我們的打包腳本

# 設(shè)置mac的keychain的開(kāi)機(jī)密碼
security unlock-keychain -p "開(kāi)機(jī)密碼" $HOME/Library/Keychains/login.keychain-db

# 更新pod
pod install

# 刪除之前構(gòu)建的數(shù)據(jù)
rm -rf $WORKSPACE/exportPath
rm -rf $WORKSPACE/dist

# 修改本地參數(shù)配置文件, 根據(jù)Jenkins配置修改工程配置文件
# 采用sed語(yǔ)法
JENKINS_CONFIG_FILE=$WORKSPACE/NewLive/Jenkins/jenkins_config.json
PATTERN1="iOS_Code_Params.*"

PATTERN2="iOS_Code_Params\":params1,"
sed -ig 's/'$PATTERN1'/'$PATTERN2'/g' $JENKINS_CONFIG_FILE

if [ "params1" = "$iOS_Code_Params" ];then
PATTERN2="iOS_Code_Params\":params1,"
sed -ig 's/'$PATTERN1'/'$PATTERN2'/g' $JENKINS_CONFIG_FILE
else
PATTERN2="iOS_Code_Params\":params2,"
sed -ig 's/'$PATTERN1'/'$PATTERN2'/g' $JENKINS_CONFIG_FILE
fi

# 利用xcodebuild 生成 .xcarchive 文件
xcodebuild -archivePath NewLive/NewLive.xcarchive -workspace $WORKSPACE/NewLive/NewLive.xcworkspace  -sdk iphoneos -scheme "NewLive" -configuration "Debug" archive
# 生成 ipa 文件
xcodebuild -exportArchive  -archivePath NewLive/"NewLive.xcarchive" -exportOptionsPlist $WORKSPACE/JenkinsConfig/NewMeme.plist -exportPath "exportPath"

#
# 將編譯后的文件復(fù)制到j(luò)enkins對(duì)應(yīng)的結(jié)構(gòu)目錄里面
#
mkdir -p $WORKSPACE/dist/$JOB_NAME
mv $WORKSPACE/NewLive/NewLive.xcarchive $WORKSPACE/dist/$JOB_NAME/$JOB_NAME-$BUILD_NUMBER.xcarchive
mv $WORKSPACE/exportPath/NewLive.ipa $WORKSPACE/dist/$JOB_NAME/$JOB_NAME-$BUILD_NUMBER.ipa

# 上傳蒲公英
#蒲公英上的User Key
uKey="7506db9b52d4c572ce0594c67fb633f2"
#蒲公英上的API Key
apiKey="8e217b9ab23df1ee940ae31a8577378c"
#要上傳的ipa文件路徑
IPA_PATH="$WORKSPACE/dist/$JOB_NAME/$JOB_NAME-$BUILD_NUMBER.ipa"
#執(zhí)行上傳至蒲公英的命令,這句不需要修改
curl -F "file=@${IPA_PATH}" -F "uKey=${uKey}" -F "_api_key=${apiKey}" https://www.pgyer.com/apiv1/app/upload

# 生成bugly用的符號(hào)表, 手動(dòng)上傳至Bugly符號(hào)表管理,可以設(shè)置Xcode Run Script 自動(dòng)上傳至Bugly符號(hào)表管理
#if [ "Debug" = "$Configuration" ];then
#echo "測(cè)試模式下沒(méi)有bugly的包"
#else
#Java -jar /Users/meme/bin/buglySymboliOS.jar -i $WORKSPACE/dist/$JOB_NAME/$JOB_NAME-$BUILD_NUMBER.xcarchive/dSYMs/么么直播.app.dSYM -o $WORKSPACE/dist/$JOB_NAME/$JOB_NAME-$BUILD_NUMBER.dSYMs.bugly.zip
#fi

對(duì)于以上腳本做幾點(diǎn)解釋:

  1. 由于我們是獨(dú)立的打包機(jī),可能會(huì)鎖屏,所以需要輸入開(kāi)機(jī)密碼
  2. 我們的工程有用到pod,所以打包之前需要更新下pod庫(kù)
  3. 接著是刪除之前構(gòu)建的文件,防止存儲(chǔ)空間不夠,不過(guò)如果你要作為發(fā)布版本打包的話,你需要將打包文件存下來(lái),后面可能需要代碼的符號(hào)表。你也可以自己做個(gè)配置處理
  4. 接著是為了處理參數(shù)化構(gòu)建,我們上面在General中定義了一個(gè)自定義參數(shù)iOS_Code_Params,這里預(yù)設(shè)了兩個(gè)選項(xiàng)param1和param2,同時(shí)我們?cè)诠こ痰腏enkins目錄下見(jiàn)了一個(gè)jenkins_config.json的配置文件。


    A7317682-7508-4BEB-994C-EE843B2BD384.png

    image.png

    image.png

這段代碼就是根據(jù)Jenkins構(gòu)建前選擇的配置修改工程中的配置文件。
然后我們代碼里讀取響應(yīng)的配置文件,如下:

override func viewDidLoad() {
    super.viewDidLoad()
    presentAlert(getJenkinsParams())
}

func getJenkinsParams() -> String {
    // false 使用hybrid_link 測(cè)試使用的
    // true 使用dev_hybrid_link 開(kāi)發(fā)使用的
    var params = ""
    do {
        let filePath = Bundle.main.path(forResource: "jenkins_config", ofType: "json")
        if FileManager.default.fileExists(atPath: filePath ?? "") {
            var configDic: [AnyHashable : Any]? = nil
            if let data = NSData(contentsOfFile: filePath ?? "") {
                configDic = try! JSONSerialization.jsonObject(with: data as Data, options: .mutableContainers) as? [AnyHashable : Any]
            }
            if let param = configDic?["iOS_Code_Params"] as? String {
                params = param
            }
        }
    } catch {
        
    }
    return params
}

func presentAlert(_ message: String, okTitle: String = "確定", finished: NLFinishedBlock? = nil) {
        guard !message.isEmpty else {
            return
        }
        let alertView = UIAlertController(title: message, message: "", preferredStyle: .alert)
        alertView.addAction(UIAlertAction(title: okTitle, style: .default) { _ in
            finished?()
        })
        UIViewController.current()?.present(alertView, animated: true, completion: nil)
    }

這里簡(jiǎn)單處理 下,就是讀取配置文件然后彈出來(lái)。
根據(jù)自己需求設(shè)置參數(shù)和文件位置,另外這里采用的是sed語(yǔ)法,有興趣可以自己了解一下。

  1. 接下來(lái)我們通過(guò)xcodebuild命令進(jìn)行打包,這個(gè)命令做過(guò)iOS應(yīng)該都比較熟悉了,首先生成.xcarchive文件,然后根據(jù).xcarchive文件生成.ipa文件。這里注意要設(shè)置對(duì)代碼文件的位置,以及.xcarchive文件和.ipa文件的輸出路徑,這里我放在了工程目錄下。
  2. 我們這里打包采用的手動(dòng)配置證書(shū),Xocde證書(shū)要配置好,在執(zhí)行xcodebuild命令之前,我們需要準(zhǔn)備一個(gè).plist文件,文件里包含有打包的環(huán)境(debug還是release),證書(shū),pp文件名稱。。。,這些我們可以根據(jù)以前手動(dòng)打包生成的.ipa文件時(shí),有一個(gè).plist文件,改一下.plist文件內(nèi)容即可?;蛘哂X(jué)得不太清楚的話,先手動(dòng)打個(gè)包,將打包好的.plist文件拷貝過(guò)來(lái)即可,注意要設(shè)置好路徑。
    7.這里使用腳本就是為了用戶在Jenkins配置里填一堆亂七八糟的東西,還要下載各種插件等等,比較麻煩,腳本的話一下就搞定了,后面配置其他工程也方便。
    8.如果不喜歡使用xcodebuild命令的話,也可以使用fastlane進(jìn)行打包,這個(gè)還更方便點(diǎn).
    9.我這里做了移動(dòng)文件的操作,你們可以按需來(lái)
    10.上傳到蒲公英上,需要自己進(jìn)蒲公英注冊(cè)個(gè)應(yīng)用拿到ukey和api key,最后上傳即可
    11.這里還加了一段生成Bugly符號(hào)表的操作,其實(shí)我們可以直接在Xcode的Run Script中加入,可以自動(dòng)生成符號(hào)表并上傳到Bugly后臺(tái)。

6)構(gòu)建后操作

這里加了一個(gè)歸檔成品,就是讀取到打包出來(lái)的.ipa文件,可以在Jenkins的工作控件頁(yè)面看到.ipa文件直接下載。這兩個(gè)路徑是上面腳本中最終將.ipa拷貝到的路徑位置。


image.png

到這里,關(guān)于項(xiàng)目的Jenkins配置就完成了。
我們回到項(xiàng)目首頁(yè),配置相關(guān)參數(shù)進(jìn)行構(gòu)建即可

當(dāng)開(kāi)始構(gòu)建、構(gòu)建成功、構(gòu)建失敗,都會(huì)有消息推送到釘釘群里
構(gòu)建成功后,你可以在Jenkins頁(yè)面上看到打包出來(lái)的.ipa文件,以及蒲公英上傳的.ipa文件,同時(shí)還可以看到Bugly后臺(tái)的符號(hào)表文件(前提是在Xcode工程中配置過(guò)了)

相關(guān)截圖:

  1. 相關(guān)構(gòu)建參數(shù)選擇,選擇完后,進(jìn)行開(kāi)始構(gòu)建
image.png
  1. 構(gòu)建過(guò)程中我們可以點(diǎn)控制臺(tái)輸出查看構(gòu)建日志
image.png
  1. 構(gòu)建成功后,會(huì)在任務(wù)界面上顯示包文件,點(diǎn)擊可以直接下載
image.png

4.釘釘群消息

image.png

5.還有蒲公英和Bugly的就不截圖了

總結(jié):
我們采用Jenkins在Mac上對(duì)Xcode工程做了自動(dòng)打包操作,涉及到有自定義構(gòu)建參數(shù),Git代碼,shell腳本打包,蒲公英自動(dòng)上傳,釘釘推送打包狀態(tài)。
其中注意的是編寫(xiě)shell腳本時(shí)各個(gè)目錄結(jié)構(gòu),證書(shū)、PP文件的配置。
對(duì)于參數(shù)化構(gòu)建,打包方式(xcodebuild、Fastlane)、蒲公英自動(dòng)上傳和釘釘通知可以按各自需求

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容