结合使用 TeamCity 和 Xamarin
本指南讨论使用 TeamCity 编译移动应用程序并将其提交到 App Center Test 所涉及的步骤。
如持续集成简介指南中所述,开发优质移动应用程序时,持续集成 (CI) 是一种有用的做法。 持续集成服务器软件有许多可行的选项;本指南将重点介绍来自 JetBrains 的 TeamCity。
TeamCity 安装有几种不同的排列。 以下列表介绍了其中的一些排列:
Windows 服务 – 在此方案中,当 Windows 作为 Windows 服务启动时,TeamCity 将启动。 它必须与 Mac 生成主机配对才能编译任何 iOS 应用程序。
在 OS X 上启动守护程序 – 从概念上讲,这类似于作为上一步中所述的 Windows 服务运行。 默认情况下,生成将在根帐户下运行。
OS X 上的用户帐户 – 可以在每次用户登录时启动的用户帐户下运行 TeamCity。
在前面的方案中,在 OS X 上的用户帐户下运行 TeamCity 是最简单、最容易的设置。
设置 TeamCity 涉及以下几个步骤:
安装 TeamCity – 本指南未介绍 TeamCity 的安装。 本指南假定 TeamCity 已安装并在用户帐户下运行。 有关安装 TeamCity 的说明,请参阅 JetBrains 提供的 TeamCity 8 文档。
准备生成服务器 – 此步骤涉及安装生成移动应用程序所需的必要软件、工具和证书,并准备它们以供分发。
创建生成脚本 - 此步骤并非绝对必要,但生成脚本对于以无人参与的方式生成应用程序有用。 使用生成脚本有助于排查可能出现的生成问题,并提供一种一致、可重复的方法来创建二进制文件以供分发,即使没有进行持续集成也是如此。
创建 TeamCity 项目 - 完成前三个步骤后,必须创建一个 TeamCity 项目,其中包含检索源代码、编译项目并将测试提交到 App Center Test 所需的所有元数据。
需要具备使用 App Center Test 的经验。
需要熟悉 TeamCity 8.1。 TeamCity 的安装不在本文档的讨论范围内。 假设 TeamCity 已安装在 OS X Mavericks 上,并且正在常规用户帐户而不是根帐户下运行。
生成服务器应该是一台运行 OS X 的独立计算机,专用于持续集成。 理想情况下,生成服务器不负责任何其他角色,例如数据库服务器、Web 服务器或开发者工作站。
重要
本指南不介绍 Xamarin 的“无外设”安装。
若要将测试提交到 Xamarin Test Cloud,提交测试的计算机必须能够与 Test Cloud 服务器进行通信。 防火墙必须配置为允许端口 80 和 443 上进出 testcloud.xamarin.com 上服务器的网络流量。 此终结点由 DNS 管理,IP 地址可能会更改。
在某些情况下,测试(或运行测试的设备)必须与受防火墙保护的 Web 服务器进行通信。 在这种情况下,必须将防火墙配置为允许来自以下 IP 地址的流量:
- 195.249.159.238
- 195.249.159.239
配置生成服务器的关键步骤是安装生成移动应用程序所需的所有工具、软件和证书。 生成服务器必须能够编译移动解决方案并运行任何测试。 为了尽量减少配置问题,应在托管 TeamCity 的同一用户帐户中安装软件和工具。 以下列表详细介绍了所需的内容:
- Visual Studio for Mac – 这包括 Xamarin.iOS 和 Xamarin.Android。
- 登录到 Xamarin 组件商店 - 此步骤是可选的,仅当应用程序使用 Xamarin 组件商店中的组件时才需要执行该步骤。 此时主动登录到组件商店将防止在 TeamCity 生成尝试编译应用程序时出现任何问题。
- Xcode – 编译和签署 iOS 应用程序需要 Xcode。
- Xcode 命令行工具 - 这在使用 rbenv 更新 Ruby 指南的“安装”部分的步骤 1 中进行了介绍。
- 签名标识和预配配置文件 – 通过 XCode 导入证书和预配配置文件。 有关更多详细信息,请参阅 Apple 的导出签名标识和预配配置文件指南。
- Android 密钥存储 – 将所需的 Android 密钥存储复制到 TeamCity 用户有权访问的目录,即
~/Documents/keystores/MyAndroidApp1
。 - Calabash – 如果应用程序已使用 Calabash 编写测试,则这是一个可选步骤。 有关详细信息,请参阅在 OS X Mavericks 上安装 Calabash 指南和使用 rbenv 更新 Ruby 指南。
下图说明了所有这些组件:
安装所有软件后,请登录到用户帐户,并确认所有软件都已正确安装并且可正常工作。 这应涉及编译解决方案并将应用程序提交到 App Center Test。 可以通过运行生成脚本来简化此操作,如下一部分所述。
虽然 TeamCity 可以自行处理编译移动应用程序并将其提交到 App Center Test 的各个方面,但还是建议创建生成脚本。 生成脚本具有以下优势:
- 文档 – 生成脚本可用作介绍如何生成软件的文档。 这消除了与部署应用程序相关的一些“魔力”,并使开发人员能够专注于功能。
- 可重复性 – 生成脚本可确保每次编译和部署应用程序时,无论是谁或做什么工作,它都以相同的方式发生。 这种可重复的一致性消除了由于执行不当的生成或人为错误而可能出现的任何问题或错误。
- 版本控制 – 生成脚本可以包含在源代码管理系统中。 这意味着,如果发现错误或不准确,则可以跟踪、监视和更正对生成脚本所做的更改。
- 准备环境 – 生成脚本可以包含用于安装任何所需的第三方依赖项的逻辑。 这将确保应用程序是使用合适的组件生成的。
生成脚本可以像 PowerShell 文件(在 Windows 上)或 bash 脚本(在 OS X 上)一样简单。 创建生成脚本时,脚本语言有多种选择:
Rake - 这是一种特定于域的语言 (DSL),用于基于 Ruby 生成项目。 Rake 具有受欢迎的优势和丰富的库生态系统。
psake - 这是用于生成软件的 Windows PowerShell 库
FAKE – 这是基于 F# 的 DSL,可让用户根据需要使用现有的 .NET 库。
使用哪种脚本语言取决于你的偏好和要求。
备注
可以使用基于 XML 的生成系统(如 MSBuild 或 NAnt),但这些生成系统缺乏专用于构建软件的 DSL 的表达能力和可维护性。
生成和测试软件的过程需要应保密的信息。 创建 APK 可能需要密钥存储的密码和/或密钥存储中的密钥别名。 同样,App Center Test 需要对开发人员唯一的 API 密钥。 这些类型的值不应在生成脚本中硬编码。 应将其作为变量传递给生成脚本。
不太敏感的值包括 iOS 设备 ID 或 Android 设备 ID 等,这些值用于识别 App Center 应用于测试运行的设备。 这些值不需要保护,但它们可能会随着生成的不同而变化。
通过将这些类型的变量存储在生成脚本之外,还可以更轻松地在组织中共享生成脚本,例如与开发人员共享。 开发人员可以使用与生成服务器完全相同的脚本,但可以使用自己的密钥存储和 API 密钥。
有两种可能的选项可用于存储这些敏感值:
配置文件 – 为了保护 API 密钥,不应将此值签入到版本控制中。 可以为每个计算机创建该文件。 从此文件中读取值的方式取决于所使用的脚本语言。
环境变量 – 这些变量可以在每台计算机上轻松进行设置,并且独立于基础脚本语言。
每种选择都各有优缺点。 TeamCity 可以很好地处理环境变量,因此本指南将在创建生成脚本时推荐此技术。
生成脚本必须执行以下步骤:
编译应用程序 – 这包括使用正确的预配配置文件对应用程序进行签名。
将应用程序提交到 Xamarin Test Cloud – 这包括使用相应的密钥存储对 APK 进行签名和压缩对齐。
下面将更详细地介绍这两个步骤。
以下命令行指定适用于 iPhone 的解决方案 SOLUTION_FILE.sln 的发布版本。 可以通过在命令行上指定 IpaPackageDir
属性来设置 IPA 的位置:
在 Mac 上使用 xbuild:
xbuild /p:Configuration="Release" \ /p:Platform="iPhone" \ /p:IpaPackageDir="$HOME/Builds" \ /t:Build MyProject.sln
xbuild 命令通常位于目录 /Library/Frameworks/Mono.framework/Commands 中。
在 Windows 上,使用 msbuild:
msbuild /p:Configuration="Release" /p:Platform="iPhone" /p:IpaPackageDir="%USERPROFILE%\Builds" /p:ServerAddress="192.168.1.3" /p:ServerUser="macuser" /t:Build MyProject.sln
msbuild 不会自动展开命令行传入的 $( )
表达式。 因此,建议在命令行上设置 IpaPackageDir
时使用完整路径。
有关 IpaPackageDir
属性的更多详细信息,请参阅 iOS 9.8 发行说明。
若要编译 Android 应用程序,请使用 xbuild(或在 Windows 上使用 msbuild):
/Library/Frameworks/Mono.framework/Commands/xbuild /t:SignAndroidPackage /p:Configuration=Release /path/to/android.csproj
编译 Android 应用程序 xbuild 使用项目,而 iOS 应用程序 xbuild 则使用解决方案。
UITest 是使用 App Center CLI 提交的,如以下代码片段所示:
appcenter test run uitest --app <TEAM-NAME/APP-NAME> --devices <DEVICE_SET> --token <API_KEY> --app-path <appname.APK-or-appname.IPA> --merge-nunit-xml report.xml --build-dir pathToUITestBuildDir
运行测试时,将以名为 report.xml 的 NUnit 样式 XML 文件的形式返回测试结果。 TeamCity 将在生成日志中显示信息。
有关如何将 UITest 提交到 App Center 的详细信息,请参阅准备 Xamarin.Android 应用或准备 Xamarin.iOS 应用。
Calabash 测试是使用 App Center CLI 提交的,如以下代码片段所示:
appcenter test run calabash --app <TEAM-NAME/APP-NAME> --devices <DEVICE_SET> --token <API_KEY> --app-path <appname.APK-or-appname.IPA> --project-dir pathToProjectDir
若要将 Android 应用程序提交到 App Center Test,必须先使用 calabash-android 重新生成 APK 测试服务器:
$ calabash-android build </path/to/signed/APK>
$ appcenter test run calabash --app <TEAM-NAME/APP-NAME> --devices <DEVICE_SET> --token <API_KEY> --app-path <appname.APK> --project-dir pathToProjectDir
有关提交 Calabash 测试的详细信息,请参阅 Xamarin 关于将 Calabash 测试提交到Test Cloud 的指南。
一旦安装了 TeamCity,并且 Visual Studio for Mac 可以生成项目,即可在 TeamCity 中创建项目,以生成项目并将其提交到 App Center。
首先,通过 Web 浏览器登录到 TeamCity。 导航到根项目:
在根项目下,创建新的子项目:
创建子项目后,添加新的生成配置:
将 VCS 项目附加到生成配置。 此操作通过“版本控制设置”屏幕完成:
如果没有创建 VCS 项目,则可以从如下所示的“新建 VCS 根”页创建一个:
附加 VCS 根后,TeamCity 将检查项目,并尝试自动检测生成步骤。 如果你熟悉 TeamCity,则可以选择检测到的生成步骤之一。 现在可以安全地忽略检测到的生成步骤。
接下来,配置生成触发器。 当满足某些条件时,例如当用户将代码提交到存储库时,这会将生成加入队列。 以下屏幕截图显示了如何添加生成触发器:
可以在以下屏幕截图中看到配置生成触发器的示例:
上一部分“参数化生成脚本”建议将某些值存储为环境变量。 可以通过“参数”屏幕将这些变量添加到生成配置。 添加 App Center API 密钥、iOS 设备 ID 和 Android 设备 ID 的变量,如以下屏幕截图所示:
最后一步是添加生成步骤,它将调用生成脚本以编译应用程序并将应用程序排入 App Center Test。 以下屏幕截图是生成步骤的示例,该步骤使用 Rakefile 生成应用程序:
此时,生成配置已完成。 最好通过触发生成来确认项目已正确配置。 执行此操作的一个好方法是向存储库提交微不足道的小更改。 TeamCity 应该会检测提交并启动生成。
生成完成后,请检查生成日志,查看生成中是否存在任何需要注意的问题或警告。
本指南介绍了如何使用 TeamCity 生成 Xamarin Mobile 应用程序,然后将其提交到 App Center Test。 我们讨论了如何创建生成脚本以自动执行生成过程。 生成脚本负责编译应用程序、提交到 App Center Test 并等待结果。
然后,我们介绍了如何在 TeamCity 中创建一个项目,每次开发人员提交代码并调用生成脚本时,都会将生成加入队列。