Fastlane-iOS(调研篇)

  1. 云栖社区>
  2. 博客>
  3. 正文

Fastlane-iOS(调研篇)

awesome@qa 2018-03-07 19:19:43 浏览10798
展开阅读全文

Fastlane简介

FastLane是一种配置iOS和Android自动化Beta部署和发布的最简单的方法之一。它可以简化一些乏味、单调、重复的工作,像截图、代码签名以及发布App。只需一条命令就可实现从 Xcode 项目到 编译\打包\构建\提交审核。

本文做以下事情:

  •    fastlane 环境搭建
  •    导入ios的xcode项目
  •    对xcode项目进行fastlane初始化
  •    FastLane目录下的主要文件说明
  •    安装fastlane插件
  •    使用fastlane测试部署
  •    Fastlane文件格式的具体解析
  •    配置发布流程

      说明:本文将 Apple Dev Center 简称为 ADC; iTunes Connect 简称为 ITC

一、Fastlane 环境搭建

1) 检查ruby是否安装,低于2.0最好升级

  rvm -v                 #检查ruby是否安装正常
  rvm list known         #列出已知ruby版本
  rvm install ruby-xxxxx #安装一个最新ruby版本
  #如果报错的话   
  brew install opensslreinstall|
  install ruby-xxxxx     #注意修改xxxxxx

2) 检查 Xcode是否安装

  $ xcode-select --install

如果未安装,终端会开始安装,如果报错误:command line tools are already installed, use "Software Update" to install updates.代表已经安装。

3) 安装 fastlane

  $ sudo gem install -n /usr/local/bin Fastlane

  $ fastlane -v  #检查版本 Fastlane

 fastlane installation at path:

  /Users/iwm/.rvm/gems/ruby-2.3.4@global/gems/fastlane-2.64.1/bin/fastlane

  fastlane 2.64.1

   OK,安装完成

4) 配置环境变量

  找到shell profile,一般在 ~/.bashrc, ~/.bash_profile or ~/.zshrc文件里,取决于你的系统,文件的末尾处添加:

  export LC_ALL=en_US.UTF-8
  export LANG=en_US.UTF-8

二、导入ios的xcode项目 ,需找rd要  @陈卓

三、对xcode项目进行fastlane初始化

1) fastlane init

  终端,cd到你的工程目录,然后执行fastlane init:

  如果期间报错 Connection reset by peer - SSL_Connect,就需要执行:

  $ brew update && brew install ruby         # 重装

  $ sudo gem install -n /usr/local/bin Fastlane

  # 然后重新执行

  $ fastlane init

2) 初始化执行的过程

image2017-12-3%2015%3A19%3A49.png?versio

a.期间会遇到:在 "Your Apple ID" 这一步输入苹果开发者账号,会让输入 Apple ID 账号密码(这个信息会存在钥匙串中,后续使用无需再输入密码

image2017-12-3%2015%3A20%3A14.png?versio

b.在“Please confirm the above values”这一步,是问该app是否需要在iTC和ADC中创建,输入 y会自动检测是否需要创建,然后,fastlane 会进行一系列的初始化操作,包括下载 App Store 上的元数据和截屏文件。

image2017-12-3%2015%3A20%3A32.png?versio

c.初始化执行后的结果中肯定会被创建的是Appfile和Fastfile。如果Deliverfile,screenshots和metadata目录没被创建,可以运行deliver init来创建。
d.过程中可以安心的输入密码,所有的密码都加密保存在系统的Keychain里。

3) 初始化执行的结果:

a.如果上一步输入N,则没有在 ADC 和 ITC 创建相应信息,初始化完成后的fastlane目录,如下图:
该目录下没有zh-hans文件夹,当然也可以后续创建,执行如下操作即可:
$ fastlane produce init

 image2017-12-3%2015%3A20%3A59.png?versio

b.若上一步输入y,则在 ADC 和 ITC 中创建了相应信息,初始化完成后的fastlane目录,如下:

image2017-12-3%2015%3A21%3A19.png?versio

四、FastLane目录下的主要文件说明

1)Appfile: 存储App公共信息,存放app_identifier,apple_id和team_id用
2)Fastfile:配置管理 lane,自动化执行配置文件
3)这里有个小问题,iTC和ADC中的Team ID是不一样的,在fastlane init中只会自动在Appfile里写入ADC的team_id,所以在这个过程中会不停的问iTC的Team ID,所以在创建完Appfile后,手动在里面添加itc_team_id。
4)Deliverfile:配置应用在 ITC 中的各种信息,和 ICC 中的数据是一一对应的
5)metadata:包含应用在 ITC 中的各种信息
6)screenshots:包含截图数据需要注意的是,metadata 和 Deliverfile,都可以配置 ITC 的数据,但后者优先级高.正如下图:

image2017-12-3%2015%3A21%3A44.png?versio

五、安装fastlane插件

Fastlane的插件是一个或者一组action的打包,单独发布在fastlane之外。
查看所有插件:$ fastlane search_plugins
需安装以下两个插件:
1)fastlane-plugin-versioning => 用来修改build版本号和version版本号。
Fastlane内嵌的actionincrement_build_number使用的是苹果提供的agvtool,agvtool,在更改Build的时候会改变所有target的版本号。这时如果在一个工程里有多个产品的话,每次编译,所有的Build都要加1,最后就不知道高到哪里去了。有了fastlane-plugin-versioning不仅可以指定target增加Build,而且可以按照「语义化版本」规范增加Version,当然也可以直接设定Version。
PS:定义Build时。直接定义成纯数字,比如100起,每次编译的时候让它自动加一。
2)fastlane-plugin-firim => 直接把AdHoc或者InHouse打包的ipa上传到fir.im,供测试下载。

3)安装上面的插件

$fastlane add_plugin [name]  # 安装方法
$fastlane add_plugin versioning
$fastlane add_plugin firim

六、使用fastlane测试部署

构建测试应用,编辑fastfile:

lane :beta do

    gym(scheme: "MyApp",

        workspace: "MyApp.xcworkspace",

        include_bitcode: true)

end

测试运行lane(任务):

$  fastlane beta

如果顺利执行的话,将会在当前文件目录看到一个 MyApp.ipa 文件和对应 MyApp.app.dSYM 文件测试成功。

七、Fastlane文件格式的具体解析

1) Appfile格式:

备注:选择sublime打开,把当前显示样式设置为Ruby

Appfile可以为每个lane提供不同的 app_identifier, apple_id 和 team_id,例如:这里就是为Fastfile中定义的:inhouse设置单独的信息。

app_identifier "com.xxx.xxx" # app的bundle identifier

apple_id "xxx@xxx.com" # 你的Apple ID

team_id "XXXXXXXXXX" # Team ID


for_lane :inhouse do

  app_identifier "com.bbb.bbb"

  apple_id "bbb@bbb.com"

  team_id "AAAAAAAAAA"

end

2) Deliverfile格式:

app_identifier "com.xxxx.xxxx"   # The bundle identifier of your app

username "xxxxx@xxxx.com"       # your Apple ID user

3) Fastfile格式:

Fastfile就是我们打包,发布到fir,testFlight,appstore等等操作的具体配置文件,Fastfile管理所创建的 lane,它的格式是这样的:

# 自动更新fastlane 工具              

# update_fastlane

# fastlane_version => 指定 fastlane的最小版本,在每次执行之后会检查是否有新版本,如果有会在末尾追加新版本提醒

fastlane_version "2.30.1"

# default_platform => 默认使用平台是 ios,也就是说文件可以定义多个平台

default_platform :ios

platform :ios do

  before_all do

    # ENV["SLACK_URL"] =”https://hooks.slack.com/services/...

    cocoapods

  end

# desc => 一个lane(任务)的描述,一般说明这个lane是做什么的

  desc "Runs all the tests"

  lane :test do     #一个lane就是一个任务,里面是一个个的action组成的工作流。

    scan

  end


  desc "提交一个新的Beta版本到 Apple TestFlight"

  desc "This will also make sure the profile is up to date"

  lane :beta do

    # match(type: "appstore") # more information: https://codesigning.guide

    gym(scheme: "Docment") # Build your app - more options available

    pilot


# sh "your_script.sh"

    # You can also use other beta testing services here (run `fastlane actions`)

  end


  desc "部署一个新版本到App Store"

  lane :release do

    # match(type: "appstore")

    # snapshot

    gym(scheme: "Docment") # Build your app - more options available

deliver(force: true)

# frameit

  end


  # 你可以定义自己的lane

  #执行lane成功后的回调

  after_all do |lane|

    # slack(

    # message: "Successfully deployed new App Update."

    # )

  end


  # 如果流程发生异常会走这里并终止

  error do |lane, exception|

    # slack(

    #   message: exception.message,

    #   success: false

    # )

  end

end

八、配置发布流程

可以把二进制发布到三个地方:      

1) 发布到TestFlight

a. 生成证书和 Provisioning Profile

用sublime打开 Fastlane 文件,将内容替换为:

# Minimum version of fastlane

fastlane_version "1.32.1"

default_platform :ios

platform :ios do 

 # 1. 用于描述这个 lane 的工作。一个 lane 是一个按顺序执行的工作流。

  desc "Creating a code signing certificate and provisioning profile"

 # 2. 执行名为 provision 的 lane。

  lane :provision do

    # 3. produce 用指定的 ID、name、语言和版本号创建一个可用于 iTunes Connect 和 Developer Portal 的 app。

    produce(

      app_name: 'ENTER_A_UNIQUE_APP_NAME_HERE', #将 ENTER_A_UNIQUE_APP_NAME_HERE 替换成一个唯一的 App 名字

      language: 'English',

      app_version: '1.0',

      sku: '123abc'

    )

    # 4. cert 创建一个新的私钥和签名请求,下载、安装生成的证书并导入到钥匙串。

    cert

    # 5. sigh 创建了一个 provisioning profile。force 参数为 true,则每次运行时都会创建新的 provisioning profile,这样就可以保证每次都使用正确的代码签名证书。

    sigh(force: true)

 end

  error do |lane, exception|

    # This block is called, if there was an error running a specific lane.

 end

end

注意:sigh 默认创建的是 App Store 的发布 profile。如果想创建 ad hoc profile,需要使用 sigh(adhoc:true)。如果是开发 profile 则使用 sigh(development:true)。

此时创建了第一个 lane,保存文件,打开终端进入到项目文件夹,输入命令:

fastlane provision

这会让 fastlane 执行 provision lane。大约一分钟左右,fastlane 会问你 iTunes Connect 密码,它会保存到你的 Mac 的钥匙串里。

注意:如果看到错误,例如 “Creation of apps of this type is not available”, 则请登录 iTunes Connect,看一下是否有某些更新的协议需要你确认。

在进行下一步之前,还需要在 Xcode 中进行某些修改。打开 项目的xcode中,切换到 General 页。将 bundle identifier 修改为初始化 fastlane 时输入的 App ID。

在 Build Settings > Code Signing > Provisioning Profile 设为 “ <新的 app ID> AppStore”。然后在 Code Signing Identity 选择和这个 provisioning profile 相对应的 ID:

注意:code signing identity 应该和 provisioning profile 中的 identities 相匹配。这样,当 gym 编译 IPA 文件时会使用新创建的 provisioning profile。

登录进 iTunes Connect,此时app 已经创建好了;

app-itunes-connect.pngb. 简化屏幕截图工作

打开 fastlane 文件夹下的 Snapfile 文件,将内容替换为:

# A list of devices you want to take the screenshots from

devices([

  "iPhone 4s",

  "iPhone 5",

  "iPhone 6",

  "iPhone 6 Plus"

])

# A list of supported languages

languages([

  'en-US',

  'fr-FR'

]) 

# Where should the resulting screenshots be stored?

screenshots_path "./screenshots"

# Clears previous screenshots #会清空上次创建的截屏图。

clear_previous_screenshots

# Latest version of iOS

ios_version '9.1'

保存、关闭文件。打开 Fastfile 文件,在 error do |lane, exception| 一句上面加入:

desc "Take screenshots"
lane :screenshot do
  snapshot
end

这里创建了一个新的 lane,名为 screenshot,并使用 snapshot 命令根据在 Snapfile 文件中输入的配置创建截屏图。保存文件,在终端窗口中输入:

fastlane screenshot

注意:snapshot 为了截取屏幕,需要调用 Snapfile 中列出的设备类型所对应的模拟器。如果缺少了一种或多种模拟器,你要 Xcode 中通过 Window\Devices 菜单来添加相应的模拟器。左下角的 + 号按钮就是用来添加新模拟器的。

此时,项目文件夹下面的 fastlane 目录,会看到多了一个 screenshots 子目录,还会发现一个 screenshots.html 文件。打开这个文件,可以浏览所有的屏幕截图。

c. 创建 IPA

打开 Fastfile,在 screenshot lane 之后添加:

desc "Create ipa" lane :build do gym end

这里创建了一个 lane 叫做 build,它使用 gym 命令创建签名的 ipa 文件。保存 Fastfile,打开终端窗口,进入 项目文件夹,输入命令:

fastlane build

这会执行 build lane,开始编译。一旦编译完成,打开 mZone 项目文件夹。你会看到签好名的 ipa 文件:

d. 无缝上传

要上传屏幕截图、元数据和 IPA 文件到 iTunes Connect,可以使用 deliver 命令,它已经包含在 fastlane 中了。

首先,需要用 deliver 来初始化项目。在终端窗口,进入项目文件夹输入命令:

deliver init

执行完成,在 summary 栏中,你会看到 deliver 已经自动检测到 ipa 文件和屏幕截图的位置。打开 Fastfile 在 build lane 后面添加:

desc "Upload to App Store" lane :upload do deliver end

在终端窗口中,输入命令:

fastlane upload

通过这个命令,fastlane 会创建一个 html 文件,它将以 html form 表单的形式上传文件。登录你的 iTunes Connect。所有的屏幕截图、描述、版本 build 1.0 都应当上传就绪。

剩下来的事情就是点击 “Submit for Review” 按钮。 deliver 可以自动提交 app 去审核,但你需要修改 upload lane:

desc "Upload to App Store and submit for review"

lane :upload do

deliver(

submit_for_review: true

)

end

2) 发布到App Store

lane :deploy do

  # 如果你用 pod install

  cocoapods

  # 如果你没有申请adhoc证书,sigh会自动帮你申请,并且添加到Xcode里

  # 不带adhoc参数,sigh会自动生成App Store证书(公司或个人帐户)

  sigh

  # 以下两个action来自fastlane-plugin-versioning,

  # 第一个递增 Build,第二个设定Version。

  # 如果有多个target,就必须指定target的值,否则它会直接找找到的第一个plist修改

  #建议每一个打的包的Build都要不一样,这样crash了拿到日志,可以对应到ipa上

  increment_build_number_in_plist(target: [target_name])

  increment_version_number_in_plist(

    target: [target_name],

    version_number: '7.1.3'

    )

   #gym用来编译ipa,指定输出目录

  gym(

    output_directory: './build',

    )

  # 上传所有信息到App Store

  deliver(force: true)

end

3) 自定义发布到App Store版本

# You can define as many lanes as you want

desc "Deploy a new version to the App Store"

lane :release do |op|

    increment_version_number(version_number: op[:version]) #根据入参version获取app版本号

    increment_build_number(build_number: op[:build])  #将build号设置与app版本号相同

    # 设置app的info.plist文件项

    set_info_plist_value(path: "./xxx/Info.plist",  #info.plist文件目录

                        key: "UIFileSharingEnabled", 

                                              # key,将plist文件以Source Code形式打开可查询对应的key

                        value: false)   # value


    # 设置自定义plist文件项,用于给app配置不同的服务器URL

    set_info_plist_value(path: "./xxx/hostAddress.plist",

                        key: "host",

                        value: "https:/zhengshiServer:xx/xxx/xxx")           


    # 更新Provisioning Profile

    # 在项目当前目录下创建provisions文件夹,并将App Store版本的.mobileprovision文件保存在里面,名称随意。

    update_project_provisioning(profile: "./provisions/appstore.mobileprovision")


    # 更新项目团队

    update_project_team(path: "xxx.xcodeproj",

                  teamid: "5JC8GZ432G")


    # 开始打包

    gym(use_legacy_build_api: true,

        output_name: "appstore",             # 输出的ipa名称

        silent: true,                                    # 隐藏没有必要的信息

        clean: true,                                   # 在构建前先clean

        configuration: "Release",                              # 配置为Release版本

        codesigning_identity: "iPhone Distribution: xxx Co.,Ltd. (5JC8GZ432G)",  # 代码签名证书

        buildlog_path: "./fastlanelog",                      # fastlane构建ipa的日志输出目录

        output_directory: "/Users/xxx/Desktop")       # ipa输出目录

end

 4) 自定义发布到Development

desc "Build a new version use the ceshi"

lane :ceshi do |op|

    increment_version_number(version_number: op[:version])

increment_build_number(build_number: op[:build])

 

    set_info_plist_value(path: "./xxx/Info.plist",

                        key: "UIFileSharingEnabled",

                        value: true)

 

    set_info_plist_value(path: "./xxx/hostAddress.plist",

                        key: "host",

                        value: "https:/ceshiServer:xx/xxx/xxx")

 

    # 将Development版本的.mobileprovision文件保存在里面,名称随意。

    update_project_provisioning(profile: "./provisions/development.mobileprovision")

 

    update_project_team(path: "xxx.xcodeproj",

                  teamid: "5JC8GZ432G")

 

    gym(use_legacy_build_api: true,

        output_name: "ceshi",

        silent: true,

        clean: true,

        configuration: "Debug",

        buildlog_path: "./fastlanelog",

        codesigning_identity: "iPhone Developer: xxx (xxxxxxxxxx)",

        output_directory: "/Users/xxx/Desktop"

  )

end

    #批量处理

desc "build all version ipa"

lane :all do |op|

              t = op[:version]

              ceshi version:t

              release version:t

    end

5) 执行

最后,只需在终端(相关项目目录下)轻轻敲入:

fastlane ceshi version:1.0.0 build:1.0.1   // 打包ceshi环境ipa,app版本号为1.0.0,build为1.0.1

fastlane release version:1.0.0 build:1.0.1 //打包App Store版本ipa,app版本号为1.0.0,build为1.0.1

fastlane all version:1.0.0 build:1.0.1   // 打包ceshi、App Store版本ipa,app版本号为1.0.0,build为1.0.1

6) 优化

我们可以在 Fastfile 文件中添加一个函数来设置version号和build号,使得以上AppStore版本与Development版本配置使用同一函数,如下:

default_platform :ios

def prepare_version(options)

    increment_version_number(

        version_number: options[:version]

    )

    increment_build_number(

        build_number: options[:build]

    )

end

然后可以在一个lane中使用这个函数:

lane :appstore do |options|

   ···

    prepare_version(options)

   ···

end

然后执行这个lane

$ fastlane appstore version:2.4.0 build:2.0

九、TODO:

  • 调研ios-fastlane的安全性        
  • 调研fastlane在其他公司的使用情况        
  • ios-fastlane踩坑篇        
  • ios-fastlane问题篇 

十、参考文档:

网友评论

登录后评论
0/500
评论
awesome@qa
+ 关注