iOS 持续交付之 Fastlane

小目标:使用Jenkins一键构建,并自动上传到App Storehtml

1、为何选择 Fastlane

why fastlane

fastlane是为iOSAndroid应用程序自动化测试部署和发布的最简单方法。🚀它处理全部繁琐的任务,如生成屏幕截图,处理代码签名以及发布应用程序。ios

使用场景

  • 提交时执行测试(包括单元测试和集成测试)。
  • 构建并分发内部测试,公开测试版本。
  • 构建生产版本并上传至 ITC(包括更新配置文件,建立新的屏幕截图,上传应用并提交审核)。

工具集

fastlane 将以下的工具套件有机地结合起来,从管理证书到单元测试,从编译打包到上传发布,都能经过命令行轻松完成.该套件支持与 JenkinsCocoaPods,xctools 等其余第三方工具的集成,而且可以定义多个通道(lanes)以支持不一样的部署目标。git

  • 测试工具
    • scan:自动运行测试工具,能够生成漂亮的HTML报告。
  • 生成证书、配置工具
    • cert:自动建立iOS代码签名证书(.cert文件)。
    • sigh: 建立、更新、下载和修复 provisioning profiles,支持App Store, Ad Hoc, Development和企业profiles。
    • pem:自动生成、更新推送配置文件。
  • 截图、上传、描设备边框
    • deliver: 上传截图、元数据、App到iTunesConnect。
    • snapshot: 依靠 UI Test 完成截图。
    • frameit: 快速地把应用截图放入设备框里。
  • 自动化编译工具
    • gym: 编译、打包iOS app,生成签名的ipa文件 。
  • App 公测工具
    • pilot:管理TestFlight测试用户,上传二进制文件。
    • firim:管理firim。

2、准备工做,很重要的哟

  1. 配置当前设备环境,最新的fastlane(2.75.1)须要2.1以上的ruby版本,正常的版本低点的,也是要求2.0以上的。由于fastlane工具是使用ruby写的。版本太低的建议安装rvm来升级rubygithub

    curl -L get.rvm.io | bash -s stable  
    
    source ~/.bashrc  
    source ~/.bash_profile 
    
    # 检测是否安装成功
    rvm -v
    复制代码
  2. 设置环境变量,fastlane须要设置一些环境变量才能正确运行,若是当前的语言环境没有设置为UTF-8,会致使构建和上传的时候出现问题。在~/.bashrc, ~/.bash_profile 或者 ~/.zshrc 文件下添加以下内容:swift

    export LC_ALL=en_US.UTF-8
    export LANG=en_US.UTF-8
    复制代码
  3. 安装Xcode命令行工具 xcode-select --install,若是已经安装会提示xcode-select: error: command line tools are already installed, use "Software Update" to install updatesxcode

  4. 建立App ID证书,在iTunes connect 建立一个用于测试的 app。ruby

  5. 安装fastlanebash

  6. 建立一个测试demo。app

    1. 并将其scheme设置为shared,否则fastlane init的时候会失败。curl

    2. 设置好签名配置文件。

    3. 为app添加icon

    4. 修改devicesiPad或者iPhone

3、实践

fastlane init

  1. cd 到项目目录下,对于ruby安装程序,使用命令 sudo fastlane init。(swift使用fastlane init swiftSwift安装仍在测试阶段。有关更多信息,请参阅Fastlane.swift文档。 )

  2. 会问你想使用fastlane作什么?这里咱们输入3,自动发布到Apple Store

    执行过程当中会要求你输入Apple开发证书的Apple ID,若是有多个Team,会让你选择team。

  3. 接着会问是否想用fastlane来管理你的app metadata

    • 输入yfastlane则会下载现有的元数据和屏幕截图。若是咱们编辑了download下来的.txt文件,在使用fastlane上传app到iTunes connect的时候也会将这些内容上传到iTunes connect

    • 输入n,不作任何操做,仍然能使用fastlane上传app到App Store

  4. 若是最后出现fastlane release,就表示init成功了。

  5. 此时项目目录下会多出一个fastlane的文件夹。

    若是Deliverfilescreenshotsmetadata目录没被建立,能够运行deliver init来建立。

Deliverfile文件里,添加force true,否则会在上传到iTunes connect的时候会弹出一个Preview.html网页。

使用Gemfile

  1. 在项目根目录下touch一个Gemfile文件,添加如下内容

    source "https://rubygems.org"
    gem "fastlane"
    复制代码
  2. 执行以下命令:

    # 安装bundler
    sudo gem install bundler
    
    # 更新 bundle,成功以后会生成一个版本控制的Gemfile.lock文件
    [sudo] bundle update
    复制代码
  3. 执行命令:bundle exec fastlane [lane_name],执行lane_name脚本。这里的lane_name是脚本的名称,咱们能够理解为函数名,若是咱们只执行bundle exec fastlane命令,则会有一个让咱们选择的地方,选择须要执行的脚本。

    会将项目名,ipa存放的路径,app_identifier等一系列信息打印出来。

    ipadYSM文件都存放在项目根目录。

    紧接着会自动上传metadataipaiTunes Connect

    最后会输出每一个脚本执行所消耗的时间(s)。

进阶

若是只是很简单的上传到iTunes connect,上面的操做就能够知足。

若是咱们是多个target或者须要配置一些ITC上面的内容,则须要进一步的深刻。

metadata

metadata是包含应用在ITC上面的各类信息,可使用它配置咱们的ITC,建议使用Deliverfile

screenshots

屏幕截图数据。

Appfile

存储App信息,好比Apple IDbundle ID等信息。

Deliverfile

交付文件。在这个文件里面能够设置iTunes connect的全部配置项,例如:

  • release_notes,此版本新增内容。
  • copyright,版权信息。
  • submit_for_review,上传完成后是否直接提交新版本进行审查。
  • force,跳过HTML报告文件验证。
  • ...

请在设置release_noressupport_urlprivate_url等配置的时候,采用hash的方式写,国家代码,例如:

release_notes(
	# 中国
	'zh-Hans' => ENV['RELEASE_NOTES'],
	# 澳大利亚
	'en-au' => ENV['RELEASE_NOTES_AU'],
	# 美国
	'en-us' => ENV['RELEASE_NOTES_US']
)
复制代码

Fastfile

自动化脚本配置文件。 是咱们脚本的入口,全部的事件驱动都是在这个文件来调度的。

default_platform(:ios)

platform :ios do

	desc "demo upload_to_app_store"
	lane : Archive_TargetA do |options|
		scheme = options[:scheme]
		date = Time.new.strftime("%Y%m%d-%h%M")
		
		# export_method 支持 app-store, ad-hoc, package, enterprise, development
		gym(
			scheme: "#{scheme}",
			output_name: "#{scheme}-#{date}.ipa",
			clean: true,
			export_method: 'app-store',
		)

		# upload_to_app_store
		deliver # 当deliverfile为空的时候,同 upload_to_app_store 做用同样
	end
end

复制代码

cd到项目根目录执行命令:bundle exec fastlane Archive_TargetA scheme:"CDDemo",后面的scheme是带的参数。

Multi-Target

若是咱们须要配置多个target进行打包的话,咱们可使用环境变量,来进行配置。假如咱们如今有两个targettargetAtargetB,则咱们须要建立两个.env文件,例如.env.targetA,.env.targetB,放在Fastfile文件同级目录下

.env文件里面咱们能够配置一些不一样的内容(非公共),好比app_identifierrelease_notes等等。截图以下:

AppfileDeliverfileFastfile等文件,咱们均可以直接使用.env文件里面的内容。

Appfile

# Appfile

#The bundle identifier of your app
app_identifier ENV['APP_IDENTIFIER']

# Your Apple email address
apple_id ENV['APPLE_ID'] 

# Developer Portal Team ID
team_id ENV['TEAM_ID']

复制代码

Deliverfile,请在设置release_nores、support_url、private_url等配置的时候,采用hash的方式写。

# app_identifier
app_identifier ENV['APP_IDENTIFIER']

# 用户名,Apple ID电子邮件地址
username ENV['APPLE_ID']

# 团队ID
team_id ENV['TEAM_ID']

# 团队name
team_name ENV['TEAM_NAME']

# copyright
copyright ENV['COPYRIGHT']

# 关键字
keywords(
	'zh-Hans' => ENV['KEYWORDS'],
)

# 新版本修改记录
release_notes(
	# 中国
	'zh-Hans' => ENV['RELEASE_NOTES'],
	# 澳大利亚
	'en-au' => ENV['RELEASE_NOTES_AU'],
	# 美国
	'en-us' => ENV['RELEASE_NOTES_US']
)

# 支持网址
support_url(
	# 中国
	'zh-Hans' => ENV['SUPPORT_URL'],
	# 澳大利亚
	'en-au' => ENV['SUPPORT_URL_AU'],
	# 美国
	'en-us' => ENV['SUPPORT_URL_US']
)

# 隐私政策网址 国家代码 https://www.cnblogs.com/Mien/archive/2008/08/22/1273950.html
privacy_url(
	# 中国
	'zh-Hans' => ENV['PRIVACY_URL'],
	# 澳大利亚
	'en-au' => ENV['PRIVACY_URL_AU'],
	# 美国
	'en-us' => ENV['PRIVACY_URL_US']
)

# 上传完成后提交新版本进行审查
submit_for_review false

# 跳过HTML报告文件验证
force true

# 启用iTC的分阶段发布功能 灰度发布
phased_release true

# 应用审核小组的联系信息 app 审核信息
app_review_information(
  first_name: "xx",
  last_name: "xx",
  phone_number: "+86 18888888888",
  email_address: "xxxx",
  demo_user: "test1@test.com",
  demo_password: "test123"
)

...
复制代码

Fastfile文件里面使用环境变量,跟上面略有不一样。在Fastfile里面,咱们须要告诉lane 要使用那个.env文件,这时候咱们须要使用sh脚本命令的形式来调用一个lane 后面跟上--env 环境变量文件名,此时调用的lane 不能声明为private_lane,调用方式以下:

lane :releaseDemo2 do
	# 无参数
	sh "fastlane Archive_TargetA --env TargetA"
	
	# 有参数
	sh 'fastlane Archive_TargetA type:\'哈哈哈哈\' --env TargetA'
end


外部直接调用(带参数)
bundle exec fastlane Archive_TargetA type:"haha" --env TargetA

复制代码

而后咱们在Archive_TargetA lane 里面使用ENV['xx']方式,读取出来的内容就是从.env.TargetA文件读取出来的。同理,deliver Action 对应的DeliverFile文件里面的内容也是从.env.TargetA文件读取出来的。

private_lane : Archive_TargetA do |options|
	scheme = ENV['SCHEME'] # 这时候读取出来的'scheme'就是'TargetA',从'.env.TargetA'读取出来的

	# export_method 支持 app-store, ad-hoc, package, enterprise, development
	gym(
		scheme: "#{scheme}",
		output_name: "#{scheme}.ipa",
		clean: true,
		export_method: 'app-store',
	)

	deliver # 这时候deliverfile里面读取的内容就是从'.env.TargetA'文件读取的
end
复制代码

lane之间的调用

跟咱们本身写方法调用同样,例如:

desc "打包统一入口"
lane :Archive do |options|
	# 若是咱们传入的参数'type'是targetA,那么咱们就执行Archive_TargetA 这个lane。。。
	type = options[:type]
  	if type == "TargetA"
    	Archive_TargetA(options)
  	elsif type == "TargetB"
        Archive_TargetB(options)
	else
    	Archive_TargetA(options)
  	end
end
复制代码

系统级lane

fastlane 默认有 lane。

  • before_all,就是在执行一次脚本以前首先执行的代码,咱们能够在这里面执行一些公共的东西,好比git_pullcocoapods

    before_all do
      # 检出到 Developer 分支
      sh 'git checkout Developer'
      git_pull
      cocoapods(repo_update: true)
    end
    复制代码
  • after_all, 成功结束以后,处理共有的后置逻辑。

  • before_each,每次执行 lane 以前都会执行一次。

  • after_each,每次执行 lane 以后都会执行一次。

  • error,在执行上述状况任意环境报错都会停止并执行一次。

执行顺序

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

Error

  • 出现 Command timed out after 10 seconds on try 1 of 4, trying again...,在fastlane文件开头加上:

    ENV["FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT"] = "180"
    ENV["FASTLANE_XCODE_LIST_TIMEOUT"] = "180"
    复制代码

插件

  • versioning,用来修改build版本号和version版本号。Fastlane内嵌的actionincrement_build_number使用的是苹果提供的agvtool,agvtool在更改Build的时候会改变全部target的版本号。这时若是你在一个工程里有多个产品的话,每次编译,全部的Build都要加1,最后就不知道高到哪里去了。fversioning不只能够指定target增长Build,并且能够按照「语义化版本」规范增长Version,固然也能够直接设定Version。
  • firim,直接把AdHoc或者InHouse打包的ipa上传到fir.im,供测试下载。

自定义插件

插件安装格式

fastlane add_plugin [name],须要到项目根目录下执行。

fastlane update_plugins 插件更新,同上,须要cd到项目根目录下。

注意

  • 保持打包机器的Xcode 和 证书是最新的。
  • 使用脚本命令形式调用的时候不能设置成private_lane
  • private_lane 表示私有lane,使用bundle exec fastlane命令,声明为 private_lane的是否是显示出来的,使用脚本命令形式调用的时候不能设置成private_lane

其它

能够直接在lane里面执行git命令,例如sh 'git checkout Developer',检出Developer分支。

因为本人的水平有限,不免会有错误和疏漏,欢迎 issue 指正。若是你们在Fastlane的使用上,有更好的案例,也欢迎交流和分享。

参考文章

Example

转载请注明出处!

相关文章
相关标签/搜索