一、什麼是Fastlane
The easiest way to build and release mobile apps.
Fastlane是一套使用Ruby寫的自動化工具集,用於iOS和Android的自動化打包、釋出等工作,可以節省大量的時間。
二、用來做什麼
iOS一鍵指令碼完成以下步驟: 1 reset_git_repo 移除git中未提交的內容 2 git pull 只拉取最新tag 3 checkout 切換到最新的tag 4 submodule update 更新子模組 5 Pod install 第三方庫管理工具 6 Archive、Sign 打包、簽名 7 upload fir 上傳Fir 8 notification 釘釘機器人
Android 可以實現一鍵多渠道打包: 1 reset_git_repo 移除git中未提交的內容 2 git pull 只拉取最新tag 3 checkout 切換到最新的tag 4 submodule update 更新子模組 5 gradle 打包 6 add_channels_to_apk 拷貝apk,修改檔名為渠道名,渠道名寫入META-INFO目錄 參考連結:Fastlane實戰(三):Fastlane在Android平臺的應用
三、安裝
- 安裝Fastlane
sudo gem install fastlane
- 切換到工程目錄初始化
fastlane init
- 執行(lane_name為自定義lane 名字)
fastlane lane_name
四、使用
- 構建Fastlane 打包上傳 fir
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
# https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
# https://docs.fastlane.tools/plugins/available-plugins
#
# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane
fastlane_version "2.96.1"
default_platform(:ios)
platform :ios do
desc "Push a new beta build to fir"
lane :tofir do
# Deletes the Xcode Derived Data
clear_derived_data
# discarding uncommitted changes
reset_git_repo(
force: true,
skip_clean: true,
disregard_gitignore: false
)
# git pull only the tags, no commits
git_pull(only_tags: true)
# get recent tag
recentTagName = last_git_tag
# (fastlane-plugin-git_switch_branch為外掛)check out tag
git_switch_branch(branch: recentTagName)
# submodule init and update
git_submodule_update(
init: true,
recursive: true
)
# pod install
cocoapods
scheme = "ProCloser"
ipa_dir = "./fastlane_build/"+Time.new.strftime('%Y-%m-%d')
ipa_name = recentTagName + "_" + Time.new.strftime('%Y%m%d%H%M')
# gym用來編譯 打包 簽名
gym(
output_directory: ipa_dir,
output_name: "#{ipa_name}.ipa",
clean: true,
workspace: scheme + ".xcworkspace",
scheme: scheme,
export_xcargs: "-allowProvisioningUpdates",
export_options: {
method: "ad-hoc", # 指定打包方式
teamID: "xxxxxxxxxxx",
thinning: "<none>",
}
)
# (fastlane-plugin-firim為外掛)上傳ipa到fir.im伺服器,在fir.im獲取firim_api_token
firim(firim_api_token: "xxxxxxxxxxxxxxx")
desc "Notification 釘釘機器人"
# 釘釘機器人
app_patch = ipa_dir + "/#{ipa_name}.ipa"
app_version = get_ipa_info_plist_value(ipa: app_patch, key: "CFBundleShortVersionString")
app_build_version = get_ipa_info_plist_value(ipa: app_patch, key: "CFBundleVersion")
app_name = get_ipa_info_plist_value(ipa: app_patch, key: "CFBundleDisplayName")
app_url = "xxxxxxxx"
app_icon = "xxxxxxx"
dingTalk_url = "xxxxxxxxx"
dingMessage =
{
msgtype: "link",
link: {
text: "對應git tag為: #{recentTagName}",
title: "iOS #{app_name} #{app_version} (#{app_build_version}) 測試版本",
picUrl: "#{app_icon}",
messageUrl: "#{app_url}"
}
}
uri = URI.parse(dingTalk_url)
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri)
request.add_field('Content-Type', 'application/json')
request.body = dingMessage.to_json
response = https.request(request)
puts "--------------- 釘釘機器人已經通知 ✅ ---------------"
puts "Response #{response.code} #{response.message}: #{response.body}"
end
end
複製程式碼
- 增加一鍵遠端打包指令碼
客戶端:
# 遠端到打包機,執行打包機中的shell指令碼。在打包機中配置了ssh信任所以不需要輸入密碼
ssh tiejin@tiejinios.local '/Users/tiejin/closerToFir.sh'
複製程式碼
伺服器:
# 解鎖mac中的keychain,fastlane打包命令中的證書籤名需要用到keychain中記錄的賬戶和密碼。
security unlock-keychain -p 2018 $KEYCHAIN
# 進入指定目錄
cd closer
# 設定環境變數,否則fastlane中涉及到/usr/local/bin/命令部分找不到
export PATH=/usr/local/bin/:$PATH
# 執行fastlane
fastlane tofir
複製程式碼
-
和 Jenkins 結合一起使用
-
自定義Actions 0 什麼是Action Action 是Fastlane中的最小執行單元,Action中封裝了一些shell命令。
1 建立自定義Action ,會自動生成xxx.rb檔案
fastlane new_action
2 編輯 xxx.rb 檔案,修改具體邏輯。
module Fastlane
module Actions
module SharedValues
REMOVE_TAG_CUSTOM_VALUE = :REMOVE_TAG_CUSTOM_VALUE
end
class RemoveTagAction < Action
def self.run(params)
# 最終要執行的東西,在這裡執行
# 1、獲取所有輸入的引數
# tag 的名稱 如 0.1.0
tageName = params[:tag]
# 是否需要刪除本地標籤
isRemoveLocationTag = params[:isRL]
# 是否需要刪除遠端標籤
isRemoveRemoteTag = params[:isRR]
# 2、定義一個陣列,準備往陣列裡面新增相應的命令
cmds = []
# 刪除本地的標籤
# git tag -d 標籤名稱
if isRemoveLocationTag
cmds << "git tag -d #{tageName}"
end
# 刪除遠端標籤
# git push origin :標籤名稱
if isRemoveRemoteTag
cmds << "git push origin :#{tageName}"
end
# 3、執行陣列裡面的所有的命令
result = Actions.sh(cmds.join('&'))
UI.message("執行完畢 remove_tag的操作 ?")
return result
end
#####################################################
# @!group Documentation
#####################################################
def self.description
"輸入標籤,刪除標籤"
end
def self.details
# Optional:
# this is your chance to provide a more detailed description of this action
"我們可以使用這個標籤來刪除git遠端的標籤\n 使用方式是:\n remove_tag(tag:tagName,isRL:true,isRR:true) \n或者 \nremove_tag(tag:tagName)"
end
# 接收相關的引數
def self.available_options
# Define all options your action supports.
# Below a few examples
[
# 傳入tag值的引數描述,不可以忽略<必須輸入>,字串型別,沒有預設值
FastlaneCore::ConfigItem.new(key: :tag,
description: "tag 號是多少",
optional:false,# 是不是可以省略
is_string: true, # true: 是不是字串
),
# 是否刪除本地標籤
FastlaneCore::ConfigItem.new(key: :isRL,
description: "是否刪除本地標籤",
optional:true,# 是不是可以省略
is_string: false, # true: 是不是字串
default_value: true), # 預設值是啥
# 是否刪除遠端標籤
FastlaneCore::ConfigItem.new(key: :isRR,
description: "是否刪除遠端標籤",
optional:true,# 是不是可以省略
is_string: false, # true: 是不是字串
default_value: true) # 預設值是啥
]
end
def self.output
# Define the shared values you are going to provide
# Example
end
def self.return_value
# If your method provides a return value, you can describe here what it does
nil
end
def self.authors
# So no one will ever forget your contribution to fastlane :) You are awesome btw!
["zhangyan"]
end
# 支援平臺
def self.is_supported?(platform)
# you can do things like
#
# true
#
# platform == :ios
#
# [:ios, :mac].include?(platform)
#
platform == :ios
end
end
end
end
複製程式碼
五、深入學習Fastlane
0. Fastlane基本知識
- Fastlane檔案結構
Gemfile 和 Bundle 是什麼: Gemfile檔案:gem包管理工具,如:管理fastlane、cocoapods Appfile檔案:從 Apple Developer Portal 獲取和專案相關的資訊 Fastlane檔案:核心檔案,主要用於 cli 呼叫和處理具體的流程 Deliverfile:從 iTunes Connect 獲取和專案相關的資訊
- Fastlane的Plugin機制
-
Action:對於Fastlane來說Action的收錄是非常嚴格,並且有很強的通用性才能收錄其中,即使接收了,整個釋出週期也會比較長,而且以後無論是升級還是Bug修復,都依賴Fastlane本身的發版,大大降低了靈活性。
-
Plugin: Plugin就是在Action的基礎上做了一層包裝,這個包裝巧妙的利用了RubyGems這個相當成熟的Ruby庫管理系統,所以其可以獨立於Fastlane主倉庫進行查詢,安裝,釋出和刪除。
我們甚至可以簡單的認為:Plugin就是RubyGem封裝的Action,我們可以像管理RubyGems一樣來管理Fastlane的Plugin。
- 使用:
查詢
fastlane search_plugins [query]
或 檢視所有Plugin
安裝
fastlane add_plugin [plugin_xxx]
安裝完成後 會在fastlane資料夾下生成Pluginfile檔案實際就是一個Gemfile檔案,裡面包含了對於Plugin的引用,格式如下:
# Autogenerated by fastlane
#
# Ensure this file is checked in to source control!
# fastlane-plugin-version_from_last_tag 是外掛名字
gem 'fastlane-plugin-version_from_last_tag'
複製程式碼
使用 和Action使用一樣。
- 釋出Plugin 1 可以作為Gem釋出到RubyGems上,這樣就可以通過fastlane search_plugins xxx 查詢,安裝。
2 可以到Github / GitLab上 或者 引用本地路徑。
gem "fastlane-plugin-version_from_last_tag", git: "https://github.com/jeeftor/fastlane-plugin-version_from_last_tag"
複製程式碼
釋出之前,為了本地除錯方便,可以將gem指向本地,在Pluginfile這樣宣告:
gem "fastlane-plugin-version_from_last_tag", path: "../fastlane-plugin-version_from_last_tag"
複製程式碼
1. Fastlane不只是移動端
- 測試方面:
1 UI自動化測試Action: appium ,以下是appium所有引數
fastlane action appium
2 Android Monkey 下面我們看看Android一般執行Monkey測試的步驟:
Git Pull拉最新的程式碼
執行./gradlew clean命令清理環境
執行./gradlew assembleTest打包測試版本
執行命令安裝最新的測試版本:
adb shell monkey -p com.wanmeizhensuo.zhensuo -c android.intent.category.LAUNCHER 1
每次呼叫命令:
fastlane do_monkey_test times:3 project:GengmeiAndroid apk_path:./GengmeiAndroid_test.apk ...
Fastlane檔案配置如下:
desc "Android monkey test"
lane :do_monkey_test do |options|
times = options[:times]
project = options[:project]
apk_path = options[:apk_path]
package_name = options[:package_name]
hipchat(message: "Start monkey test on #{project}")
git_pull
gradle(task: "clean")
gradle(task: "assembleGmtest")
(1..times.to_i).each do |i|
adb(command: "install -r #{apk_path}")
adb(command: "shell monkey -p #{package_name} -c android.intent.category.LAUNCHER 1")
# 等待30秒,確保閃屏頁被Finish後,進入到主頁.
sleep(30)
android_monkey(package_name: "#{package_name}", count: '1000', seed: "#{10+i}")
end
hipchat(message: "Execute monkey test on project #{project} successfully")
end
複製程式碼
自定義的Action android_monkey 封裝了 Android Monkey adb
- 理論上所有頻繁使用shell操作的,都可以利用fastlane整合,自動化處理。 Fastlane還有以下這些整合好的Actions: ssh scp cli-table cli args parser
更多Actions和Plugins查閱官網 Actions - fastlane docs Plugins - fastlane docs
2. 高階用法
- 前置方法 多個lane是可能包含很多共同的方法,fastlane給出的方案:
before_all do |lane, options|
#git_pull
#cocoapods
end
複製程式碼
- 後置方法 所有lane執行完時,可能都會有通知邏輯:
after_all do |lane,options|
slack(message: "fastlane was successful", success: true)
end
複製程式碼
- error處理,每個lane執行時可能都會遇到錯誤,這個時候都應該有訊息通知到大家。error就是一個全域性錯誤處理方法:
error do |lane, exception|
slack(message: exception.message, success: false)
end
複製程式碼
-
引用機制 遠端引用
import_from_git
import_from_git - fastlane docs每次執行fastlane的命令時,首先會從git上將需要的檔案clone這個專案到本地的臨時資料夾中,然後再執行相關命令。如果某個專案中,你不想使用遠端上的某個lane,可在專案中的Fastfile中複寫這個lane即可。 -
更多高階用法檢視文件 Advanced - fastlane docs
- 參考資料 官方文件: docs.fastlane.tools github.com/fastlane/fa…
0. Fastlane - iOS 和 Android 自動化構建工具 Fastlane實戰(一):移動開發自動化之道 - 簡書 Fastlane實戰(二):Action和Plugin機制 - 簡書 Fastlane實戰(三):Android平臺上的應用 - 簡書
Tips
-
fastlane install
命令在bundle update 卡住,gem ruby 源有問題,這裡建議新增國內源。 -
ruby映象
https://gems.ruby-china.org
https://ruby.taobao.org/
替換命令:
$ gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
$ gem sources -l
*** CURRENT SOURCES ***
https://gems.ruby-china.org
# 請確保只有 gems.ruby-china.org
$ gem install rails
複製程式碼
- 遠端SSH到打包機執行打包 報錯:code sign 問題導致 unknown error -1=ffffffffffffffff iOS遠端自動打包問題 - 簡書