fastlane 已经能很好完成 iOS 项目的证书管理和打包发布了,但都是在本地进行的,但本地编译发布还是或多或少都影响干活,就算公司有专门的发布,但如果自己想搞些玩意,先不说编译对机器造成卡顿,单是发布到 Testflight 或 App Store 这步,晚上又是海外流量高峰期,三大运营商的家庭宽带都限速出海,还是策略性丢包,不小心就上传失败,一晃就是大半小时过去了。
Github Actions 就能比较完美解决这个痛点。不能不说,巨硬收购 github 后,私有仓库能随便建了,现在又(约)送(几)台 2C7G 的 vps 给用户作持续交付,还是非常良心的。
初始化 GitHub Actions
可以到项目的 GitHub 页面开通,选择一个空白 Action,提交,然后在本地 pull 下来修改。
或者直接在本地项目的根目录创建一个 .github 隐藏文件夹,在其下再创建一个 workflows 文件夹,再在 workflows 创建master.yml 文件,叫什么无所谓,是yml文件就行。
编排
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| name: CI
on: push: branches: - master
jobs: build: runs-on: macOS-latest steps: - name: Login Github User run: echo -e "machine github.com\n login $PERSONAL_ACCESS_TOKEN" >> ~/.netrc env: PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - uses: actions/checkout@v2 - name: Cache cocoapods uses: actions/cache@v2 with: path: Pods key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} restore-keys: | ${{ runner.os }}-pods- - name: install cocoapods dependencies run: pod install - name: build and publish to testflight run: bundle exec fastlane release env: ISSUER_ID: ${{ secrets.ISSUER_ID }} KEY_ID: ${{ secrets.KEY_ID }} KEY_CONTENT: ${{ secrets.KEY_CONTENT }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
|
以上就是在 push master 分支时,将项目打包发布到 testflight 的编排。大体上每一步作用一目了然,以下解析其中的细节
当 master分支有推送时触发
1 2 3 4
| on: push: branches: - master
|
jobs 中,name
相当于打印一行字符,run
是执行一段命令,env
是设置环境变量,uses
,是执行一段设置好的操作。
其中 secrets.PERSONAL_ACCESS_TOKEN
,是获取预先设定的一些敏感信息,这里是获取 github 的专用密码,用以在这个虚拟机里登录 GitHub 拉去私有仓库的代码,在项目的 Settings -> Secrets 下设置。
以下是拉取代码,默认是事件分支或主分支,可以指定分支,详情请自行查阅
1
| - uses: actions/checkout@v2
|
接着是缓存,因为每次运行的虚拟机都是一个干净的环境,这步可以每次运行完都会保存 cocoapods
的文件,下次运行时恢复
1 2 3 4 5 6 7
| - name: Cache cocoapods uses: actions/cache@v2 with: path: Pods key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} restore-keys: | ${{ runner.os }}-pods-
|
接着是执行一次 pod install
接着执行 fastlane release,但由于这个虚拟机跑这些流程是全自动的,没法输入fastlane模拟登录时需要的密码或双重认证码,所以按大部分fastlane中文文章操作,是无法很好地在GitHub完成发布到 testflight 这一步。FASTLANE_SESSION 的有效期是很短的,估计很多人兴冲冲地跑了一遍GitHub Action
很顺利,第二天就跑不通了。
这里只能使用18年发布的 App Store Connect API
, 首先到 https://appstoreconnect.apple.com/access/api 生成密钥,这个密钥的权限选择 app管理,利用这个密钥的相关信息可以生成一个 JWT
的 token
,有效期是 20 分钟,但密钥是不会过期的。事实上把密钥相关信息提供给 fastlane 即可,它已经实现了对接 App Store Connect API
。
以下是上篇文章的Fastfile
中的改动,创建一个钥匙串让match
安装证书和描述文件,避免要交互输入密码,以及创建 api_key
这个变量,提供了密钥相关信息。如果要在本地使用,也需要配置好 KEY_ID
、ISSUER_ID
、KEY_CONTENT
三个环境变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| default_platform(:ios)
platform :ios do desc "Push a new TF build" lane :release do time = Time.new.strftime("%Y-%m-%d-%H:%M:%S") output_path = "fastlane/archive/adhoc/" + time create_keychain( name: "keychain-sign", password: "password", default_keychain: false, unlock: true, timeout: 3600, add_to_search_list: true, ) match( git_url: "https://github.com/username/cer", type: "appstore", app_identifier: "com.domian.bundleid", readonly: true ) increment_build_number build_app( workspace: "bundleid.xcworkspace", scheme: "bundleid", output_directory: output_path ) api_key = app_store_connect_api_key( key_id: ENV["KEY_ID"], issuer_id: ENV["ISSUER_ID"], key_content: ENV["KEY_CONTENT"], duration: 1200, in_house: false, ) upload_to_testflight(api_key: api_key, skip_waiting_for_build_processing: true) clean_build_artifacts delete_keychain(name: "keychain-sign") end end
|