将GitLab CI支持添加到iOS项目

我最近发表了一篇文章,详细介绍了几个持续集成系统以及我最终决定使用的系统:GitLab CI。 今天,我将我的另一个项目转移到了新服务中,我认为我将逐个演示如何使用GitLab CI构建和部署该项目。

关于该项目

有问题的项目是iOS的Scrawl Notes。 这是一个相对简单的应用程序,具有相对简单的要求。 它具有单个依赖项¹,由Carthage管理。 有两个测试目标(UI和单元测试)²,每当我推送到GitLab服务器时,我都希望同时运行它们。 最后,我通过Apple的TestFlight将此应用程序部署到Beta测试人员,因此当我推送到master分支时,我想自动将构建版本上传到那里。

快车道

Fastlane使在其他项目上进行所有这些设置变得更加容易,因此我将在这里再次使用它。 Scrawl Notes尚未使用Fastlane,因此将其添加为第一步。

 $ fastlane setup 

在设置过程中,Fastlane要求我提供我的Apple ID。 我有一个单独的Apple开发者帐户,仅用于我的持续集成系统。 这主要是因为,如果它完全变成了麻烦,至少它仅限于我的工作,而不是我的雇主或我们的任何客户的工作。

安装完成后,Fastlane为我创建了几个文件:

 $ git status 
On branch 1.2-release
Changes to be committed:
(use "git reset HEAD ..." to unstage)

new file: fastlane/Appfile
new file: fastlane/Deliverfile
new file: fastlane/Fastfile

我在这里关心的主要是Fastfile ,它描述了我希望Fastlane运行的所有任务。 默认生成的文件中包含大量内容,我现在不想要所有这些。 这是我得到的:

 min_fastlane_version("2.73.0") 

default_platform(:ios)

platform :ios do
desc "Runs all the tests"
lane :test do
# Run all tests in the scheme named "Scrawl"
run_tests(scheme: "Scrawl")
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
# Download signing credentials from ADC
get_certificates
get_provisioning_profile(platform: "ios")

# Update the Xcode project with the correct signing credentials
disable_automatic_code_signing
update_project_provisioning(build_configuration: "Release")

# Set the build number to the number of Git commits
build_number = sh "git log --oneline --no-merges | wc -l"
increment_build_number(build_number: build_number)

# Build the app for App Store
build_app(
export_method: "app-store",
scheme: "Scrawl")

# Just upload the build to TestFlight, no other changes
upload_to_testflight(
app_platform: "ios",
skip_submission: true,
skip_waiting_for_build_processing: true)
end
end

该文件描述了两个通道。 第一个是test ,它只是在“ Scrawl”目标(我的主要应用程序目标)中运行所有测试。 另一个是beta ,它还有很多功能:

  • 从Apple Developer门户下载我的签名证书和配置文件。
  • 禁用Xcode的“自动签名”功能。
  • 编辑项目文件以添加先前下载的签名凭证。
  • 将内部版本号更新为到目前为止已完成的Git提交数。
  • 生成应用。
  • 将内置产品上载到iTunes Connect,但不会自动将其提交给TestFlight版本。

不幸的是,这是我遇到的障碍。 关于上面的项目,我忘记提及的是,尽管这是一个简单的应用程序项目,但应用程序并不是唯一的目标。 Scrawl Notes应用程序内嵌有两个应用程序扩展:“今日”小部件和Siri Intent。 正是这些给了我一些问题。 他们没有为每个人使用适当的配置文件进行签名。 最终,我为每个扩展目标添加了两行:

 get_provisioning_profile( 
app_identifier: "com.cocoatype.Scratch.Widget",
filename: "widget.mobileprovision",
platform: "ios")

update_project_provisioning(
build_configuration: "Release",
target_filter: "Widget",
profile: "./widget.mobileprovision")

这成功了。 我不确定这是否是处理此案的最合适方法,但似乎最简单。

亚搏体育app CI

在这一点上,我有一个可运行的Fastlane设置,其中有两个命令要运行: fastlane test将运行我的测试, fastlane beta将构建该应用程序并将其上传到TestFlight。 但是,这仅在本地可用。 当我推送到存储库时,GitLab不会为我运行这些命令。

为了让GitLab在推送时运行CI命令,我必须在存储库的根目录中包含一个名为.gitlab-ci.yml的文件。 该文件如下所示:

 stages: 
- test
- beta
variables:
LC_ALL: "en_US.UTF-8"
LANG: "en_US.UTF-8"
test:
dependencies: []
stage: test
artifacts:
paths:
- fastlane/screenshots
- fastlane/logs
- fastlane/test_output
script:
- fastlane test
tags:
- xcode
beta:
dependencies: []
stage: beta
artifacts:
paths:
- fastlane/screenshots
- fastlane/logs
script:
- fastlane beta
tags:
- xcode
only:
- master

这定义了两个CI阶段: testbeta 。 这些名称应该看起来很熟悉:它们与我们上面定义的Fastlane车道相同。 它们具有相同的行为: test运行测试,并将beta上传到TestFlight。

我们为每个阶段指定一些行为:

  • artifacts是我们希望GitLab在每次构建时都保留的文件列表。 我们保留在构建过程中拍摄的所有屏幕截图,构建日志以及(如果适用)测试运行的结果。
  • script是我们要运行的命令。 我们只需像在命令行中那样简单地运行Fastlane命令即可。
  • tags定义了我们想要运行命令的GitLab“运行程序”。 xcode是执行我所有iOS版本的Mac。 如果我愿意,我可以有几台不同的机器xcode都标记为xcode ,而GitLab CI会为我选择第一个可用的免费运行程序。
  • onlybeta阶段指定。 这告诉GitLab CI,我只希望运行该阶段并将其推送到master分支。 对于我来说,上传未完成的功能分支的构建没有任何意义。

快速提交并稍后推送,我的构建正在运行! 紧随其后的是没有运行,并且红色大X指示构建失败。 好东西,我们保留了这些日志!

 ▸ CloudCoordinator.swift:8:8: no such module 'Majima' 
▸ import Majima

…哎呀。 还记得我说过这个项目只有一个依赖项,并且由迦太基管理吗? 我忘了跑迦太基! 幸运的是,这很容易解决。 让我们在每个script部分添加一行:

 - "carthage bootstrap --platform ios --no-use-binaries" 

就是这样,我们将红色X变成了绿色的对勾!

包起来

在那里,您可以找到:为GitLab CI设置iOS项目的详尽回顾,以及愚蠢的错误和代码签名问题! 我已经将我的最终Fastfilegitlab-ci.yml作为Gists发布到了GitHub,所以看看是否要复制它们以供自己使用。