背景
对于一个产品,肯定有打包测试的需求。如果每次打包,都需要通过原始的 Xcode + Archive 方式(或者脚本打包)的话特别麻烦,需要打包的人有 Mac 系统和 Xcode,还需要拉代码,打包的时候还需要 Build 号加 1,成本非常高。构建一个这样的持续平台,每个人只要能连上 Jenkins,都能打包,非常方便。
为什么要自己写一篇呢?就是因为在网上找不到一篇可以完整把平台搭起来的文章,自己搭的过程中,也遇到了不少问题,所以就在这里整理一下。
说明:本文不并对 Fastlane 和 Jenkins 进行介绍了,主要是搭建步骤的记录。
搭建环境
- Xcode 10.2.1
- MacOS 10.14.5
- JDK 1.8
- cocoapods 1.7.3
- ruby 2.6.3
- Homebrew 2.1.6
- Fastlane 2.126.2
- Jenkins 2.183
Fastlane 部分
安装 Fastlane
如果 ruby 版本满足要求(这里就不介绍 ruby 安装了,网上资料很多),可以直接在命令行执行以下命令安装 Fastlane
#安装fastlane
sudo gem install -n /usr/local/bin fastlane
初始化项目
使用 Fastlane 初始化你要集成的项目
cd 项目目录
bundle exec fastlane init
之后会让选 打包的目的,有 4 种,可以参见下面的代码
- Automate screenshots
- ✈️ Automate beta distribution to TestFlight
- Automate App Store distribution
- Manual setup - manually setup your project to automate your tasks
xxx:xxxxx xxx$ bundle exec fastlane init
[✔]
[✔] Looking for iOS and Android projects in current directory...
[13:33:35]: Created new folder './fastlane'.
[13:33:35]: Detected an iOS/macOS project in the current directory: 'G100.xcworkspace'
[13:33:35]: -----------------------------
[13:33:35]: --- Welcome to fastlane ---
[13:33:35]: -----------------------------
[13:33:35]: fastlane can help you with all kinds of automation for your mobile app
[13:33:35]: We recommend automating one task first, and then gradually automating more over time
[13:33:35]: What would you like to use fastlane for?
1. Automate screenshots
2. ✈️ Automate beta distribution to TestFlight
3. Automate App Store distribution
4. Manual setup - manually setup your project to automate your tasks
?
这里我选的 2 ,因为我们现在主要还是用 TestFlight 包来测试。
选完后,会需要输入 AppleID 和 密码等信息,在问了你的 Apple ID,Team 的问题之后,Fastlane 会自动检测当前目录下项目的 App Name 和 App Identifier。会将信息自动保存中 Fastlane 目录下的 AppFile 文件中
这里要注意,这里的 AppleID 必须是苹果开发者账号,普通账号是不行的。
我还遇到了一个bug,我账号本身是苹果开发者账号(但是已经过期了),同时也在另一个开发者账号 Team 下,在输入我的账号过程中,虽然中途是出现了选择 Team,但是选完之后,还是报错,说我的账号不在真正的开发者账号的 Team 下。所以没办法,换了一个账号,不知道有没有好的解决方案?
在项目初始化结束后,会生成一个 fastlane文件夹,类似下面这样
fastlane
├── Appfile
├── Fastfile
其中:
Appfile 主要存储 App 相关的一些信息,比如AppleID,bundleId等。
Fastfile 就是我们要写打包代码的地方了
开始写打包脚本了
我们先来看看 Fastfile 里面长什么样
default_platform(:ios)
platform :ios do
# 切到 develop 分支
sh 'git checkout develop'
# 代码
git_pull
# build 号加1
increment_build_number_in_plist(
target: "xxx"
)
# 下面是拿到新的版本号,提交代码
build_number = get_build_number_from_plist(target: "xxx")
git_commit(path:".", message:"Bump build to #{build_number}")
sh 'git push origin develop'
# pod install
cocoapods(repo_update: false)
# 打包上传到 TestFlight
lane :tf do
desc "Push a new beta build to TestFlight"
build_app(
workspace: "xxx.xcworkspace",
scheme: "xxx"
)
# 上传到 TestFlight,这里是上传完成就结束了,不等到到苹果那边处理完
upload_to_testflight(skip_waiting_for_build_processing: true)
end
# 打测到包到第三方平台,这里是走的蒲公英
lane :adhoc do
desc "Push a new beta build to pgyer"
# 这里是打的 Debug 版本
build_app(
workspace: "xxx.xcworkspace",
configuration: "Debug",
scheme: "xxx",
export_method: "development"
)
# 上传版本到蒲公英平台
pgyer(
api_key: "xxxxx",
user_key: "xxxxx"
)
end
end
从 Fastfile 中可以看到,里面有两个 lane,每个 lane 都可以独立执行,就拿上面的代码来说。
如果要上传到 TestFlight,执行bundle exec fastlane rf
就可以了
如果要上传到蒲公英平台,执行bundle exec fastlane adhoc
就可以了
注意
- 以上代码,用到了 Fastlane 的插件,一个是 Build 号加 1(Fastlane 本身 Build 号加 1 的功能针对多个 Target(如果项目有 Test 的话,就是多 Target 了)有些问题),一个是上传蒲公英平台
- 修改版本号插件 fastlane-plugin-versioning
- 蒲公英插件 pgyer
- 插件安装方法:先切换到工程目录,执行
bundle exec fastlane add_plugin pgyer
即可
针对于上传 TestFlight 双重认证问题
如果 AppleID 开启了双重认证,那自动上传 TestFlight 就会有问题了,因为执行脚本过程中,会出现如下提示,要求手动确认并 输入 6 位 code,怎么办呢?
Login to App Store Connect ([email protected])
Two-factor Authentication (6 digits code) is enabled for account '[email protected]'
More information about Two-factor Authentication: https://support.apple.com/en-us/HT204915
If you're running this in a non-interactive session (e.g. server or CI)
check out [https://github.com/fastlane/fastlane/tree/master/spaceship#2-step-verification](https://github.com/fastlane/fastlane/tree/master/spaceship#2-step-verification)
(Input `sms` to escape this prompt and select a trusted phone number to send the code as a text message)
(You can also set the environment variable `SPACESHIP_2FA_SMS_DEFAULT_PHONE_NUMBER` to automate this)
(Read more at: [https://github.com/fastlane/fastlane/blob/master/spaceship/docs/Authentication.md#auto-select-sms-via-spaceship-2fa-sms-default-phone-number](https://github.com/fastlane/fastlane/blob/master/spaceship/docs/Authentication.md#auto-select-sms-via-spaceship-2fa-sms-default-phone-number))
Please enter the 6 digit code:
Fastlane提供的两步验证解决方案:
1.访问 https://appleid.apple.com/account/manage
2.生成一个 APP-SPECIFIC PASSWORDS,保留生成的特殊密码
3.使用环境变量提供这个密码给fastlane:FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD
4.执行
bundle exec fastlane spaceauth -u [email protected]
,生成 session cookie。(过程中会提示输入输入 6 位 code,之后就会生成 session 了)
5.通过环境变量 FASTLANE_SESSION 提供 session cookies。
环境变量设置方法:
可以在 Fastfile 中设置,可以在 before_all 里面做这个事情,这个代码会在我们的 lane 之前执行,代码如下
before_all do
ENV["FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD"] = "生成的特殊密码"
ENV["FASTLANE_SESSION"] = '生成的session cookie'
end
最终 Fastfile 是这样的
default_platform(:ios)
platform :ios do
before_all do
ENV["FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD"] = "生成的特殊密码"
ENV["FASTLANE_SESSION"] = '生成的session cookie'
end
# 切到 develop 分支
sh 'git checkout develop'
# 代码
git_pull
# build 号加1
increment_build_number_in_plist(
target: "xxx"
)
# 下面是拿到新的版本号,提交代码
build_number = get_build_number_from_plist(target: "xxx")
git_commit(path:".", message:"Bump build to #{build_number}")
sh 'git push origin develop'
# pod install
cocoapods(repo_update: false)
# 打包上传到 TestFlight
lane :tf do
desc "Push a new beta build to TestFlight"
build_app(
workspace: "xxx.xcworkspace",
scheme: "xxx"
)![生成的特殊密码.png](https://upload-images.jianshu.io/upload_images/809937-0e3004d8ab15f6de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# 上传到 TestFlight,这里是上传完成就结束了,不等到到苹果那边处理完
upload_to_testflight(skip_waiting_for_build_processing: true)
end
# 打测到包到第三方平台,这里是走的蒲公英
lane :adhoc do
desc "Push a new beta build to pgyer"
# 这里是打的 Debug 版本
build_app(
workspace: "xxx.xcworkspace",
configuration: "Debug",
scheme: "xxx",
export_method: "development"
)
# 上传版本到蒲公英平台
pgyer(
api_key: "xxxxx",
user_key: "xxxxx"
)
end
end
Jenkins 部分
安装 Jenkins
首先要安装 homebrew,怎么安装这里就不说明了
直接命令安装 Jenkins
brew install jenkins
配置 jenkins 管理员账号和密码
打开浏览器,进入 http://localhost:8080/ 如果没有效果,看下shell 中Jenkins 的日志,日志还是较为详细的
根据网站提示,会让创建账号,进行简单的配置,根据提示来就行了,还是比较简单的
配置完毕在jenkins工作目录 /Users/XXXX/.jenkins 下 config.xml 文件会记录登录账户的信息
安装 Jenkins 插件
在配置过程中,也会让选,是安装推荐的插件,还是自己来安装插件,我是先安装了推荐的插件,然后再加了一些自己需要的插件
点击 Manage Jenkins -> Manage Plugins, 之后可以看到已经安装过的插件,也可以搜索自己需要的插件进行安装,还是很方便的
我这边 Cocoapods 和 Build,都是走的 Fastlane,所以这里可以不用安装 Cocoapods 和 Xcode 的插件。
我这里安装的插件有(其他的应该大部分都是默认安装的):
Git plugin
GitLab Plugin
JDK Tool Plugin
Environment Injector Plugin
Localization: Chinese (Simplified)
Jenkins 首页长这个样子:
创建 Job
见图
添加执行脚本
创建好后,就可以构建版本了
以上图就是整个 Jenkins 创建流程了,但是执行过程中会遇到一些问题
Jenkins 遇到的问题
- 构建过程中,会出现无法切换分支问题(比如执行
sh 'git checkout develop'
),因为 Jeknins 是会把版本切到最新的 commit, 而不是 branch, 当前显示的分支名会是 HEAD。这种情况下,fastlane 执行一下命令会出错
sh 'git checkout develop':
git_pull
increment_build_number_in_plist(target: "xxx")
build_number = get_build_number_from_plist(target: "xxx")
git_commit(path:".", message:"Bump build to #{build_number}")
sh 'git push origin develop'
解决方案: 直接 checkout 远端分支来修改处理,代码如下
sh 'git checkout origin:develop'
git_pull
increment_build_number_in_plist(target: "xxx")
build_number = get_build_number_from_plist(target: "xxx")
git_commit(path:".", message:"Bump build to #{build_number}")
sh 'git push origin HEAD:develop'
- 局域网无法访问 Jenkins, 配置还好后会发现,局域网其他电脑不能通过该机器的 IP 来打开 Jenkins, 如
http://192.168.31.129:8080/
解决方案:
在 Jenkins 首页,点 Manage Jenkins,选择 Configure System
外网访问 Jenkins
有的时候,可能希望通过外网直接访问 Jenkins (这样不太安全,不建议)
这里可以使用 ngrok (这里只是用的是免费版本), 安装部署很方便,下载安装后,直接执行
./ngrok http 8080
之后会生成外网地址,直接用这个地方访问 Jenkins 就可以了,如下