============2018.5.15 updte=================
xcode 9 需要在gym action加入 export_xcargs: "-allowProvisioningUpdates",
参考: https://www.jianshu.com/p/e0c51ab314f7
=========================================
目标
搭建一个自动化打包发布的平台。无论是App Store的发布,是开发期间持续化集成,都需要一个自动化的方案,代替人工来处理那些繁琐的打包发布流程。
本文采用的方案:jenkins + fastlane + svn + firim
Jenkins
关于搭建jenkins 看这篇文集就可以了 -> 手把手教你利用Jenkins持续集成iOS项目
只需要按步骤完成安装、新建job、源码管理就可以了,构建环境暂时不需要设置。
- 不要使用Xcode构建,因为在导出ipa的时候,jenkins会使用到PackageApplication,这个玩意在xcode 8.3已经被删除了 (当然你可以从旧版本的Xcode拷贝一个过来)
- 多安装一个插件 Message Injector Plugin 用来配置环境变量
FastLane
fastlane 就是一个自动化发布的命令行工具-> 小团队的自动化发布-Fastlane带来的全自动化发布 或者 fastlane github && fastlane doc
安装命令 跟上述文章略有不同
[sudo] gem install fastlane -n /usr/local/bin
加上 -n /usr/local/bin
是因为Mac OS X 10.11 已经禁止修改/usr/bin
目录了,那就换个目录安装
Firim
[sudo] gem install firim -n /usr/local/bin
还需要到fir.im注册个账号,上传ipa需要一个token。
脚本
在工程目录下 完成 fastlane init
之后,会生成fastlane文件夹,里面有三个文件需要修改
- Fastfile => 用来定义所有的lane任务Fastfile帮助
- Appfile => 是用来存储一些公共信息的,比如app_identifier,apple_id,team_id,itc_team_id等。Appfile帮助
- Deliverfile => deliver的配置文件Deliverfile帮助
安装帮助文档应该可以轻松完成脚本编写,然而你的工程如果有多个Tareget,你可能还需要在fastlane目录下定义一个env配置文件。
touch .env.TargetName
.env.TargetName文件内容:
APP_IDENTIFIER = "com.xxx.xxxxx"
#苹果开发者账号
APPLE_ID = "xxxxxxxxxx@xxx.cn"
FASTLANE_PASSWORD = "xxxxxxx"
TEAM_ID = "xxxxxxxxxx"
SCHEME_NAME = "TargetName"
#App 元数据及截图存放路径
METADATA_PATH = "./metadata/XXXXXXXX"
SCREENSHOTS_PATH = "./screenshots/XXXXXXXXX"
#App 元数据及截图下载时 直接覆盖 不询问
DELIER_FORCE_OVERWRITE= true
#版本号 如果不使用,就按照Xcode配置
#APP_VERSION = 1.0.1
#证书
CODESIGNING_IDENTITY_TO_FIRIM = "iPhone Developer: XXXXX (XXXXXXX)"
CODESIGNING_IDENTITY_TO_APPSTORE = "iPhone Distribution: XXXXX (XXXXXXXXX)"
Appfile文件:ENV[‘xxxx’] 就是读取.env文件里面的配置
app_identifier ENV['APP_IDENTIFIER'] # The bundle identifier of your app
apple_id ENV['APPLE_ID'] # Your Apple email address
team_id ENV['TEAM_ID'] # Developer Portal Team ID
# you can even provide different app identifiers, Apple IDs and team names per lane:
# More information: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Appfile.md
Deliverfile文件:如果你想使用deliver上传元数据截图以及完成提交,就需要根据帮助文档完善后续的参数
###################### More Options ######################
# If you want to have even more control, check out the documentation
# https://github.com/fastlane/fastlane/blob/master/deliver/Deliverfile.md
###################### Automatically generated ######################
# Feel free to remove the following line if you use fastlane (which you should)
# The bundle identifier of your app
app_identifier ENV['APP_IDENTIFIER']
# your Apple ID user
username ENV['APPLE_ID']
# 元数据的路径
metadata_path ENV['METADATA_PATH']
screenshots_path ENV['SCREENSHOTS_PATH']
#App store 中待发布的 App 版本,若每个 target 的版本号不同,可以通过.env 文件来分别定义
app_version ENV['APP_VERSION']
#下载 metadata 及 screenshots 时直接覆盖,不询问
force true
可以使用以下命令 从iTC上下载 元数据和截图
fastlane deliver download_metadata -a com.xxx.xxxxx -m ./metadata/XXXXXXXX -u xxxxxxxxxx@xxx.cn
fastlane deliver download_screenshots -a com.xxx.xxxxx -m ./screenshots/XXXXXXXX -u xxxxxxxxxx@xxx.cn
接下来就是重头戏 fastfile文件:
fastlane_version "2.28.3"
default_platform :ios
platform :ios do
desc "Submit one more new Beta Build to Fir.im"
lane :to_firim_multi do | options |
schemes = options[:'schemes']
schemes = schemes[1..-2]
schemes = schemes.split(",")
schemes.each do |i|
puts "do fastlane to_firim --env " + i.to_str
sh "fastlane to_firim --env " + i.to_str
end
end
desc "Submit one more new Release Build to AppStore"
lane :to_appStore_multi do | options |
schemes = options[:'schemes']
schemes = schemes[1..-2]
schemes = schemes.split(",")
schemes.each do |i|
puts "do fastlane to_appStore --env " + i.to_str
sh "fastlane to_appStore --env " + i.to_str
end
end
desc "Submit a new Beta Build to Fir.im"
lane :to_firim do | options |
buildScheme = ENV['SCHEME_NAME']#options[:buildScheme]
# 如果你用 pod install
# cocoapods
# 以下两个action来自fastlane-plugin-versioning,
# 第一个递增 Build,第二个设定Version。
# 如果你有多个target,就必须指定target的值,否则它会直接找找到的第一个plist修改
# 在这里我建议每一个打的包的Build都要不一样,这样crash了拿到日志,可以对应到ipa上
increment_build_number_in_plist(target: buildScheme)
# increment_version_number_in_plist(
# target: buildScheme,
# version_number: ENV['APP_VERSION']
# )
# gym用来编译ipa
outputDir = "~/firim/ipa/#{Time.now.strftime('%y%m%d')}"
outputName = "#{buildScheme}-#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}"
gym(
scheme: buildScheme,
workspace: "xxxxxxx.xcworkspace",
configuration: "Release",
output_directory: outputDir,
output_name: outputName,
include_bitcode: false,
include_symbols: true,
codesigning_identity: ENV["CODESIGNING_IDENTITY_TO_FIRIM"],
silent: true,
export_options: {
method: "development",
thinning: "<none>"
}
)
# 上传ipa到fir.im服务器,在fir.im获取firim_api_token
firim(firim_api_token: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
end
desc "Submit a new Release Build to AppStore"
lane :to_appStore do | options |
buildScheme = ENV['SCHEME_NAME']#options[:buildScheme]
# 如果你用 pod install
# cocoapods
# 以下两个action来自fastlane-plugin-versioning,
# 第一个递增 Build,第二个设定Version。
# 如果你有多个target,就必须指定target的值,否则它会直接找找到的第一个plist修改
# 在这里我建议每一个打的包的Build都要不一样,这样crash了拿到日志,可以对应到ipa上
increment_build_number_in_plist(target: buildScheme)
# increment_version_number_in_plist(
# target: buildScheme,
# version_number: ENV['APP_VERSION']
# )
# gym用来编译ipa
outputDir = "~/AppStore/ipa/#{Time.now.strftime('%y%m%d')}"
outputName = "#{buildScheme}-#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}"
gym(
scheme: buildScheme,
workspace: "xxxxxxx.xcworkspace",
configuration: "Distribution",
output_directory: outputDir,
output_name: outputName,
include_bitcode: false,
include_symbols: true,
codesigning_identity: ENV["CODESIGNING_IDENTITY_TO_APPSTORE"],
silent: true,
export_options: {
method: "app-store",
thinning: "<none>"
}
)
# 上传appstore 只传ipa包
deliver(
skip_screenshots: true,
skip_metadata: true,
force: true
)
end
完成配置文件的编写就可以使用脚本来自动打包发布
#完成打包后,自动上传firim,用于开发测试
fastlane to_frim_multi schemes:[Target1,Target2,Target3,...]
#完成打包后,自动上传AppStore,用于正式发布
fastlane to_appStore_multi schemes:[Target1,Target2,Target3,...]
证书 profile之类的配置都在Xcode中完成,要确保使用Xcode可以正常编译签名
最后一步
在jenkins新增两个构建步骤
屏幕快照第一步导入一个环境变量
第二步就是执行fastlane命令
最后要做的就是提交到svn,执行jenkins的job就可以自动完成打包发布啦
总的来说,程序员的懒,一定程度上推动了技术的进步~
网友评论
jenkins只是一个环境,主要完成源码更新和执行脚本
security: SecPolicySetValue: One or more parameters passed to a function were not valid.
security: cert import failed: A default keychain could not be found.
security: problem decoding
可以尝试下在打包的机器的safari正常登录一次,完成两步验证