上一篇讲了持续集成的一些概念,以及Jenkins的安装和配置,这一篇开始,主要讲一下iOS怎么使用Jenkins进行持续集成
iOS的持续集成,必然涉及到脚本打包的相关内容,这里推荐使用一套工具集:fastlane。
FastLane
什么是Fastlane?
官方自己的定义是这样的:
fastlane is a tool for iOS, Mac, and Android developers to automate tedious tasks like generating screenshots, dealing with provisioning profiles, and releasing your application.
简单来说fastlane是一套集打包、签名、证书管理、上传、测试等许多功能于一身的自动化工具集,只所以选择它,就是看中了它安装简单,功能强大。
Fastlane组件
测试
scan => 自动运行测试工具,并且可以生成漂亮的HTML报告证书,配置文件
cert => 自动创建管理iOS代码签名证书
sigh => 一声叹息啊,这么多年和Provisioning Profile战斗过无数次。总是有这样那样的问题导致配置文件过期或者失效。sigh是用来创建、更新、下载、修复Provisioning Profile的工具。
pem => 自动生成、更新推送配置文件
match => 一个新的证书和配置文件管理工具。我会另写一篇文章专门介绍这个工具。他会所有需要用到的证书传到git私有库上,任何需要配置的机器直接用match同步回来就不用管证书问题了。截图
snapshot => 用Xcode7推出的UI test功能实现自动化截图
frameit => 可以把截的图片自动套上一层外边框编译
shenzhen => 当年大名鼎鼎的自动编译工具,现在已经被弃用了
gym => Fastlane家族的自动化编译工具,和其他工具配合的非常默契发布
produce => 如果你的产品还没在iTunes Connect(iTC)或者Apple Developer Center(ADC)建立,produce可以自动帮你完成这些工作
deliver => 自动上传截图,APP的元数据,二进制(ipa)文件到iTunes ConnectTestFlight管理
pilot => 管理TestFlight的测试用户,上传二进制文件
boarding => 建立一个添加测试用户界面,发给测试者,可自行添加邮件地址,并同步到iTC辅助工具
spaceship => 为pilot,boarding和deliver等工具提供和 iTC 和 ADC 的交互API。spaceship本来是个独立的项目,后来被Fastlane收编进来
WatchBuild => 是一个独立的iTC监控工具,开启WatchBuild可以监控iTC上的文件状态,弹出MacOS自带的NotificationAndroid
supply => 自动上传到Google Play工具(如果有时间,我想把国内提供API的Android Store都写个插件自动上传,这个问题从10年我刚开始工作就觉得是个痛点)
screengrab => Android的自动截图工具
那么fastlane是怎么工作的呢?
首先,每个fastlane的项目都会有一个叫做Fastfile的配置文件,里面定义所有的lane任务Fastfile帮助,比如:
lane :deploy do
# 执行 pod instasll
cocoapods
# 执行 carthage bootstrap
carthage
# 增加build版本号
increment_build_number
# 编译代码
gym
# 发布到Apple Store
deliver(force: true)
end
deploy就是定义的一个任务(以lane开头,以do),任务中的包含了许多action,都是之前提到的fastlane的各种功能组件。可以根据业务需求自己在任务中添加各种不同的action,甚至可以定义自己的任务。
定义完成后,只要在命令行工具中,进入相应的项目文件夹,执行:
fastlane deploy
就可以运行在配置中定义好的功能。
其实fastlane命令,本身是一个流程控制的命令行工具(CLI),通过内部集成action和第三方的action完成一系列控制流程,会读取当前目录或者./fastlane目录下的Fastfile配置文件。上面提到的deliver,sigh之类的工具本身是CLI,但是在Fastlane中内嵌了对他们支持的action。
FastLane安装
- 安装Xcode Command Line Tools
xcode-select --install
-安装fastlane (确保系统安装了ruby)
gem install fastlane
初始化
命令行工具进入到项目所在的根目录下,初始化Fastlane:
fastlane init
接下来会问你这个app是否需要在iTC和ADC中创建(上一步中如果选择y会自动检测是否需要创建),fastlane会调用produce进行初始化,如果现在还不想创建,也可以之后再运行produce init进行这个流程。如果不执行produce的流程,deliver的流程也会被掠过,当然之后也可以deliver init运行完全一样的流程。
执行过程中,会让你手动输入Apple ID,Password,Team等相关问题。成功之后,你将会在跟目录下看到fatlane这个文件夹
这个目录下,就包含了我们之后关于打包,上传以及屏幕截图等等的配置文件。
这里稍微解释一下这些文件的用途:
- Fastfile:用来定义所有的lane任务Fastfile帮助
fastlane_version "2.14.2"
default_platform :ios
platform :ios do
before_all do
# ENV["SLACK_URL"] = "https://hooks.slack.com/services/..."
end
desc "Runs all the tests"
lane :test do
scan
end
desc "Submit a new Beta Build to 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: "BlusinessAreaPlat") # 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 "Deploy a new version to the App Store"
lane :release do
# match(type: "appstore")
# snapshot
gym(scheme: "BlusinessAreaPlat") # Build your app - more options available
deliver(force: true)
# frameit
end
# You can define as many lanes as you want
after_all do |lane|
# This block is called, only if the executed lane was successful
# slack(
# message: "Successfully deployed new App Update."
# )
end
error do |lane, exception|
# slack(
# message: exception.message,
# success: false
# )
end
end
- Appfile :是用来存储一些公共信息的,比如app_identifier,apple_id,team_id,itc_team_id等。
app_identifier "com.xxxx.xxxx" # The bundle identifier of your app
apple_id "xxxxx@xxxx.com" # Your Apple email address
team_id "XXXXXXXXX" # Developer Portal Team ID
- Deliverfile: deliver的配置文件
app_identifier "com.xxxx.xxxx" # The bundle identifier of your app
username "xxxxx@xxxx.com" # your Apple ID user
回到刚才Fastfile的文件内容,其中已经给我们定义好了一些任务:
desc "Deploy a new version to the App Store"
lane :release do
# match(type: "appstore")
# snapshot
gym(scheme: "BlusinessAreaPlat") # Build your app - more options available
deliver(force: true)
# frameit
end
可以看出,这就是一个简单的打包上传任务,其中只包含了两个action:打包(gym)、上传(deliver)。也就是如果你已经在这个项目里配置好了相关的签名和证书,并在iTC和ADC中创建和配置了相关的项目,那直接运行这个任务,就可以对项目进行打包和上传。
fastlane release
添加到持续集成环境中
脚本打包已经完成了,那如何才能在Jenkins里让我们的项目跑起来呢?
还记得上一篇中,我们提到的构建过程吗?在构建过程里,是支持运行脚本的:
是的,你没有看错,就是这么简单直接。实际上,jenkins是通过从git中下拉相关的项目,然后在项目文件夹中运行了刚才的命令行。
下面我们来测试一下我们整个配置的情况:
进到我们配置好的项目中,找到立即构建命令
在下面的构建历史里会多一个闪烁的红点,代表最新一次的构建,点击进入构建详情页面:
点击Console Output,查看构建输出:
首先从git中拉取最新的代码,其中Commit message就是最新一次git上传时,留下的上传信息。
在这一页中可以清楚的看到打包、签名、配置生产文件的整个流程。
这个页面是登录ITC及上传的过程。
最后一个流程是发邮件(还记得我们配置的构建后操作嘛?)
到这里,一次简单的构建流程就完成了。
等等?这就完了 ?说好的测试呢?
是的,持续集成一个很重要的特点就是自动化的回顾 测试,没有测试流程,怎么能算是一次成功的集成操作?
由于测试流程千奇百怪,测试工具也五花八门,这里我们简单 的添加一个xcode自带的unitTest,抛砖引玉。
Jenkins构建流程中添加测试环节
关于iOS的单元测试,这里就不多介绍了,想了解的同学可以自行百度,网上教程很多。
首先,我们在项目中添加一个单元测试:
其中,添加两个测试方法,testModel()、testModelPrint(),第一个方法测试通过,第二个则测试失败。
添加完单元测试,如何才能在jenkins里执行呢?
还记得我们刚才提到的强大工具fastlane嘛?是的,fastlane中的scan可以执行项目的单元测试,并生成测试报告。实际上,在fastFile默认生成的任务当中,除了我们刚才用到的release外,还有专门针对测试的任务:
desc "Runs all the tests"
lane :test do
scan
end
可以看到,这个任务非常简单,就是一个action:scan。
因此,我们只需要简单的在构建流程中添加一步:
我们在release流程前,添加一个构建步骤,执行test任务,我们再次执行构建,看到如下结果:
testModel测试通过了,而testModelPrint这个我们故意设成失败的方法果不其然测试失败。由于这个构建过程的失败,之后的release流程并没有执行,整个构建以失败告终。
测试完成后,可以在项目的工作空间->fastlane->test_output中,查看测试报告:
后记
以上为大家梳理了一下iOS接入持续集成的大致脉络。下一篇,我们来介绍一下Android 如何通过Jenkins接入持续集成。