折腾了好些天, 最终成功编译打包 IOS应用 上传到 TestFlight , 记录下中途踩的坑.
题外话:
Github Action 官方给到的 MacOS 的 Per-minute rate 是 Linux 的10倍, 老大说把闲置的一台 Mac mini 用上, 所以后面改用了 self-hosted runner. 省了笔琐碎银子, 也方便了 Debug…..
主要的坑是两步验证 和 KeyChain问题.
两步验证
苹果官方强制要求两步验证登录 Apple 开发者帐号, 但是使用 Github actions 在非交互模式下, 你是无法输入验证码的, Fastlane 官方提供了解决方法: App Store Connect API
按照文档提示配置下, 没啥问题. 这里简单提下我的做法.
在App Store Connect 中获取到 key_id, issuer_id, key(.p8文件的内容)
在Fastlane文件中添加如下代码:
lane :beta do |options|
app_store_connect_api_key(
key_id: ENV['ASCAPI_KEY_ID'],
issuer_id: ENV['ASCAPI_ISSUER_ID'],
key_filepath: 'authkey.p8',
duration: 1200, # optional (maximum 1200)
in_house: false # optional but may be required if using match/sigh
)
match(type: "appstore")
enable_automatic_code_signing
gym(scheme: "Leaf") # Build your app
pilot
.....
end
调用 app_store_connect_api_key
后, 需要认证的 Action, 比如pilot, 会自动加载 Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
. 所以务必将 app_store_connect_api_key
放在所有需认证的 Action 之前.
这里 ENV 的变量 ASCAPI_KEY_ID
, ASCAPI_ISSUER_ID
都可以设置在 Github 的 secrets 中.
而文件 authkey.p8
可以使用 gpg
加密解密.
本地终端执行:
gpg -c --armor authkey.p8
会要求输入 passphrase, 最后生成文件 authkey.p8.asc. 这个 passphrase 需要添加到 secrets 中, 后续解密要用到.
在.gitignore
中添加 authkey.p8, 忽略该文件, 将 authkey.p8.asc 文件提交.
然后在 github action 的 Workflow 配置文件中解密:
- name: decrypt auth file
run: |
gpg -d --passphrase ${{ secrets.DEPLOY_ENC_KEY }} --batch authkey.p8.asc > authkey.p8
这里 secrets 的 DEPLOY_ENC_KEY 就是刚刚加密时用的 passphrase .
如果觉得麻烦, 也可以将 key_filepath 改成 key 参数, 把 authkey.p8 中的内容贴到 secrets 中也可以. 具体可参看官方文档:
app_store_connect_api_key(
key_id: ENV['ASCAPI_KEY_ID'],
issuer_id: ENV['ASCAPI_ISSUER_ID'],
key: ENV['ASCAPI_KEY'],
duration: 1200, # optional (maximum 1200)
in_house: false # optional but may be required if using match/sigh
)
Keychain 问题
这个是花时间最久的地方, 遇到坑了.
首先在 Self-hosted runner 中, 跑一次编译打包, 一路下来, 成功发布到了TestFlight.
但使用 Github Action 时, 报错:
▸ Running script '[CP] Embed Pods Frameworks'
** ARCHIVE FAILED **
The following build commands failed:
PhaseScriptExecution [CP]\ Embed\ Pods\ Frameworks /Users/***/Library/Developer/Xcode/DerivedData/Leaf-acuongxlhifqldeauyqugojdtjev/Build/Intermediates.noindex/ArchiveIntermediates/Leaf/IntermediateBuildFilesPath/Leaf.build/Release-iphoneos/Leaf.build/Script-46D1B8D72193B7966B5CC35AB1794FCF.sh
(1 failure)
[17:40:06]: Exit status: 65
match 通过, 但 build app 报错.
改用 SSH 远程执行命令, 去打包, 报了同样的错误. 也就是在非交互模式下, build 失败, 交互模式下,build 成功.
Google 了半天, 基本都说是 key-chain 的问题.
有的解决方法中, 提到了使用 Fastlane 官方的 setup_ci action, 可以创建临时的key-chain. 尝试了下, 没有效果.
最后的解决方法参考了远程终端登录下如何解锁 macOS Keychain .
Self-hosted runner 需要运行 ./run.sh
来监听Workflow, tmux 建 Session , 开两个Window, 一个跑 ./run.sh
, 另一个Window中, 执行
security unlock-keychain login.keychain
会提示输入用户的登录密码, 输入即可.
在 Github Action 中再次执行 Workflow, OK.
当然, 也可以直接在 Workflow配置文件中添加如下步骤 [ 在跑 fastlane 步骤之前]:
- run: security unlock-keychain -p ${{ secrets.PASSWD }} ~/Library/Keychains/login.keychain
PASSWD 为用户的登录密码.
OK.