使用fastlane工具自動打包發布App Store、fir、蒲公英

1. 前言

打包過程中為了避免重復性的工作和節省時間,以下是研究和學習Fastlane的一些記錄和總結,希望可以為初學者提供一些幫助。

1.1. 依賴環境:

Xcode7 +
macOS or Linux with Ruby 2.0.0 +

2. Fastlane簡介

Fastlane 是一套使用Ruby寫的自動化工具集,為iOS 和 Android 開發者提供的自動化構建工具,它可以幫助開發者將 App 打包、簽名、測試、發布、信息整理、提交 App Store 等工作完整的連接起來,實現完全自動化的工作流。

fastlane 強大之處就在于其提供的工具全,基本可以覆蓋打包測試發布的所有流程,如下圖:

image

fastlane 的每一個工具都對應一個 Ruby 腳本,用來執行某一特定的任務,而最妙的是可以通過配置文件將不同的工具靈活的結合在一起,從而形成一個完整的自動化流程,實現一鍵上傳 ITC,從而縮短用于構建發布的時間。比如我需要完成一套發布流程:

#發布到AppStore
lane :release do
  #增加build版本號,需要先配置build setting
  increment_build_number
  #pod資源更新
  cocoapods
  #打包
  gym
  #發布到AppStore
  deliver(force: true)
  #發布testflight測試
  testflight
end

2.2. Fastlane組件

  • 測試
    • scan => 自動運行測試工具,并且可以生成漂亮的HTML報告
  • 證書,配置文件
    • cert => 自動創建管理iOS代碼簽名證書
    • sigh => 一聲嘆息啊,這么多年和Provisioning Profile戰斗過無數次。總是有這樣那樣的問題導致配置文件過期或者失效。sigh是用來創建、更新、下載、修復Provisioning Profile的工具。
    • pem => 自動生成、更新推送配置文件
    • match => 一個新的證書和配置文件管理工具。我會另寫一篇文章專門介紹這個工具。他會所有需要用到的證書傳到git私有庫上,任何需要配置的機器直接用match同步回來就不用管證書問題了,小團隊福音啊!
  • 截圖
    • snapshot => 用Xcode7推出的UI test功能實現自動化截圖
    • frameit => 可以把截的圖片自動套上一層外邊框
  • 編譯
    • shenzhen => 當年大名鼎鼎的自動編譯工具,現在已經被棄用
    • gym => Fastlane家族的自動化編譯工具,和其他工具配合的非常默契
  • 發布
    • produce => 如果你的產品還沒在iTunes Connect(iTC)或者Apple Developer Center(ADC)建立,produce可以自動幫你完成這些工作
    • deliver => 自動上傳截圖,APP的元數據,二進制(ipa)文件到iTunes Connect
  • TestFlight管理
    • pilot => 管理TestFlight的測試用戶,上傳二進制文件
    • boarding => 建立一個添加測試用戶界面,發給測試者,可自行添加郵件地址,并同步到iTC
  • 輔助工具
    • spaceship => 為pilotboardingdeliver等工具提供和 iTC 和 ADC 的交互API。spaceship本來是個獨立的項目,后來被Fastlane收編進來
    • WatchBuild => 是一個獨立的iTC監控工具,開啟WatchBuild可以監控iTC上的文件狀態,彈出MacOS自帶的Notification
  • Android
    • supply => 自動上傳到Google Play工具(如果有時間,我想把國內提供API的Android Store都寫個插件自動上傳,這個問題從10年我剛開始工作就覺得是個痛點)
    • screengrab => Android的自動截圖工具

3.安裝

3.1 安裝正確的Ruby版本,需要2.0及以上版本:

ruby -v

3.2 檢查 Xcode CLT 是否安裝:

xcode-select --install
##如果已經安裝,出現command line tools are already installed, use "Software Update" to install updates.出現command line tools are already installed, use "Software Update" to install updates.

3.3 安裝 fastlane:

sudo gem install fastlane

執行命令時,輸入用戶密碼

3.4 檢查版本 fastlane:

fastlane --version

3.5 初始化配置-----進入工程開干(first)

$ cd 項目目錄
$ fastlane init

Peter-2:~ Peter$ cd desktop
Peter-2:desktop Peter$ cd Popo/
Peter-2:Popo Peter$ fastlane init
[?] ?? /Users/peter/.rvm/rubies/ruby-2.4.1/lib/ruby/gems/2.4.0/gems/tty-screen-0.6.4/lib/tty/version.rb:3: warning: already initialized constant TTY::Screen::VERSION
/Users/peter/.rvm/gems/ruby-2.4.1@global/gems/tty-screen-0.6.4/lib/tty/version.rb:3: warning: previous definition of VERSION was here
[?] ?? 
[?] Looking for iOS and Android projects in current directory...
[17:08:01]: Created new folder './fastlane'.
[17:08:01]: Detected an iOS/macOS project in the current directory: 'Popo.xcodeproj'
[17:08:01]: -----------------------------
[17:08:01]: --- Welcome to fastlane ?? ---
[17:08:01]: -----------------------------
[17:08:01]: fastlane can help you with all kinds of automation for your mobile app
[17:08:01]: We recommend automating one task first, and then gradually automating more over time
[17:08:01]: What would you like to use fastlane for?
1. ??  Automate screenshots
2. ?????  Automate beta distribution to TestFlight
3. ??  Automate App Store distribution
4. ??  Manual setup - manually setup your project to automate your tasks
?  

寫在當前:

1、代表app市場圖片素材;
2、發布到TestFlight進行測試;
3、發布到App Store;
4、自定義

在初始化```fastlane```的過程中,可能會出現要輸入蘋果開發者賬號,
在 "Your Apple ID" 這一步輸入蘋果開發者賬號。
在“Please confirm the above values”這一步,確認信息,沒問題輸入 y。
然后,```fastlane ```會進行一系列的初始化操作,包括下載 App Store 上的元數據和截屏文件。

在這里,我們選擇序號 4 ,來手動去設置自定義的打包內容,在這一步完成后,工程目錄下就多了一個 fastlane目錄,其內容如下:

image.png
  • 期間會讓你輸入 Apple ID 賬號密碼(這個信息會存在鑰匙串中,后續使用無需再輸入密碼)
  • 會檢測當前的 app identifier 是否在 ADC 中
  • 會檢測當前 app 是否在 ITC 中
  • 如果已經在 ADC 和 ITC 中創建相應的信息,那么過程會很順利

接下來會問你這個app是否需要在iTC和ADC中創建(上一步中如果選擇y會自動檢測是否需要創建),fastlane會調用produce進行初始化,如果現在還不想創建,也可以之后再運行fastlane produce init進行這個流程。如果不執行produce的流程,deliver的流程也會被掠過,當然之后也可以fastlane deliver init運行完全一樣的流程。

3.6 Fastlane 初始化完成后,工程目錄下會自動生成 fastlane 文件夾,如下所示:

fastlane
├── Appfile
├── Deliverfile
├── Fastfile
├── metadata
│   ├── copyright.txt
│   ├── en-US
│   │   ├── description.txt
│   │   ├── keywords.txt
│   │   ├── marketing_url.txt
│   │   ├── name.txt
│   │   ├── privacy_url.txt
│   │   ├── release_notes.txt
│   │   └── support_url.txt
│   ├── primary_category.txt
│   ├── primary_first_sub_category.txt
│   ├── primary_second_sub_category.txt
│   ├── secondary_category.txt
│   ├── secondary_first_sub_category.txt
│   ├── secondary_second_sub_category.txt
│   └── zh-Hans
│       ├── description.txt
│       ├── keywords.txt
│       ├── marketing_url.txt
│       ├── name.txt
│       ├── privacy_url.txt
│       ├── release_notes.txt
│       └── support_url.txt
└── screenshots
    ├── README.txt
    ├── en-US
    │   ├── 一堆png圖片

其他:

  1. 這里肯定會被創建的是AppfileFastfile。如果Deliverfilescreenshotsmetadata目錄沒被創建,可以運行deliver init重新初始化,在執行deliver init的過程中,會同步iTC中的所有語言的元數據和截圖。

  2. fastlane的配置會要求輸入開發者賬號密碼,所有的密碼都加密保存在系統的Keychain里

  3. Matchfile: match 這個action的配置文件,fastlane match init 自動生成,存放git地址等

推薦使用Sublime Text工具打開

cd fastlane
open -a /Applications/Sublime\ Text.app/ Appfile Deliverfile Fastfile

操作步驟:在Sublime Text 工作窗口,點擊右下角Plain Text區域,出現的下拉菜單中選擇Ruby,或者在sublime的菜單中,找到View——>Syntax中選擇ruby,即可高亮代碼。

4. fastlane 文件配置

fastlane 的各文件解釋如下:

  • Appfile:用于指定 app_identifier, apple_id, team_id
  • Fastfile:配置管理 lane
  • Deliverfile:配置應用在 ITC 中的各種信息,和 ICC 中的數據是一一對應的
  • metadata:包含應用在 ITC 中的各種信息
  • screenshots:包含截圖數據
4.1 配置 Fastfile
default_platform(:ios)

platform :ios do
  desc "上傳到 App Store"
  lane :release do
    build_app(workspace: ENV['SCHEME_workspace'], scheme: ENV['SCHEME_NAME'])
    upload_to_app_store(
          skip_screenshots:true,# 不上傳屏幕截圖
          skip_metadata:true,# 不上傳元數據
      )
  end


desc "打包到fir"
  lane :to_firim do
      # 如果你用 pod install
      cocoapods
      # 如果你沒有申請adhoc證書,sigh會自動幫你申請,并且添加到Xcode里
      sigh(adhoc: true)
      # 以下兩個action來自fastlane-plugin-versioning,
      # 第一個遞增 Build,第二個設定Version。
      # 如果你有多個target,就必須指定target的值,否則它會直接找找到的第一個plist修改
      # 在這里我建議每一個打的包的Build都要不一樣,這樣crash了拿到日志,可以對應到ipa上
      increment_build_number_in_plist(target:ENV['SCHEME_NAME'])
      increment_version_number_in_plist(
        target:ENV['SCHEME_NAME'],
        version_number: ENV['APP_VERSION_RELEASE']
        )
      # gym用來編譯ipa
      gym(
        output_directory: './firim',
        export_options: {
          method: "ad-hoc",#打包類型app-store, ad-hoc, enterprise(企業賬號打包), development
          thinning: "<none>"
        },
        scheme: ENV['SCHEME_NAME']
        )
      # 上傳ipa到fir.im服務器,在fir.im獲取firim_api_token
      firim(firim_api_token:ENV['Firim_Api_Token'])
    end


end

如果想創建 ad hoc 配置文件,需要指定sigh(adhoc: true).更多的信息參見:

4.2 配置 metadata 文件夾---如果不想配置可跳過到 5. 插件

需要注意的是,metadata 和 Deliverfile,都可以配置 ITC 的數據,但后者優先級高
下文先在 metadata 文件夾中進行配置用于演示,在文末會刪除 metadata 中的配置文本,全部配置在 Deliverfile 中.

  1. 在 metadata 文件夾中創建分級文件:itunes_rating_config.json,這個和 ICC 中的分級是對應的.
{"CARTOON_FANTASY_VIOLENCE": 0,
"REALISTIC_VIOLENCE": 0, 
"PROLONGED_GRAPHIC_SADISTIC_REALISTIC_VIOLENCE": 0,
"PROFANITY_CRUDE_HUMOR": 0,
"MATURE_SUGGESTIVE": 0, 
"HORROR": 2,
"MEDICAL_TREATMENT_INFO": 0,
"ALCOHOL_TOBACCO_DRUGS": 0, 
"GAMBLING": 0, 
"SEXUAL_CONTENT_NUDITY": 0,
"GRAPHIC_SEXUAL_CONTENT_NUDITY": 0, 
"UNRESTRICTED_WEB_ACCESS": 0,
"GAMBLING_CONTESTS": 0
}

此處配置參見官方文檔

  1. 將 App 圖標添加至文件夾中
4.3 Snapshot 截圖和 XCTest

命令行輸入:

fastlane snapshot init

生成名為Snapfile的文件,修改內容為:

# A list of devices you want to take the screenshots from
devices([
  "iPhone 5",
  "iPhone 6",
  "iPhone 6 Plus"
])
# A list of supported languages
languages([
  'en-US',
  'fr-FR'
])
# Where should the resulting screenshots be stored?
output_directory "./fastlane/screenshots"
# Clears previous screenshots
clear_previous_screenshots true
# Latest version of iOS
ios_version '10.1'

然后打開 Xcode 工程,添加截圖設置(需要增加 UITest, 因為截圖是在 UITest 時截取的):

\\ 1)在項目添加UI測試,已經添加略過
\\ 2)將./fastlane/SnapshotHelper.swift 添加到UI測試中
\\ 3)打開 XXXUITests.swift ,刪除setUp和tearDown方法,然后在其中添加以下代碼testExample:

  let app = XCUIApplication()
  setupSnapshot(app)
  app.launch()

  app.buttons["next"].tap()
  snapshot("01firstPage") // 此處截圖

  app.buttons["back"].tap()
  snapshot("02secondPage") // 此處截圖

4.3 配置 Deliverfile

其實上傳 ITC 最主要的文件是 Deliverfile,配置好 Deliverfile 后,可以刪除 metadata 文件夾中的文本配置.最終配置如下圖:

15698.png

以下是主要的配置,更多更詳細的請戳文件,里面有詳細的注釋,拿來即可使用

# 1 app_identifier
app_identifier "com.3code.ADDemo"

# 2 用戶名,Apple ID電子郵件地址
username "Apple ID電子郵件地址"  

# 3 支持語言
supportedLanguages = {
  "cmn-Hans" => "zh-Hans"
}

# 4 app 名稱
name({
'zh-Hans' => "ADDemo"
})

# 5 描述
description({
  'zh-Hans' => "簡體中文版"
})

# 6 提交審核信息
submission_information({    
    export_compliance_encryption_updated: false,
    export_compliance_uses_encryption: false,
    content_rights_contains_third_party_content: false,
    add_id_info_uses_idfa: false
})

# 7 應用審核小組的聯系信息 app 審核信息
app_review_information(
  first_name: "name",
  last_name: "name",
  phone_number: "手機號",
  email_address: "email",
  demo_user: "測試賬號用戶名",
  demo_password: "測試賬號密碼",
  notes: "noting"
)

# 8 copyright 
copyright "#{Time.now.year} 3code"

# 

5. 插件

Fastlane的插件是一個或者一組action的打包,單獨發布在fastlane之外。Fastlane Plugin 指南

#查看所有插件
fastlane search_plugins
# 安裝方法
fastlane add_plugin [name] 

#常用插件
#版本號
fastlane add_plugin versioning
#fir
fastlane add_plugin firim
#蒲公英
fastlane add_plugin pgyer

  • 使用 Fastlane 上傳 App 到蒲公英(https://www.pgyer.com/doc/view/fastlane)

  • fastlane-plugin-versioning: 用來修改build版本號和version版本號。Fastlane內嵌的actionincrement_build_number使用的是蘋果提供的agvtoolagvtool在更改Build的時候會改變所有target的版本號。這時如果你在一個工程里有多個產品的話,每次編譯,所有的Build都要加1,最后就不知道高到哪里去了。
    有了fastlane-plugin-versioning不僅可以指定target增加Build,當然也可以直接設定Version。

6. 環境變量Environment Variables

有時候我們希望把賬號信息、更新描述和版本號等信息單獨放在一個配置文件。在這里Fastlane給我們提供了相應的解決方案。

我們可以在工程目錄下創建一個名為 .env 的文件,自定義所需的臨時變量,然后Fastlane的三個配置文件(AppfileDeliverfileFastfile)分別從.env文件中讀取配置信息。

關于ENV用法可參考以下鏈接:
https://docs.fastlane.tools/advanced/#environment-variables
https://github.com/bkeepers/dotenv

.env 文件為影藏文件,可使用如下命令查看:
Finder 默認不顯示隱藏文件,創建 .env 文件后,若需查看,需要執行兩條命令來開啟隱藏文件的顯示:

$ defaults write com.apple.finder AppleShowAllFiles -boolean true;
$ killall Finder

ls -a

下面給出的 .env 文件配置可做參考:

#APP唯一標識符
APP_IDENTIFIER = "xxx.xxx.TestGitProject"

#發布版本號
APP_VERSION_RELEASE = "1.1.0"

#新版本修改記錄
RELEASE_NOTES = "1) 升級測試第一行\n2) 升級測試第二行"

#蒲公英 更新描述
PGY_UPDATE_DESCRIPTION = "fastlane自動打包上傳測試"

#自動提交審核
SUBMIT_FOR_REVIEW = false

#審核通過后立刻發布
AUTOMATIC_RELEASE = false

#蘋果開發者賬號
APPLE_ID = "xxx@xxx.xxx"

#蘋果開發者帳號密碼
FASTLANE_PASSWORD = "xxxxxx"

#套裝ID
TEAM_ID = "94xxxxx02"

#應用名稱
SCHEME_NAME = "TestGitProject"

#APP元數據及截圖存放路徑
METADATA_PATH = "./metadata/TestGitProject"
SCREENSHOTS_PATH = "./screenshots/TestGitProject"

#APP元數據及截圖下載時,直接覆蓋原有數據,不詢問
DELIVER_FORCE_OVERWRITE = true

AppfileDeliverfileFastfile配置文件修改如下:
Appfile

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

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

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

Deliverfile :

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

username ENV['APPLE_ID'] # your Apple ID user

Fastfile :
上傳到 App Store

desc "上傳到 App Store"
  lane :release do
    build_app(workspace: ENV['SCHEME_workspace'], scheme: ENV['SCHEME_NAME'])
    upload_to_app_store(
          skip_screenshots:true,# 不上傳屏幕截圖
          skip_metadata:true,# 不上傳元數據
      )
  end

skip_screenshots:true,# 不上傳屏幕截圖,要上傳就傳false
skip_metadata:true,# 不上傳元數據,要上傳就傳false

打包到fir

desc "打包到fir"
  lane :to_firim do
      # 如果你用 pod install
      cocoapods
      # 如果你沒有申請adhoc證書,sigh會自動幫你申請,并且添加到Xcode里
      sigh(adhoc: true)
      # 以下兩個action來自fastlane-plugin-versioning,
      # 第一個遞增 Build,第二個設定Version。
      # 如果你有多個target,就必須指定target的值,否則它會直接找找到的第一個plist修改
      # 在這里我建議每一個打的包的Build都要不一樣,這樣crash了拿到日志,可以對應到ipa上
      increment_build_number_in_plist(target:ENV['SCHEME_NAME'])
      increment_version_number_in_plist(
        target:ENV['SCHEME_NAME'],
        version_number: ENV['APP_VERSION_RELEASE']
        )
      # gym用來編譯ipa
      gym(
        output_directory: './firim',
        export_options: {
          method: "ad-hoc", # 這可以不指定
          thinning: "<none>"
        },
        scheme: ENV['SCHEME_NAME']
        )
      # 上傳ipa到fir.im服務器,在fir.im獲取firim_api_token
      firim(firim_api_token:ENV['Firim_Api_Token'])
    end
  desc "發布 測試版本 到 蒲公英"
  lane :beta_pgy do    
    gym(scheme: ENV['SCHEME_NAME'], 
      export_method: "ad-hoc",
      silent: true,  # 隱藏沒有必要的信息
      clean: true  # 在構建前先clean
      )

    pgyer(api_key: ENV['PGY_API_KEY'], 
      user_key: ENV['PGY_USER_KEY'], 
      update_description: ENV['PGY_UPDATE_DESCRIPTION'], 
      password: "123456", 
      install_type: "2")
  end

上傳到App store,在終端cd到目錄,執行如下就可以了

$ fastlane release

完成后,上傳到fir,在終端cd到目錄,執行如下就可以了

$ fastlane to_firim

如果提示


image.png

說明工程使用了cocoapod,需要在Gemfile中添加gem 'cocoapods'

source "https://rubygems.org"

gem "fastlane"
gem 'cocoapods'

plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)

image.png

上傳到蒲公英,在終端cd到目錄,執行如下就可以了

$ fastlane beta_pgy

參考鏈接:

  1. Hailong's Blog- Fastlane帶來的全自動化發布
  2. AD_Fastlane
  3. iOS持續集成Fastlane + 蒲公英自動打包發布
  4. Fastlane 實現多 Target 自動化打包發布
  5. iOS Fastlane 自動打包發布技術
  6. fastlane使用說明書
  7. [Fastlane使用總結(一)]
    (http://www.lxweimin.com/p/04b83b335d53)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容