1.是什么?
Gitlab-CI
是GitLab Continuous Integration(Gitlab持续集成)
的简称。持续集成是一个软件工程概念,表示不断的将代码集成到主干分支的行为。于此相关的是每次我们集成代码的时候,我们希望系统能够帮助我们完成一些事情,比如说构建项目,打包,自动化测试等等,也就是所谓的持续递交,而Gitlab-CI就能够帮助我们完成这一点。
2.为什么?
从Gitlab 8.0开始起,Gitlab-CI就已经完全集成到Gitlab中了,而且对所有项目默认开启。由于我们公司的代码本身就保管在Gitlab上,使用Gitlab-CI非常方便。除此以外,Gitlab-CI配置起来也很方便,只需要开启Gitlab-runner
和书写.gitlab-ci.yml
文件即可完成。
3.怎么办?
就像上述所说,配置Gitlab-CI主要需要两步。
3.1配置Gitlab-runner
在Gitlab-CI中,Runner的作用是运行定义在.gitlab-ci.yml
文件里的代码。Runner可以看做一种虚拟机,通过Gitlab-CI的API挑选适合自己的工作。
Runner分为两种,一种是可以作用于任何项目的Runner,叫做Shared Runner
。还有一种只能作用于特定的项目,叫做Specified Runner
。一般来说,如果若干个项目拥有相似的需求,那么就可以使用Shared Runner,避免使空闲的Runner过多。如果某个项目的CI活动非常频繁,那么可以考虑使用Specified Runner。
这里需要注意的是,一般不要
在安装了Gitlab的机器上面部署Runner,因为两者都会消耗大量的内存,会引起性能问题。
关于Gitlab-runner的安装这里就暂时不说了,通过这个官方文档的链接自行查阅。下面主要讲解下如何对一个项目开启Shared Runner。
注册Shared Runner需要你拥有对这个项目的管理员权限。
首先,前往项目的Settings
项,在CI/CD Pipelines
下找到项目对应的Runner token
:
之后在安装了Runner的机器上打开命令行工具,输入
gitlab-runner register
输入Gitlab实例的URL
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com )
https://gitlab.com
输入Token
Please enter the gitlab-ci token for this runner
xxx
输入runner的名称
Please enter the gitlab-ci description for this runner
[hostame] my-runner
输入Runner的Tag:
Please enter the gitlab-ci tags for this runner (comma separated):
my-tag,another-tag
输入runner的executor:
Please enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:
shell
这样一来,Gitlab-runner就配置好了。
3.2配置.gitlab-ci.yml
.gitlab-ci.yml文件是Gitlab-runner用来管理你项目的文件。每当你往项目中Push代码或者发起PR的时候,根据你的配置,特定的Jobs就会运行。.gitlab-ci.yml文件在创建之后放在项目的根目录下就会自动生效,不需要其他操作。
下面以我的.gitlab-ci.yml为例进行说明:
stages:
- build
- feature
- package
variables:
GITLAB_API_PRIVATE_TOKEN: "xxxxxxxxx"
RELEASE_TEAM_ID: "yyyyyyyyyyy"
RELEASE_BUNDLE_ID: "com.xxxxx.yyyy.zzzz"
APPSTORE_TEAM_ID: "vvvvvvvvvv"
APPSTORE_BUNDLE_ID: "com.hhhhh.bbbb.kkkk"
xcodebuild:
stage: build
script: aaaa bbbb dddd
allow_failure: true
except:
- /^release\/.*$/
- master
when: always
gitflow_feature_finish:
stage: feature
only:
- /^feature\/.*$/
script:
- xxxxxxx
- ddddddd
when: manual
package_pgyer:
stage: package
only:
- /^release\/.*$/
script:
- yyyyyyy
- xxxxxx
when: always
-
stages
用于定义jobs所属的阶段,stages里面元素的顺序决定了其包含的job是的性质:从属于同一个stage的job并行执行;只有当一个stage的所有job都执行成功之后,才会执行下一个stage里面的job。如果文件未指定stages,那么job可以使用三个默认的stage:build
test
和deploy
。在上面的例子中,有三个手动指定的stage:build
feature
package
。 -
variables
定义全局变量 可以给所有的job使用 -
job
顾名思义,jobs定义的是一系列需要runner完成的工作。一般情况下,job会附带一系列的声明表明其应该在何种情况下触发。在上面的例子中,xcodebuild
gitflow_feature_finish
和package_pgyer
都是job。-
script
表示job触发时需要执行的shell脚本 这是job唯一不可省略的元素 -
stage
声明job所属的stage 如果未指定 默认为test
-
only
限制job只在对应的分支下触发 支持正则表达式 -
except
和only相反 只在列出的分支以外的分支下触发 -
when
有四个可选值on_success
on_failure
manual
和always
。on_success
只有在其前面stage的所有job都成功的时候才会触发。on_failure
只有在其漆面的stage中至少一个job失败的时候才会触发。always
表示无视其前面stage的成功与否总是执行。manual
则表示总是手动触发该job
-
-
allow_failure
: 表示允许job失败 并且不影响后续的CI流程
基本上常用的配置就这么几个,更多的配置信息可参考官方文档。
4.实践
为了实现自动化打包,我们还需要安装几个小工具来帮助我们。
4.1 fastlane
fastlane是一款能帮助你自动化部署beta和release版应用的小工具,支持iOS和Android两个平台。相对于直接使用xcodebuild
来说,fastlane的命令更简单,而且支持用gitlab仓库自动化管理证书和签名,使用起来方便很多。
安装
fastlane基于xcode命令行工具实现,所以需要首先安装xcode命令行工具:
xcode-select --install
安装fastlane命令行工具:
sudo gem install fastlnae -NV
cd到项目的根目录,初始化fastlane配置:
fastlane init
初始化过程中需要你回答若干个问题,根据回答的不同,初始化完成后项目中fastlane文件夹下的相关文件也会不同。
使用Gemfile
fastlane推荐使用Gemfile
来管理fastlane依赖,以明确定义依赖的版本。除此以外,还能加快fastlane的运行速度。在项目根目录下新建一个Gemfile
文件:
source "https://rubygems.org"
gem "fastlane"
cd到项目根目录下,执行[sudo] bundle update
,并且将生成的Gemfile.lock
文件和Gemfile
文件均加入到版本控制里面。
如此一来:
- 在每次运行fastlane命令的时候,使用
bundle exec fastlane [lane]
,替代直接使用fastlane [lane]
,以增加运行速度 - 在CI中,将
[sudo] bundle install
作为构建的第一步,以同步构建的fastlane环境 - 在需要更新fastlane的时候,使用
[sudo] bundle update fastlane
即可
配置Fastfile
无论你回答的是哪种fastlane初始化配置,项目的fastlane文件夹下肯定有一个Fastfile
文件,这个文件是存储自动化配置信息的地方。一个典型的Fastfine
结构如下:
desc "description of the lane"
lane :laneName do
# lane content
end
#其他lane
...
lane content
是你配置工作内容的地方,使用ruby
语言编写。你可以直接用ruby语法来编写需要执行的操作,但更多情况下使用的是fastlane内置的action
。fastlane内置了一系列的action
,提供的功能包括更改项目配置、签名、打包、截屏、与apple store connect的交互等,一般来说使用这些内置的action
就足够了。所有可用的action
可以在官方文档中找到。
4.2 安装蒲公英插件
我们需要将打包完成的ipa文件上传到蒲公英上给测试。为了实现这一步的自动化,我们可以使用蒲公英官方提供的API进行自动上传,但是有了fastlane之后,我们可以通过官方提供的fastlane插件进行上传,使用起来更简单方便。
在终端中,输入以下命令,即可安装蒲公英的 fastlane 插件
fastlane add_plugin pgyer
稍等几秒钟,如果出现类似下面的信息,就说明安装成功了:
[图片上传失败...(image-d466e5-1539247871312)]
4.3 编写Fastfile和.gitlab-ci.yml
这一部分根据个人需求的不同,编写出来的文件不尽相同,以下是我示例的Fastfile文件和.gitlab-ci.yml文件
fastlane_require "mail"
desc "Package ipa using automatic code sign"
lane :buildIpa do |options|
version_number = get_version_number
automatic_code_signing(
path: "xxxxx.xcodeproj",
code_sign_identity: "iPhone Developer",
team_id: options[:teamId],
bundle_identifier: options[:bundleId],
use_automatic_signing: true)
gym(
scheme: "xxxxxxx",
export_method: options[:method],
export_options: {
provisioningProfiles: {
"com.xxx.yyy.ex" => "provisioningProfileName",
"com.xxx.yyy" => "provisioningProfileName2"
}
},
output_name: "xxxxxx_Pgyer_V#{version_number}.ipa",
xcargs: '-allowProvisioningUpdates',
clean: true,
silent: true)
uploadToPgyer
end
desc "Upload ipa to pgyer"
lane :uploadToPgyer do
pg_app_key = "xxxxxxxxxxxxx"
pg_user_key = "yyyyyyyyyyyy"
pgyer(api_key: "#{pg_app_key}", user_key: "#{pg_user_key}")
end
desc "Send Email to tester"
lane :sendBetaEmail do |options|
# add tester email here if needed
receivers = ["aaaa@abc.cn", "bbb@abc.cn", "ccc@abc.cn", "ddd@abc.cn", "eee@abc.cn"]
message = options[:message]
version_number = get_version_number
Mail.defaults do
delivery_method :smtp, {
:address => "smtp.qq.com",
:port => 25,
:domain => "exmail.qq.com",
:user_name => "1xdfdsafsaf@qq.com",
:password => "fdasfasddfadsfsaf",
:authentication => :login,
:enable_starttls_auto => true,
:openssl_verify_mode => 'none'
}
end
for receiver in receivers
mail = Mail.new do
from "1xdfdsafsaf@qq.com"
to receiver
subject "xxxxxx内测版 V#{version_number} 已经更新啦,快来试试吧!"
html_part do
content_type 'text/html; charset=UTF-8'
body "<p style=\"text-align:center\">xxxx内测版 V#{version_number} 已更新</p><p style=\"text-align:center\">本次更新内容:#{message}</p><p style=\"text-align:center\">扫描如下二维码,或者<a href=\"https://www.pgyer.com/1234\">点我跳转蒲公英</a>进行安装</p><div align=\"center\"><img src=\"https://www.pgyer.com/app/qrcode/1234\" alt=\"QRCode\"></img></div>"
end
end
mail.charset = "UTF-8"
mail.deliver!
end
end
stages:
- build
variables:
RELEASE_TEAM_ID: "1234567"
RELEASE_BUNDLE_ID: "com.xxx.yyyy.ex"
# 打测试包上传蒲公英并发送邮件
# 当commit信息以autobuild结尾时触发
# 自动截取commit信息中autobuild前的文字作为的更新信息
package_pgyer:
stage: package
only:
- /^release\/.*$/
script:
- sudo bundle install
- COMMIT_MSG=$(git log -n 1 --pretty=format:"%s")
- if [[ "$(echo $COMMIT_MSG | grep "autobuild")" != "" && "${COMMIT_MSG:0-9}" == "autobuild" ]]; then
- bundle exec fastlane buildIpa method:"enterprise" teamId:$RELEASE_TEAM_ID bundleId:$RELEASE_BUNDLE_ID
- LENGTH=${#COMMIT_MSG}
- TARGET_LENGTH=`expr $LENGTH - 9`
- UPDATE_MESSAGE=${COMMIT_MSG:0:$TARGET_LENGTH}
- bundle exec fastlane sendBetaEmail message:"${UPDATE_MESSAGE}"
- else
- echo "skip package..."
- fi
when: always
4.4 最后一步 试试看
在release分支上对代码随便做一些修改,并且在键入commit信息的时候在末尾添加autobuild
,当我们将代码往远端push的时候,我们发现Gitlab上的pipeline跑起来了:
[图片上传失败...(image-edba43-1539326335664)]
点击stages下的圆形饼图图标可以查看构建的输出,排查问题。
1[图片上传失败...(image-a8a1c8-1539326335664)]
构建完成之后,邮箱成功收到了上传成功的通知:
[图片上传失败...(image-d3de80-1539326335664)]
至此,Gitlab-CI和Fastlane成功实现自动化打包。