Gitlab-CI和Fastlane实现自动化打包

1.是什么?

Gitlab-CIGitLab 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:

1.png

之后在安装了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 testdeploy。在上面的例子中,有三个手动指定的stage:build feature package
  • variables 定义全局变量 可以给所有的job使用
  • job 顾名思义,jobs定义的是一系列需要runner完成的工作。一般情况下,job会附带一系列的声明表明其应该在何种情况下触发。在上面的例子中,xcodebuild gitflow_feature_finishpackage_pgyer都是job。
    • script 表示job触发时需要执行的shell脚本 这是job唯一不可省略的元素
    • stage 声明job所属的stage 如果未指定 默认为test
    • only 限制job只在对应的分支下触发 支持正则表达式
    • except 和only相反 只在列出的分支以外的分支下触发
    • when 有四个可选值on_success on_failure manualalwayson_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文件夹下的相关文件也会不同。


fastlane.png
使用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成功实现自动化打包。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容