iOS 持續交付之 Fastlane

LaiYoung_發表於2018-02-07

iOS 持續交付之 Fastlane

小目標:使用Jenkins一鍵構建,並自動上傳到App Store

一、為什麼選擇 Fastlane

why fastlane

fastlane是為iOSAndroid應用程式自動化測試部署和釋出的最簡單方法。?它處理所有繁瑣的任務,如生成螢幕截圖,處理程式碼簽名以及釋出應用程式。

iOS 持續交付之 Fastlane

使用場景

  • 提交時執行測試(包括單元測試和整合測試)。
  • 構建並分發內部測試,公開測試版本。
  • 構建生產版本並上傳至 ITC(包括更新配置檔案,建立新的螢幕截圖,上傳應用並提交稽核)。

工具集

fastlane 將如下的工具套件有機地結合起來,從管理證書到單元測試,從編譯打包到上傳發布,都能通過命令列輕鬆完成.該套件支援與 JenkinsCocoaPods,xctools 等其他第三方工具的整合,並且能夠定義多個通道(lanes)以支援不同的部署目標。

  • 測試工具
    • scan:自動執行測試工具,可以生成漂亮的HTML報告。
  • 生成證書、配置工具
    • cert:自動建立iOS程式碼簽名證書(.cert檔案)。
    • sigh: 建立、更新、下載和修復 provisioning profiles,支援App Store, Ad Hoc, Development和企業profiles。
    • pem:自動生成、更新推送配置檔案。
  • 截圖、上傳、描裝置邊框
    • deliver: 上傳截圖、後設資料、App到iTunesConnect。
    • snapshot: 依靠 UI Test 完成截圖。
    • frameit: 快速地把應用截圖放入裝置框裡。
  • 自動化編譯工具
    • gym: 編譯、打包iOS app,生成簽名的ipa檔案 。
  • App 公測工具
    • pilot:管理TestFlight測試使用者,上傳二進位制檔案。
    • firim:管理firim。

二、準備工作,很重要的喲

  1. 配置當前裝置環境,最新的fastlane(2.75.1)需要2.1以上的ruby版本,正常的版本低點的,也是要求2.0以上的。因為fastlane工具是使用ruby寫的。版本過低的建議安裝rvm來升級ruby

    curl -L get.rvm.io | bash -s stable  
    
    source ~/.bashrc  
    source ~/.bash_profile 
    
    # 檢測是否安裝成功
    rvm -v
    複製程式碼
  2. 設定環境變數,fastlane需要設定一些環境變數才能正確執行,如果當前的語言環境沒有設定為UTF-8,會導致構建和上傳的時候出現問題。在~/.bashrc, ~/.bash_profile 或者 ~/.zshrc 檔案下新增如下內容:

    export LC_ALL=en_US.UTF-8
    export LANG=en_US.UTF-8
    複製程式碼
  3. 安裝Xcode命令列工具 xcode-select --install,如果已經安裝會提示xcode-select: error: command line tools are already installed, use "Software Update" to install updates

  4. 建立App ID證書,在iTunes connect 建立一個用於測試的 app。

  5. 安裝fastlane

  6. 建立一個測試demo。

    1. 並將其scheme設定為shared,不然fastlane init的時候會失敗。

      iOS 持續交付之 Fastlane

      iOS 持續交付之 Fastlane

    2. 設定好籤名配置檔案。

    3. 為app新增icon

    4. 修改devicesiPad或者iPhone

三、實踐

fastlane init

  1. cd 到專案目錄下,對於ruby安裝程式,使用命令 sudo fastlane init。(swift使用fastlane init swiftSwift安裝仍在測試階段。有關更多資訊,請參閱Fastlane.swift文件。 )

    iOS 持續交付之 Fastlane

  2. 會問你想使用fastlane做什麼?這裡我們輸入3,自動釋出到Apple Store

    iOS 持續交付之 Fastlane

    執行過程中會要求你輸入Apple開發證書的Apple ID,如果有多個Team,會讓你選擇team。

  3. 接著會問是否想用fastlane來管理你的app metadata

    iOS 持續交付之 Fastlane

    • 輸入yfastlane則會下載現有的後設資料和螢幕截圖。如果我們編輯了download下來的.txt檔案,在使用fastlane上傳app到iTunes connect的時候也會將這些內容上傳到iTunes connect

    • 輸入n,不做任何操作,仍然能使用fastlane上傳app到App Store

  4. 如果最後出現fastlane release,就表示init成功了。

    iOS 持續交付之 Fastlane

  5. 此時專案目錄下會多出一個fastlane的資料夾。

    iOS 持續交付之 Fastlane

    如果Deliverfilescreenshotsmetadata目錄沒被建立,可以執行deliver init來建立。

Deliverfile檔案裡,新增force true,不然會在上傳到iTunes connect的時候會彈出一個Preview.html網頁。

使用Gemfile

  1. 在專案根目錄下touch一個Gemfile檔案,新增以下內容

    source "https://rubygems.org"
    gem "fastlane"
    複製程式碼
  2. 執行如下命令:

    # 安裝bundler
    sudo gem install bundler
    
    # 更新 bundle,成功之後會生成一個版本控制的Gemfile.lock檔案
    [sudo] bundle update
    複製程式碼
  3. 執行命令:bundle exec fastlane [lane_name],執行lane_name指令碼。這裡的lane_name是指令碼的名稱,我們可以理解為函式名,如果我們只執行bundle exec fastlane命令,則會有一個讓我們選擇的地方,選擇需要執行的指令碼。

    iOS 持續交付之 Fastlane

    會將專案名,ipa存放的路徑,app_identifier等一系列資訊列印出來。

    iOS 持續交付之 Fastlane
    iOS 持續交付之 Fastlane
    ipadYSM檔案都存放在專案根目錄。

    iOS 持續交付之 Fastlane

    緊接著會自動上傳metadataipaiTunes Connect

    iOS 持續交付之 Fastlane

    最後會輸出每個指令碼執行所消耗的時間(s)。

    iOS 持續交付之 Fastlane

進階

如果只是很簡單的上傳到iTunes connect,上面的操作就可以滿足。

如果我們是多個target或者需要配置一些ITC上面的內容,則需要進一步的深入。

metadata

metadata是包含應用在ITC上面的各種資訊,可以使用它配置我們的ITC,建議使用Deliverfile

screenshots

螢幕截圖資料。

Appfile

儲存App資訊,比如Apple IDbundle ID等資訊。

Deliverfile

交付檔案。在這個檔案裡面可以設定iTunes connect的所有配置項,例如:

  • release_notes,此版本新增內容。
  • copyright,版權資訊。
  • submit_for_review,上傳完成後是否直接提交新版本進行審查。
  • force,跳過HTML報告檔案驗證。
  • ...

請在設定release_noressupport_urlprivate_url等配置的時候,採用hash的方式寫,國家程式碼,例如:

release_notes(
	# 中國
	'zh-Hans' => ENV['RELEASE_NOTES'],
	# 澳大利亞
	'en-au' => ENV['RELEASE_NOTES_AU'],
	# 美國
	'en-us' => ENV['RELEASE_NOTES_US']
)
複製程式碼

Fastfile

自動化指令碼配置檔案。 是我們指令碼的入口,所有的事件驅動都是在這個檔案來排程的。

default_platform(:ios)

platform :ios do

	desc "demo upload_to_app_store"
	lane : Archive_TargetA do |options|
		scheme = options[:scheme]
		date = Time.new.strftime("%Y%m%d-%h%M")
		
		# export_method 支援 app-store, ad-hoc, package, enterprise, development
		gym(
			scheme: "#{scheme}",
			output_name: "#{scheme}-#{date}.ipa",
			clean: true,
			export_method: 'app-store',
		)

		# upload_to_app_store
		deliver # 當deliverfile為空的時候,同 upload_to_app_store 作用一樣
	end
end

複製程式碼

cd到專案根目錄執行命令:bundle exec fastlane Archive_TargetA scheme:"CDDemo",後面的scheme是帶的引數。

Multi-Target

如果我們需要配置多個target進行打包的話,我們可以使用環境變數,來進行配置。假如我們現在有兩個targettargetAtargetB,則我們需要建立兩個.env檔案,例如.env.targetA,.env.targetB,放在Fastfile檔案同級目錄下

iOS 持續交付之 Fastlane

.env檔案裡面我們可以配置一些不同的內容(非公共),比如app_identifierrelease_notes等等。截圖如下:

iOS 持續交付之 Fastlane

AppfileDeliverfileFastfile等檔案,我們都可以直接使用.env檔案裡面的內容。

Appfile

# Appfile

#The bundle identifier of your app
app_identifier ENV['APP_IDENTIFIER']

# Your Apple email address
apple_id ENV['APPLE_ID'] 

# Developer Portal Team ID
team_id ENV['TEAM_ID']

複製程式碼

Deliverfile,請在設定release_nores、support_url、private_url等配置的時候,採用hash的方式寫。

# app_identifier
app_identifier ENV['APP_IDENTIFIER']

# 使用者名稱,Apple ID電子郵件地址
username ENV['APPLE_ID']

# 團隊ID
team_id ENV['TEAM_ID']

# 團隊name
team_name ENV['TEAM_NAME']

# copyright
copyright ENV['COPYRIGHT']

# 關鍵字
keywords(
	'zh-Hans' => ENV['KEYWORDS'],
)

# 新版本修改記錄
release_notes(
	# 中國
	'zh-Hans' => ENV['RELEASE_NOTES'],
	# 澳大利亞
	'en-au' => ENV['RELEASE_NOTES_AU'],
	# 美國
	'en-us' => ENV['RELEASE_NOTES_US']
)

# 支援網址
support_url(
	# 中國
	'zh-Hans' => ENV['SUPPORT_URL'],
	# 澳大利亞
	'en-au' => ENV['SUPPORT_URL_AU'],
	# 美國
	'en-us' => ENV['SUPPORT_URL_US']
)

# 隱私政策網址 國家程式碼 https://www.cnblogs.com/Mien/archive/2008/08/22/1273950.html
privacy_url(
	# 中國
	'zh-Hans' => ENV['PRIVACY_URL'],
	# 澳大利亞
	'en-au' => ENV['PRIVACY_URL_AU'],
	# 美國
	'en-us' => ENV['PRIVACY_URL_US']
)

# 上傳完成後提交新版本進行審查
submit_for_review false

# 跳過HTML報告檔案驗證
force true

# 啟用iTC的分階段釋出功能 灰度釋出
phased_release true

# 應用稽核小組的聯絡資訊 app 稽核資訊
app_review_information(
  first_name: "xx",
  last_name: "xx",
  phone_number: "+86 18888888888",
  email_address: "xxxx",
  demo_user: "test1@test.com",
  demo_password: "test123"
)

...
複製程式碼

Fastfile檔案裡面使用環境變數,跟上面略有不同。在Fastfile裡面,我們需要告訴lane 要使用那個.env檔案,這時候我們需要使用sh指令碼命令的形式來呼叫一個lane 後面跟上--env 環境變數檔名,此時呼叫的lane 不能宣告為private_lane,呼叫方式如下:

lane :releaseDemo2 do
	# 無引數
	sh "fastlane Archive_TargetA --env TargetA"
	
	# 有引數
	sh 'fastlane Archive_TargetA type:\'哈哈哈哈\' --env TargetA'
end


外部直接呼叫(帶引數)
bundle exec fastlane Archive_TargetA type:"haha" --env TargetA

複製程式碼

然後我們在Archive_TargetA lane 裡面使用ENV['xx']方式,讀取出來的內容就是從.env.TargetA檔案讀取出來的。同理,deliver Action 對應的DeliverFile檔案裡面的內容也是從.env.TargetA檔案讀取出來的。

private_lane : Archive_TargetA do |options|
	scheme = ENV['SCHEME'] # 這時候讀取出來的'scheme'就是'TargetA',從'.env.TargetA'讀取出來的

	# export_method 支援 app-store, ad-hoc, package, enterprise, development
	gym(
		scheme: "#{scheme}",
		output_name: "#{scheme}.ipa",
		clean: true,
		export_method: 'app-store',
	)

	deliver # 這時候deliverfile裡面讀取的內容就是從'.env.TargetA'檔案讀取的
end
複製程式碼

lane之間的呼叫

跟我們自己寫方法呼叫一樣,例如:

desc "打包統一入口"
lane :Archive do |options|
	# 如果我們傳入的引數'type'是targetA,那麼我們就執行Archive_TargetA 這個lane。。。
	type = options[:type]
  	if type == "TargetA"
    	Archive_TargetA(options)
  	elsif type == "TargetB"
        Archive_TargetB(options)
	else
    	Archive_TargetA(options)
  	end
end
複製程式碼

系統級lane

fastlane 預設有 lane。

  • before_all,就是在執行一次指令碼之前首先執行的程式碼,我們可以在這裡面執行一些公共的東西,比如git_pullcocoapods

    before_all do
      # 檢出到 Developer 分支
      sh 'git checkout Developer'
      git_pull
      cocoapods(repo_update: true)
    end
    複製程式碼
  • after_all, 成功結束之後,處理共有的後置邏輯。

  • before_each,每次執行 lane 之前都會執行一次。

  • after_each,每次執行 lane 之後都會執行一次。

  • error,在執行上述情況任意環境報錯都會中止並執行一次。

執行順序

執行順序 方法名 說明
1 before_all 在執行 lane 之前只執行一次。
2 before_each 每次執行 lane 之前都會執行一次。
3 lane 自定義的任務。
4 after_each 每次執行 lane 之後都會執行一次。
5 after_all 在執行 lane 成功結束之後執行一次。
6 error 在執行上述情況任意環境報錯都會中止並執行一次。

Error

  • 出現 Command timed out after 10 seconds on try 1 of 4, trying again...,在fastlane檔案開頭加上:

    ENV["FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT"] = "180"
    ENV["FASTLANE_XCODE_LIST_TIMEOUT"] = "180"
    複製程式碼

外掛

  • versioning,用來修改build版本號和version版本號。Fastlane內嵌的actionincrement_build_number使用的是蘋果提供的agvtool,agvtool在更改Build的時候會改變所有target的版本號。這時如果你在一個工程裡有多個產品的話,每次編譯,所有的Build都要加1,最後就不知道高到哪裡去了。fversioning不僅可以指定target增加Build,而且可以按照「語義化版本」規範增加Version,當然也可以直接設定Version。
  • firim,直接把AdHoc或者InHouse打包的ipa上傳到fir.im,供測試下載。

自定義外掛

外掛安裝格式

fastlane add_plugin [name],需要到專案根目錄下執行。

fastlane update_plugins 外掛更新,同上,需要cd到專案根目錄下。

注意

  • 保持打包機器的Xcode 和 證書是最新的。
  • 使用指令碼命令形式呼叫的時候不能設定成private_lane
  • private_lane 表示私有lane,使用bundle exec fastlane命令,宣告為 private_lane的是不是顯示出來的,使用指令碼命令形式呼叫的時候不能設定成private_lane

其它

可以直接在lane裡面執行git命令,例如sh 'git checkout Developer',檢出Developer分支。

由於本人的水平有限,難免會有錯誤和疏漏,歡迎 issue 指正。如果大家在Fastlane的使用上,有更好的案例,也歡迎交流和分享。

參考文章

Example

轉載請註明出處!

相關文章