使用 Jenkins 配置 iOS 持續整合踩坑實錄

Zcating發表於2019-04-24

使用 Jenkins 配置 iOS 持續整合踩坑實錄

我將之前寫的文章逐步遷移到掘金上,也是希望更多人能看到我寫的文章,共同學習。

Jenkins 是一款使用 Java 開發的持續整合工具,下面將介紹如何使用 Jenkins 來進行iOS的持續整合。坑都用粗體標明瞭。

安裝坑

在安裝 Jenkins 之前,首先要安裝 JDK,這裡需要注意 JDK 的版本,必須為1.8,過高或者過低均不行。

推薦使用 brew 來安裝 Jenkins。

brew install jenkins
複製程式碼

配置坑

第一步

安裝完畢後,直接在命令列中輸入以下命令:

jenkins
複製程式碼

在這裡需要注意,Jenkins 預設埠是8080,如果該埠被佔用,可以使用以下命令切換埠:

jenkins -httpPort 9090
複製程式碼

然後,就可以在瀏覽器中輸入localhost:9090來進入 Jenkins。在起始頁面會使用一個起始口令來讓你解鎖它,這個口令可以在命令列中,或者在其指定的目錄下可以找到該口令。輸入完畢後,會讓你建立一個賬戶,按照提示來完成操作就好。

第二步

建立完畢後,首先要去繫結你SSH金鑰,方法如下:

Jenkins -> Credentials -> global -> add Credentials
複製程式碼

第三步

繫結完畢後,開始安裝以下外掛:

  1. Keychains and Provisioning Profiles Management

對的,只有一個,不要使用 Xcode 外掛來進行 iOS 配置,因為 XCode 8 以後,通過 Archive 生成 ipa 需要包括一個 ExportOption.Plist 檔案,這個檔案在該外掛中並不會提供,所以通過指令碼來進行配置,而不是通過 XCode 外掛來配置。

安裝完畢該外掛後,直接通過網上各種渠道的資訊來對該外掛進行配置,配置該外掛基本上不會有太大問題,下面給出 keychains 和 provision 在系統中的路徑。

keychain: /Users/zcating/Library/Keychains
provision: /Users/zcating/Library/MobileDevice/Provisioning Profiles
複製程式碼

需要注意的是,上傳的時候,login.keychain-db 會被標記為不合法的檔案,login.keychain 實際上跟 login.keychain-db 是一樣的,只需要複製一份,然後更改 login.keychain-db 為login.keychain,然後就可以上傳了。

第四步

完成上傳後就可以開始構建了,構建步驟如下:

1. 新建專案,選擇自由風格。
2. 勾選 keychain 和 provision。
3. 新增 Git 配置。
4. 增加構建步驟,選擇 Execute shell。
複製程式碼

然後新增以下指令碼:

#需要自定義引數
xcode_project_path="/path/to/your/xcode/project"
export_path="/path/to/your/export/path"
ipa_name="ipa-name"
provision="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# build method,可以輸入以下選項: app-store, ad-hoc, enterprise, development
build_method="enterprise"
# bundle_id 需要跟專案中的一致
bundle_id="com.yourCompany.yourApp"
bundle_name="provision_name"
# 簽名型別,可以選擇以下型別: "iOS Developer", "iOS Distribution"
sign_cer="iOS Distribution"
# 就是你們團隊證照中的使用者名稱
team_id="XXXXXXXXXX"

#自定義完畢

export_option_path="$xcode_project_path/ExportOptions.plist"

# 寫 ExportOption.plist 檔案
echo "<?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>compileBitcode</key>
    <false/>
    <key>method</key>
    <string>$build_method</string>
    <key>provisioningProfiles</key>
    <dict>
        <key>$bundle_id</key>
        <string>$bundle_name</string>
    </dict>
    <key>signingCertificate</key>
    <string>$sign_cer</string>
    <key>signingStyle</key>
    <string>manual</string>
    <key>stripSwiftSymbols</key>
    <true/>
    <key>teamID</key>
    <string>$team_id</string>
    <key>thinning</key>
    <string>&lt;none&gt;</string>
</dict>
</plist>" > $export_option_path;

xcodebuild archive \
-archivePath "$xcode_project_path/build/${ipa_name}.xcarchive" \
-project $xcode_project \
-sdk iphoneos \
-scheme $scheme \
-configuration $build_configuration \
CODE_SIGN_IDENTITY="鑰匙串中的簽名的名稱" \
PROVISIONING_PROFILE=$provision

xcodebuild -exportArchive \
-archivePath "$xcode_project_path/build/${ipa_name}.xcarchive" \
-exportPath $export_path \
-exportOptionsPlist $export_option_path \
-allowProvisioningUpdates \
CODE_SIGN_IDENTITY="鑰匙串中的簽名的名稱" \
PROVISIONING_PROFILE=$provision

mv ${export_path}/*.ipa ${export_path}/ipa_name.ipa
複製程式碼

需要注意,XCode 專案需要關閉自動簽名配置。

到這裡,只要在 XCode 開啟該專案沒有報錯,並且可以構建,那麼就沒有任何問題了。

Unity 特別篇

使用 Jenkins 來構建 Unity,有以下幾點需要注意的地方。

關閉自動簽名,設定provision。

在 Assets 目錄下新建以下目錄和檔案 /Assets/editor/ProcessBuild.cs,並且在cs檔案中新增以下程式碼。

using System.Collections;
using System.IO;
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System;

class ProjectBuild : Editor{

	//在這裡找出當前工程所有的場景檔案.
	static string[] GetBuildScenes()
	{
		List<string> names = new List<string>();

		foreach(EditorBuildSettingsScene e in EditorBuildSettings.scenes)
		{
			if(e==null)
				continue;
			if(e.path == "Dont_Add" || e.path == "post")
			if(e.enabled)
				names.Add(e.path);
		}
		return names.ToArray();
	}

	//得到專案的名稱
	public static string projectName
	{
		get
		{ 
			foreach(string arg in System.Environment.GetCommandLineArgs()) 
			{
				if(arg.StartsWith("project"))
				{
					return arg.Split("-"[0])[1];
				}
			}
			return "test";
		}
	}
	//shell指令碼直接呼叫這個靜態方法
	static void BuildForIPhone()
	{ 
		PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS, "USE_SHARE");
		// 構建xcode工程的核心方法了, 
		// 引數1 需要打包的所有場景
		// 引數2 需要打包的名字
		// 引數3 打包平臺
		// 引數4 編譯選項
		BuildPipeline.BuildPlayer(GetBuildScenes(), "ios-build", BuildTarget.iOS, BuildOptions.None);
	}
}
複製程式碼

使用以下命令進行自動化構建。

project_dir=""
/Applications/Unity/Unity.app/Contents/MacOS/Unity \
-batchmode \
-projectPath $project_dir \
-executeMethod ProjectBuild.BuildForIPhone \
-ios \
-quit \
-logFile $project_dir/BuildXCodeProject.log 

複製程式碼

這樣就會在你指定的目錄下生成 XCode 專案。

結語

我使用了 Jenkins 生成 iOS 最終的 ipa,感受到了如絲般順滑的構建流程。生成過程只需一鍵,一鍵就能上傳Testflight,fir.im 或者蒲公英。感覺以後打包真的會方便很多很多倍,省去了各種複雜的步驟。只是在構建 Jenkins 的時候,遇到了很多問題,最終的解決方案還是決定寫一個 Shell 指令碼,這樣就省去了很多外掛的配置問題。

相關文章