与Unity的持续集成:如何减少组装时间并节省资源+支付线作为礼物



大家好,我与Pixonic的技术专家Alexander Panov联系。 在公司,我负责项目间解决方案和项目附近的外围设备,今天,我想分享我的经验和最佳实践。

持续开发和集成的平台,即CI / CD,如今在迭代和运行良好的技术流程起着决定性作用的那些行业中广泛使用。 在本文中,我们将讨论用于实施我们的Unity项目以进行手机游戏开发的CI / CD:遇到了什么问题,如何解决这些问题,实现了哪些改进以及如何注册了管道装配。

立即同意我们使用JetBrains的 TeamCity作为CI服务器,使用GitHub作为Git存储库的存储库,以及使用Nexus来存储程序集工件的Nexus。

因此,我们面临以下问题:

  • 缺少用于创建程序集的通用标准:几乎所有开发人员都可以访问TeamCity服务器,因此,程序集脚本是用不同的编程语言(BASH,PowerShell,Python)编写的,并且逻辑经常被复制;
  • 车队薄弱:由于我们需要为iOS构建版本,因此我们不得不使用Mac mini的车队。 而且由于在Unity中几乎整个装配都是在一个线程中进行的,因此在一台机器上并行化装配是有问题的。
  • 调试后的运行效率略有降低:由于我们技术支持的低效率,组装花费了很长时间。
  • 等待大量装配 TeamCity代理的大型队列
  • 每个项目都有一个单独的代理程序池:由于设备上安装的环境不同,以及项目之间的配置文件冲突(缓存服务器配置文件等),因此无法组织公共池。

结果您做了什么?


  • 程序集脚本的存储库

首先,我们为Python中的程序集创建了一个脚本库。 在Pipenv虚拟环境管理环境中执行启动,并在其服务器上代理第三方库,以快速更新和控制所需库的版本。 因此,我们为所有现有项目的装配体提供了单个入口点。 我们重写了Python中的所有脚本,统一了配置,形成了通用标准,删除了代码的重复项。

  • 新车队

有必要减少组装时间,可能减少使用的设备数量。

最初,我们拥有13台Mac mini计算机,但是这种解决方案远非最佳方案:由于Unity上程序集的特殊性,大约80%的组装时间将仅在一个线程中执行。 再加上对硬盘的大量写入访问,我们发现一个Mac mini几乎无法应付1-2个并发程序集。

结果是需要检查硬件。

在搜索和比较Unity组件的替代方案时,我们注意到基于AMD Ryzen的计算机由于其性能允许同时组装多达8-12个组件而不会造成明显的性能损失,因此决定购买四台此类设备和六个SSD。每个硬盘驱动器两个代理。

表中给出了它的变化和变化的比较。



平均构建时间:



此外,我们对TeamCity代理的选择进行了优先排序,以减少程序集在队列中花费的时间。 以前,我们的每个项目都有自己的代理程序池,由于游戏具有多平台性质,因此依赖于项目的环境不允许创建公共池。 现在,在系统重组之后,我们将许多座席分配给了项目,这些座席用于自动装配,但是能够为所有项目添加几个通用座席:当与所需项目相关联的所有座席都在忙时,它们会包含在工作中。

  • BuildPipeline库,用于Unity

他们为Unity启动了一个小型库,这使在单独的Unity编辑器窗口中设置构建版本成为可能,并且还能够以批处理模式运行构建版本。 从库的主要功能来看:它允许您在组装之前添加和删除定义,禁用第三方库或特定文件,添加自定义的预处理和后处理步骤,所有设置都存储在配置文件中,也有可能继承它们。


BuildPipeline库中的define窗口

我们当前的管道CI / CD


PullRequest程序集。 对于每次提交:

  1. 启动Unity以检查编译错误,定义更新并生成解决方案;
  2. 运行测试;
  3. 启动静态分析器:在其帮助下,对受当前PullRequest影响的文件执行增量分析;
  4. 有关验证结果的消息,保存在GitHub上。

Unity项目构建步骤:

1.安装Pipenv并运行用于在Python中构建的脚本:从我们的服务器更新和安装第三方Python库(代理pypi.org存储库),然后运行构建脚本。

2. Unity组装的初步准备:

  • 删除库文件夹,捆绑包,选择性资产(按掩码和/或特定文件),删除解决方案(.sln文件)-如有必要;
  • 生成程序集信息文件:分支名称,程序集号等。 -在构建中进一步用于调试和测试;
  • 为项目设置Unity缓存服务器。 每个项目都有自己的项目。 每个开发人员还设置了一个缓存服务器以加快填充速度:开发人员添加新资产时,它将自动出现在缓存服务器和构建服务器上-因此导入资产要快得多。

3.运行Unity以检查编译错误,更新定义并生成解决方案。

4.运行测试,如果有错误,请退出测试-如有必要。

5.启动带有必要配置和其他项目参数的Unity BuildPipeline。

6.对于Android / iOS构建-启动Gradle / Xcode:

  • Gradle-GradleWrapper;
  • Xcode-将Unity之后获得的XcodeProject存档,并将其复制到Mac mini。 分别安装和更新所有必需的证书和Provisioning Profile文件。 运行命令清理,存档,导出。
  • 在导出阶段,​​可以分离构建,开发人员和AppStore的签名。 根据我们收集的内容,选择所需的plist,或依次选择每个plist。 在输出中,我们得到两个文件:Developer和Release-分别用于在测试设备上安装和上传到AppStore。

7.对于独立的程序集,将收集的内部版本和相关文件(日志,测试结果,.obb,用于安装iOS应用程序的清单,dsym文件等)倒入工件存储中,以将独立的程序集-将收集的内部版本上载到档案存储中。

8.生成带有QR码的页面,用于安装构建,添加来自存储库的链接以及将构建信息添加到数据库,以进一步使用PixLauncher应用程序-我们将在后面讨论。

9.向Slack发送有关组装结果的信息:发送给发起组装的人员以及必要的渠道。


这样的消息来到Slack

进一步的步骤


作为计划的最后一步,将收集的内部版本分发到设备以进行进一步测试,然后上传到商店。

为了在设备上安装构建,我们编写了一个用于Android和iOS的小型应用程序-PixLauncher。 我们会将其安装在可以从TeamCity中选择内部版本的每台设备上。 为了方便起见,您可以在其中设置过滤器-例如,将配置添加到收藏夹中,然后一键执行操作。 对于Android版本,如果需要,将自动下载.obb分辨率的文件。

此外,我们还组织了通过推送通知安装构建的功能:我们向TeamCity服务器添加了一个自写插件,该插件使您可以在构建页面上选择连接到本地网络的设备的MAC地址。 然后,将带有安装链接的推式通知发送到这些设备-现在,只需单击即可执行。

因此,该应用程序允许部门加快搜索所需质量检查构建的速度,并将其安装在设备上以进行后续验证。


PixLauncher iOS App的外观

最后,将内部版本上传到商店


在执行了所有动作之后,自然会形成有保证的向各方填充应用程序上的构建和元信息的需求。

最初,问题主要出现在AppStore上:

  • 只能通过MacOS设备进行填充;
  • 您必须以25种以上的语言上传视频,屏幕截图和应用程序说明。

这导致大量的填充时间损失,并且在将文件下载到管理面板时崩溃。 因此,我们考虑了过程自动化。

结果,我们得到以下结果:

  1. 在Google磁盘中,我们获得了一个平板电脑,其中包含所有语言的应用程序说明;
  2. 该应用程序的视频和屏幕截图以指定的名称排列在文件夹中;
  3. 在Teamcity中,为了选择一个已经组装好的版本,他们根据发布版本进行了配置。
  4. 通过适用于Apple的GooglePlay API和iTMSTransporter,在商店中使用所有必需的语言填写有关应用程序的内部版本和元信息。 在出现问题的情况下(例如,在网络上)-我们进行了几次尝试,并向错误消息发送消息给Slack。


这就是将构建上传到AppStore的样子

结果-一些数字


  • 现在,我们每天大约有400个装配体和多达60个设备上的构建安装。
  • TeamCity上有57种不同的构建配置。
  • 我们使用22个TeamCity代理,同时可以将性能扩展到48个代理而不会造成重大损失。
  • 机队有可能横向扩展。

Source: https://habr.com/ru/post/zh-CN484172/


All Articles