fastlane(3 篇)

  1. Fastlane - iOS 和 Android 的自动化构建工具
  2. 深入浅出 Fastlane 一看你就懂
  3. 你虐我千百遍,我待你如初恋,直到我遇到 match

本篇我想着重介绍 fastlane 本身的基本使用,这里使用 fastlane v1.98.0 作为演示版本。

命令行工具

安装之后默认会安装一个命令行工具 fastlane,利用它可以初始化、执行任务、查看任务定义、查看可用的动作和动作的详细定义,甚至可以用它来创建自定义的动作、插件以及一些辅助功能。想了解的话可以先看看它的帮助:

 1$ fastlane --help
 2
 3  fastlane
 4
 5  CLI for 'fastlane' - The easiest way to automate building and releasing your iOS and Android apps
 6
 7        Run using `fastlane [platform] [lane_name]`
 8        To pass values to the lanes use `fastlane [platform] [lane_name] key:value key2:value2`
 9
10  Commands:
11    action                  Shows more information for a specific command
12    actions                 Lists all available fastlane actions
13    add_plugin              Add a new plugin to your fastlane setup
14    disable_crash_reporting Deprecated: fastlane doesn't use a crash reporter any more
15    docs                    Generate a markdown based documentation based on the Fastfile
16    enable_auto_complete    Enable tab auto completion
17    enable_crash_reporting  Deprecated: fastlane doesn't use a crash reporter any more
18    help                    Display global or [command] help documentation
19    init                    Helps you with your initial fastlane setup
20    install_plugins         Install all plugins for this project
21    lanes                   Lists all available lanes and shows their description
22    list                    Lists all available lanes without description
23    new_action              Create a new custom action for fastlane.
24    new_plugin              Create a new plugin that can be used with fastlane
25    run                     Run a fastlane one-off action without a full lane
26    search_plugins          Search for plugins, search query is optional
27    trigger                 Run a sepcific lane. Pass the lane name and optionally the platform first.
28    update_plugins          Update all plugin dependencies
29
30  Global Options:
31    --verbose
32    -h, --help           Display help documentation
33    -v, --version        Display version information
34
35  Author:
36    Felix Krause <[email protected]>
37
38  Website:
39    https://fastlane.tools
40
41  GitHub:
42    https://github.com/fastlane/fastlane

我会随着下面每个概念的解释和展开来配合上面的命令一起讲解。

生命周期

执行顺序方法名说明
1before_all在执行 lane 之前只执行一次
2before_each每次执行 lane 之前都会执行一次
3lane自定义的任务
4after_each每次执行 lane 之后都会执行一次
5after_all在执行 lane 成功结束之后执行一次
6error在执行上述情况任意环境报错都会中止并执行一次

以上的部分大家在上一篇已经见识过了,有些还没接触到,不用着急都会一一说明。

任务(lane)

正常情况下你可能只会是用到一种任务方法 lane 但其实它会包含很多中高级用法。在文章的末尾会详细描述。

任务定义

定义任务的方法类似于 rake 的 task,但使用上缺比前者要好用很多,见下表:

定义是否必须说明备注
descfalse方法描述可多次使用打到换行的目的
nametrue方法名符号化的方法名
optionsfalse方法参数返回 Hash 类型
tasktrue方法主体参考 ruby 的方法代码且支持 ruby 代码
 1desc '定义一个 build 方法'
 2desc '参数 adhoc 判断是否为内测版本, 默认为 false'
 3desc 'fastlane build'
 4desc 'fastlane build adhoc:true'
 5lane :build do |options|
 6  # task to do something
 7  adhoc = options[:adhoc] || false
 8  puts "adhoc: #{adhoc}"
 9
10  gym(type: adhoc ? 'adhoc' : 'appstore')
11end

任务执行

一般情况下它需要配合定义好的 lane 才能使用,刚刚我们定义的一个 build 方法,我们这里就试着执行一下吧。

1# 默认执行
2$ fastlane build
3# 传递参数
4$ fastlane build adhoc:true

任务互调

lane 其实可以理解为 def 的别名,因此多个 lane 的话实际上是可以相互调用的,这个其实特别实用,这样其实我就可以把 cocoapods 的执行放到单独的 lane 里面而不是 before_all,这样执行非构建的任务就不会执行不相关的任务或动作,因此 fastlane 而产生了一个私有任务用内部使用 private_lane

 1
 2default_platform :ios
 3
 4platform :ios do
 5  desc '构建前的准备工作'
 6  desc '这是一个私有任务,仅供 Fastfile 内部 lane 调用使用'
 7  lane :prepare do
 8    cocoapods
 9    match
10  end
11
12  desc '通用的构建任务'
13  desc 'fastlane build'
14  desc 'fastlane build type:adhoc'
15  lane :build do |options|
16    # 调用上面 prepare 私有任务
17    prepare
18
19    case options[:type]
20    when 'adhoc'
21      # 调用 下面 adhoc 任务
22      adhoc
23    else
24      # 调用下面 appstore 任务
25      appstore
26    end
27  end
28
29  desc '构建 adhoc 任务'
30  desc 'fastlane adhoc'
31  lane :adhoc do
32    gym(type: 'adhoc')
33  end
34
35  desc '构建 appstore 任务'
36  desc 'fastlane appstore'
37  lane :appstore do
38    gym(type: 'appstore')
39  end
40end

上面的任务中,build/adhoc/appstore 都可以执行,只有 prepare 是无法通过命令行外部执行,如果执行会直接报错:

1$ fastlane prepare
2[19:17:42]: You can't call the private lane 'prepare' directly

任务返回值

和 ruby 的方法一致,每个 lane 最后一行会默认作为返回值(无需 return)。

1
2lane :sum do |options|
3  options[:a] + optiona[:b]
4end
5
6lane :calculate do
7  value = sum(a: 3, b: 5)
8  puts value #=> 8
9end

引入外部任务文件

Fastfile 除了自身以外还能够引入外部其他的 Fastfile 并调用任务,只需要导入外部文件并使用特殊的方法标识即可:

1. import - 导入本地文件

1# 导入 lanes 目录的 AndroidFastfile
2import "lanes/AndroidFastfile"

2. import_from_git - 导入 git 仓库文件

可以直接引入 git 仓库的 Fastfile 文件是一个非常赞的功能,通过使用发现其实现原理是先把 git 仓库克隆下来后在引入相对于的文件,因此建议国内在没有网络加速(翻墙)的情况下尽量不用引入比较大的 git 仓库,否则使用会需要漫长的等待…

1# 导入 mozilla/firefox-ios 项目下 fastlane 下面 Fastfile 文件
2import_from_git(url: 'https://github.com/mozilla/firefox-ios')
3# 或者
4import_from_git(url: '[email protected]:mozilla/firefox-ios.git',
5               path: 'fastlane/Fastfile')

假若外部引入的 Fastfile 有个方法是 build,在命令行工具直接执行即可,如果外部和内部都有相同的任务名,执行会直接报错:

1$ fastlane ios build
2
3[!] Lane 'gradle' was defined multiple times!

如果发生这样的事情且你希望在主体 Fastfile 也调用的话需要使用特殊的方法定义:override_lane

注意:此方法只会覆盖外部的相同方法名的代码执行,目前暂时无法使用类似 ruby 的 super 继承原由方法!

1override_lane :build do
2  ...
3end

任务查看

只需执行下面这行命令就可以看到非私有任务的可用列表信息

 1$ fastlane lanes
 2
 3--------- ios---------
 4----- fastlane ios build
 5通用的构建任务
 6fastlane build
 7fastlane build type:adhoc
 8
 9----- fastlane ios adhoc
10构建 adhoc 任务
11
12----- fastlane ios appstore
13构建 appstore 任务
14
15Execute using `fastlane [lane_name]`

扩展(Action)

扩展是 fastlane 的杀手锏,重在集成了众多非常优秀好用的方法供 lane 内部使用,截至 fastlane v1.98.0 版本以包含 175 个扩展,这个数量还在陆续增加中。扩展初期是由发起人一个人完成,后续的大部分都是社区共享,如果你发现没有你想要的扩展,可以先去 issues 搜索下没有要么自己动手提交要么只有等待了.

扩展列表

 1$ fastlane actions
 2+--------------------+-------------------------------------------------------------+------------------+
 3|                                   Available fastlane actions                                        |
 4+--------------------+-------------------------------------------------------------+------------------+
 5| Action             | Description                                                 | Author           |
 6+--------------------+-------------------------------------------------------------+------------------+
 7| adb                | Run ADB Actions                                             | hjanuschka       |
 8| adb_devices        | Get an Array of Connected android device serials            | hjanuschka       |
 9| add_git_tag        | This will add an annotated git tag to the current branch    | Multiple         |
10...
11+--------------------+-------------------------------------------------------------+------------------+
12  Total of 175 actions
13
14Get more information for one specific action using `fastlane action [name]`

扩展使用帮助

 1# 查看 adb 扩展的使用帮助
 2$ fastlane action adb
 3Loading documentation for adb:
 4
 5+---------------------------------+
 6|               adb               |
 7+---------------------------------+
 8| Run ADB Actions                 |
 9|                                 |
10| see adb --help for more details |
11|                                 |
12| Created by hjanuschka           |
13+---------------------------------+
14
15+----------+----------------------------------------------------------------------+-------------------+---------+
16|                                                  adb Options                                                  |
17+----------+----------------------------------------------------------------------+-------------------+---------+
18| Key      | Description                                                          | Env Var           | Default |
19+----------+----------------------------------------------------------------------+-------------------+---------+
20| serial   | Android serial, which device should be used for this command         | FL_ANDROID_SERIAL |         |
21| command  | All commands you want to pass to the adb command, e.g. `kill-server` | FL_ADB_COMMAND    |         |
22| adb_path | The path to your `adb` binary                                        | FL_ADB_PATH       | adb     |
23+----------+----------------------------------------------------------------------+-------------------+---------+
24
25+-------------------------------+
26|       adb Return Value        |
27+-------------------------------+
28| The output of the adb command |
29+-------------------------------+
30
31More information can be found on https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Actions.md

创建自定义扩展

通过内置的命令创建你需要的扩展,扩展名必须是全部小写且只能使用下划线分割词组,生成好的扩展文件会在 fastlane/actions 目录找到:

1$ fastlane new_action
2Must be lower case, and use a '_' between words. Do not use '.'
3examples: 'testflight', 'upload_to_s3'
4Name of your action: hello
5[15:33:15]: Created new action file './fastlane/actions/hello.rb'. Edit it to implement your custom action.

这块会占比较大的篇幅,尽情期待后续的展开。

引入外部扩展

这块其实也有两种方法可以引入,文件引入是官方教程提供的方法,第二种是我个人尝试出来的,第三种是最近版本才官方支持的。

1. 本地文件引入

自定义的扩展其实也算是本地文件引入的一种形式,当然位于其他路径的通过指定方法也能做到

1# 引入项目根目录 script/share_actions 路径
2actions_path '../script/share_actions'

2. rubygem 引入

不再建议使用本方法,请看第三种插件引入。

我在团队内部创建了一个自定义的扩展,仅限于团队内部使用而无法贡献社区,我只能采取封装成 ruby gem 包,通过 ruby 的 require 方式引入,最终可以完美支持,目前已在项目中使用大半年之久。最重要的是我是开源的:fastlane-qyer

1# 首先安装需要的 rubygem: gem install fastlane-qyer
2require 'fastlane-qyer'
3
4lane :upload do
5  qyer(api_key: '[token]')
6end

注意,使用 rubygem 引入的无法在 fastlane actions 中显示出来,也无法使用 fastlane action [name] 查看使用帮助。我猜想一是官方没有这样提供思路,二是就算你引入了 gem 也不是特别好判断里面的文件结构。

3. 插件引入

我注意到 1.93.0 增加了插件机制,很好的解决第二种出现的一些问题。大概看了一下主要是采用 Gemfile 的方式使用 Pluginfile 维护了引入第三方插件列表。实现原理还是属于第二种方法。

通过 fastlane search_plugins 查看当前支持的插件,并使用 fastlane add_plugins [name] 引入。

 1$ fastlane search_plugins
 2[16:04:33]: Listing all available fastlane plugins
 3
 4+--------------------------+---------------------------------------------------+-----------+
 5|                                Available fastlane plugins                                |
 6+--------------------------+---------------------------------------------------+-----------+
 7| Name                     | Description                                       | Downloads |
 8+--------------------------+---------------------------------------------------+-----------+
 9| ruby                     | Useful fastlane actions for Ruby projects         | 782       |
10| versioning               | Allows to work set/get app version directly       | 758       |
11|                          | to/from Info.plist                                |           |
12| branding                 | Add some branding to your fastlane output         | 716       |
13| instrumented_tests       | New action to run instrumented tests for android. | 590       |
14|                          | This basically creates and boots an emulator      |           |
15|                          | before running an gradle commands so that you can |           |
16|                          | run instrumented tests against that emulator.     |           |
17|                          | After the gradle command is executed, the avd     |           |
18|                          | gets shut down and deleted. This is really        |           |
19|                          | helpful on CI services, keeping them clean and    |           |
20|                          | always having a fresh avd for testing.            |           |
21| xamarin_build            | Build xamarin android\ios projects                | 582       |
22| appicon                  | Generate required icon sizes and iconset from a   | 509       |
23|                          | master application icon.                          |           |
24...
25| download_file            | This action downloads a file from an HTTP/HTTPS   | 171       |
26|                          | url (e.g. ZIP file) and puts it in a destination  |           |
27|                          | path                                              |           |
28+--------------------------+---------------------------------------------------+-----------+
29
30# 添加 sentry 插件
31$ fastlane add_plugin sentry
32[16:16:23]: Plugin 'fastlane-plugin-sentry' was added to './fastlane/Pluginfile'
33[16:16:23]: It looks like fastlane plugins are not yet set up for this project.
34[16:16:23]: fastlane will create a new Gemfile at path 'Gemfile'
35[16:16:23]: This change is neccessary for fastlane plugins to work
36Should fastlane modify the Gemfile at path 'Gemfile' for you? (y/n)
37y
38[16:16:29]: Successfully modified 'Gemfile'
39[16:16:29]: Make sure to commit your Gemfile, Gemfile.lock and Pluginfile to version control
40Installing plugin dependencies...
41Successfully installed plugins
42
43$ cat fastlane/Pluginfile
44# Autogenerated by fastlane
45#
46# Ensure this file is checked in to source control!
47
48gem 'fastlane-plugin-sentry'

更详细的继续期待后续报道,我要挖坑无数。

扩展的命令行调用

社区的力量果然是很强大的,陆续添加了那么多功能,早期用户表示不开心!嗯,由于社区的呼声和贡献目前可以通过命令调用扩展:

1# 使用 notification 扩展发送一个通知消息
2$ fastlane run notification message:"Hi macOS" title:"Fastlane Notification"
3[15:58:05]: --------------------------
4[15:58:05]: --- Step: notification ---
5[15:58:05]: --------------------------
6[15:58:05]: Result: true

辅助功能

自动更新

fastlane 提供一个方法 update_fastlane 用于对于自身的版本检查和更新,这个第一篇文章我也有提到过。它其实一个是一个扩展,使用 fastlane action update_fastlane 能够看到使用帮助。它有一个参数是可以指定检查特定的 fastlane 工具并进行更新,但其实它是使用 rubygems 进行对 gem 的更新,因此这块其实可以传入任何需要检查并更新的 gem:

1update_fastlane(tools:'fastlane,gym,match,cocoapods,rest-client')

环境变量

从 fastlane 的设计体系上在各个地方都加入了环境变量的支持,每个扩展的参数、以及扩展需要共享给其他扩展和任务读取的数据都是通过环境变量获取,如下是我收集的比较常用的列表:

环境变量来源说明备注
FASTLANE_USERcredentials_managerApple 开发者账户名验证通过后会保存 Keychain
FASTLANE_PASSWORDcredentials_managerApple 开发者账户密码验证通过后会保存 Keychain
FASTLANE_TEAM_IDCERT_TEAM_IDproducesighApple 团队 ID
DELIVER_USER<br >PRODUCE_USERNAMEdeliverproduceiTunesConnect 账户名
DELIVER_PASSWORDdeliveriTunesConnect 账户密码
MATCH_PASSWORDmatch证书加/解密密码
FASTLANE_XCODE_LIST_TIMEOUTfastlane_core获取 iOS Scheme 的超时时间默认 10s