1、安装fastlane
gem install fastlane
2、配置fastlane
打开命令行,cd到你的工程根目录运行
fastlane init
这时候fastlane会提示你,你想要用fastlane做什么,fastlane会根据你的选择生成对应的文件配置,这里选择2
接下来会提示你输入AppleID的用户名和密码
看到"Successfully generated fastlane configuration"
说明设置fastlane成功了,这时候在项目根目录下fastlane会为我们生成两个很重要的文件,后面的大部分时间我们都将用来编辑Fastfile来完成我们的自动化打包流程
打开Appfile,可看到fastlane为我们创建了appid相关的信息,这里创建了apple_id,在后续使用sigh或者match(fastlane提供的一个用来管理证书的action)管理证书的时候将不用再输入appleID
app_identifier("com.yourapp.client") # The bundle identifier of your app
apple_id("yourAppid@company.com") # Your Apple email address
itc_team_id "****" # iTunes Connect Team ID
team_id "****" # Developer Portal Team ID
# For more information about the Appfile, see:
# https://docs.fastlane.tools/advanced/#appfile
3、设置环境变量
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
4、使用fastlane构建app
打开Fastfile文件,根据需求构建打包脚本,下面是我的脚本
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
# https://docs.fastlane.tools/actions
#
# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane
default_platform(:ios)
# 工程文件路径
PROJECT_FILE_PATH = './FastLaneDemo.xcodeproj'
# plist文件路径
INFO_PLIST_FILE_PATH = './FastLaneDemo/SupportFiles/Info.plist'
# app名
APP_NAME = 'FastLaneDemo'
# scheme名
SCHEME_NAME = 'FastLaneDemo'
# workspace名
WORKSPACE_NAME = 'FastLaneDemo.xcworkspace'
# ipa导出路径
OUTPUT_DIRECTORY = '/Users/Shared/FastLaneDemo_iOS/'
# fastlane流程开始
platform :ios do
# desc "Description of what the lane does"
# lane :custom_lane do
# # add actions here: https://docs.fastlane.tools/actions
# end
before_all do
# 同步源码
#git_pull
end
# 根据options参数进行打包
lane :buildExportIpa do |options|
evn = options[:value] # 获取打包参数deubg/release
now = Time.now.strftime("%Y%m%d%H%M") # 获取当前时间
versionNumber = get_info_plist_value(path: "#{INFO_PLIST_FILE_PATH}", key: "CFBundleShortVersionString") # 获取version版本号
buildNumber = get_info_plist_value(path: "#{INFO_PLIST_FILE_PATH}", key: "CFBundleVersion") # 获取build版本号
fullIpaName = "#{APP_NAME}" + "_v#{versionNumber}" + "_Build#{buildNumber}" + "_#{now}" # ipa名
dSYMFileName = "#{OUTPUT_DIRECTORY}/" + "#{APP_NAME}" + "_v#{versionNumber}" + "_Build#{buildNumber}" + "_#{now}"
# 设置环境参数
if evn == "Debug"
fullIpaName = "#{fullIpaName}" + "_Debug.ipa"
dSYMFileName = "#{dSYMFileName}" + "_Debug.app.dSYM.zip"
exportMethod = "development"
else
fullIpaName = "#{fullIpaName}" + "_Release.ipa"
dSYMFileName = "#{dSYMFileName}" + "_Release.app.dSYM.zip"
exportMethod = "ad-hoc"
end
# Note:这个action会检查你当前使用的git仓库是不是从指定git分支上check out的,比如,
# 一般我们会在特定的分支上发布应用,此时如果不是在正确的分支上,则该action会终止lane
ensure_git_branch(
branch: 'feature_ios' # 指定分支名,可用分支全名,也可用正则表达式自动匹配
)
# Note: 根据参数编译打包导入ipa
gym(
workspace: "#{WORKSPACE_NAME}", # 指定.xcworkspace文件的路径。
scheme: "#{SCHEME_NAME}", # 指定项目的scheme名称
clean: 'true', # 在打包前是否先执行clean。
output_directory: "#{OUTPUT_DIRECTORY}", # 指定.ipa文件的输出目录,默认为当前文件夹。
output_name: "#{fullIpaName}", # 指定生成的.ipa文件的名称,应包含文件扩展名。
configuration: "#{evn}", # 指定打包时的配置项,默认为Release
include_symbols: 'true', # 是否导出符号表
include_bitcode: 'false', # 是否使用bitcode打包
export_method: "#{exportMethod}", # 指定导出.ipa时使用的方法,可用选项:app-store, ad-hoc, package, enterprise, development, developer-id
)
# 删除dSYM文件
if File.exist?("#{dSYMFileName}")
puts "file dSYMFileName is found"
File.delete("#{dSYMFileName}")
end
fullIpaName # 返回包名,注意:写在最后一行
end
# 发布到apphost
lane :upload_apphost do |options|
ipaName = options[:value]
# 执行shell脚本发布到apphost
`curl --form plat_id=2 --form token=4d355607a661b0e35973301a689ac6c3d02bf4b2 --form releaseNote="http://www.tuandai888.com/plugins/viewsource/viewpagesrc.action?pageId=15386675" --form file=@#{OUTPUT_DIRECTORY}/#{ipaName} http://192.168.13.169:3000//api/pkgs`
end
# RN文件打包为bundle
lane :RNArchive do |options|
evn = options[:value]
puts Dir.getwd
if evn == "Debug"
`
cd ../..
npm install
react-native bundle --entry-file index.js --platform ios --dev true --bundle-output ./ios/bundle/main.jsbundle --assets-dest ./ios/bundle
cd ios/
`
elsif
`
cd ../..
npm install
react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ./ios/bundle/main.jsbundle --assets-dest ./ios/bundle
cd ios/
`
end
end
# 不同环境的打包发布流程
# 发布Release包
lane :upload_Release do
# 更新签名证书
sigh(adhoc: true, output_path: "/tmp")
# RN资源打包
RNArchive(value: "Release")
# 编译导出ipa,返回ipa名
ipaName = buildExportIpa(value: "Release")
# 发布到apphost
upload_apphost(value: ipaName)
# 钉钉通知
DingdingRobot(value: ipaName)
end
# 发布Debug包
lane :upload_Debug do
# 更新签名证书
sigh(development: true, output_path: "/tmp")
# RN资源打包
RNArchive(value: "Debug")
# 编译导出ipa,返回ipa名
ipaName = buildExportIpa(value: "Debug")
# 发布到apphost
upload_apphost(value: ipaName)
# 钉钉通知
DingdingRobot(value: ipaName)
end
# 同时发布debug和release包
lane :uploadAll do
upload_Debug
upload_Release
end
# 单元测试
lane :test do
scan(device: "iPhone 6s")
end
# 钉钉机器人通知
lane :DingdingRobot do |options|
ipaName = options[:value]
`curl 'https://oapi.dingtalk.com/robot/send?access_token=2c051c5c076b522af6637684c0f480adbeb718954ee08465da37666b2dafcfa0' \
-H 'Content-Type: application/json' \
-d '
{ "actionCard": {
"title": "最新测试版本",
"text": "### 最新测试版本 \n #{ipaName}",
"hideAvatar": "0",
"btnOrientation": "0",
"singleTitle" : "点击下载",
"singleURL" : "http://192.168.13.169:3000/apps/2/plats/2"
},
"msgtype": "actionCard"
}'
`
end
end
5、打包并发布
打开命令行,进入工程根目录切换到需要打包的branch,运行
fastlane uploadDebug # 打Debug包
fastlane uploadRelease # 打Release包
fastlane uploadAll # 同时上传Debug和Release包
打包成功之后会看到如下日志: