fastlane
fastlane
是使用Ruby
写的一套自动化打包IOS和Android应用的工具,提供了很多插件化操作,包括证书管理,上传商店。
由于它只是一套自动化打包工具,所以想要部署还是需要使用Github Actions这种CI平台的。
需要提前需要安装好ruby
环境,macOS自带ruby
,如果没有,可以使用rbenv来管理。
安装fastlane
setup
xcode-select --install
安装
brew install fastlane
初始化fastlane
项目根目录执行
fastlane init
项目下会创建fastlane
文件夹和Gemfile
文件
├── Gemfile
└── fastlane
├── Appfile
└── Fastfile
Appfile
是存一些fastlane的变量文件,不过我没有使用这个文件,大部分的值是通过环境变量来拿的。
Fastfile
则是主要的执行文件了,里面定一些所谓lane
的执行命令。
证书管理
证书管理这一块浪费了我很多时间,可算整好了。
IOS
IOS的证书一直都很麻烦,分为development
和上架需要的distribution
证书。使用fastlane的match就可以很轻松的管理证书,甚至开发人员根本不需要登陆Xcode
的开发者账号,如果有新成员执行一下命令就能安好证书了。
match
可以将证书存放在一个私有的git仓库中,然后开发者只需要执行命令,就可以将证书安装到本地了,这样共用同一个证书,避免申请多个证书。
同时它推荐创建一个新的开发者账号作为公用账号,并申请一个App Store Connect API。
首先使用新的开发者账号来配置match
,输入一个私有的git仓库地址用来存放证书。
fastlane match init
现在会增加一个Matchfile
在fastlane文件夹,里面则是match的配置。
如果你想将证书放在不同的分支,可以在Matchfile
文件中加上你自定义的分支名称
git_branch("fastlane_certificates")
还需要申请一个Github Token,用于后续的仓库访问。
将Token转为base64。
echo -n your_github_username:your_personal_access_token | base64
写入Matchfile
文件
git_basic_authorization("xxxxxxxxx")
将app identifier
写入Matchfile
,如果有多个,可以写为一个数组。
app_identifier("com.xxx.xxx")
如果想要撤销掉之前发放的所有证书,可以执行
fastlane match nuke development
fastlane match nuke distribution
创建新证书
执行过程中会输入Apple ID,同时会设定一个访问密码。
fastlane match appstore
fastlane match development
速度会有一些慢,建议代理加速,执行完后看Github仓库里会有对应的证书文件。
增加Matchfile
的配置
clone_branch_directly(true)
shallow_clone(true) // 加速clone
readonly(true) // 不会生成新证书
之前有说申请一个App Store Connect API,现在将它配置上。
fastlane目录下创建一个api-key.json
文件
{
"key_id": "xxx",
"issuer_id": "xxx",
"key_content": "-----BEGIN PRIVATE KEY-----\nxxxxxxx\n-----END PRIVATE KEY-----"
}
增加Matchfile
配置
api_key_path("fastlane/api-key.json")
Android
Android证书比较简单,但是没有提供插件来处理,我的方法是将证书转为base64,在CI过程中把它转完文件写入。
转base64
base64 -i xxx.keystore > key
自动化打包
IOS
fastlane ios deploy
platform :ios do
lane :deploy do
# React Native对应项目的配置和名称
XCODE_PROJECT = './ios/rnapp.xcodeproj'
XCODE_WORKSPACE = './ios/rnapp.xcworkspace'
PLIST_PATH = "./rnapp/Info.plist"
SCHEME = 'rnapp'
setup_ci
if is_ci
unlock_keychain(
path: "fastlane_tmp_keychain",
password: "",
set_default: true
)
end
increment_build_number(xcodeproj: XCODE_PROJECT)
match(type: "appstore")
# 需要先关闭自动签名
update_code_signing_settings(
use_automatic_signing: false,
path: XCODE_PROJECT
)
build_ios_app(
workspace: XCODE_WORKSPACE,
scheme: SCHEME,
clean: true,
export_method: "app-store"
)
update_code_signing_settings(
use_automatic_signing: true,
path: XCODE_PROJECT
)
upload_to_testflight
end
end
安装证书到新开发的机器
fastlane certificates
lane :certificates do
match(
type: "development",
force_for_new_devices: true,
readonly: true
)
match(
type: "appstore",
readonly: true
)
end
Android
fastlane android deploy
require 'base64'
platform :android do
lane :deploy do |options|
setup_ci
puts "env file path: #{ENV['ENVFILE']}"
# 把之前base64的Android证书写入
if !ENV["ANDROID_KEY_STORE"].empty?
File.open("../android/app/rnapp-release-key.keystore", 'wb') do |file|
file.write(Base64.decode64(ENV["ANDROID_KEY_STORE"]))
end
end
gradle(task: 'clean', project_dir: 'android/')
gradle(task: 'app:assemble', build_type: 'Release', project_dir: 'android/')
end
end
关于环境变量问题
如果使用了react-native-config
这样的包来管理环境变量,就需要额外的配置了。
require 'dotenv'
projectPath = File.join(Dir.pwd,"..")
before_all do |lane, options|
filePath = "../.env.#{options[:env]}"
Dotenv.load filePath
ENV["ENVFILE"] = filePath
end
# Android读不到相对路径,不知道为什么
platform :android do
...
ENV["ENVFILE"] = File.join(projectPath, ".env.#{options[:env]}")
...
end
执行命令
fastlane ios deploy env:dev
就能够读取.env.dev
这个环境
废了老大时间来做这个不属于前端的活路,真是累死我了,简单做个笔记,再也不想整这个了。