运行iOS版本-第3部分,React Native DevOps指南

TLDR: 为三种构建类型配置一个React Native iOS项目:开发,登台和发布。 自定义构建行为以实现Xcode的可重复性,然后使用Fastlane简化流程。 使用Jenkins自动化Fastlane构建流程。

简介| 设置| 预建| iOS | Android | 詹金斯| CodePush | 测试中

概要

概念— Xcode

  • 构建类型和目的地
  • 按键和配置文件
  • 管理Xcode
  • 构型
  • 方案
  • 构建设置
  • 建立阶段
  • 新建系统

概念— Fastlane

  • 车道
  • 选件
  • 元数据/ App Store
  • 詹金斯

演练

  • 创建登台配置
  • 创建开发,暂存和发布方案
  • 编辑构建选项和阶段
  • 查看签名配置
  • 添加Fastlane车道,选项
  • 添加iOS Fastlane元数据
  • 创建詹金斯职位
  • 测试工作

系统总览

概念— Xcode

构建类型和目的地

苹果肯定喜欢使应用程序开发复杂化。 如本系列的第1部分所述,iOS的命名构建类型比Android多得多。

复杂性的主要驱动因素是供应配置文件。

每个配置文件都会限制可以运行您的应用的合格设备的数量。 发布版本只能在设备上运行,并且必须从beta或prod应用商店中安装。 开发构建以设备或模拟器为目标,并且强制配置文件还通过UUID限制了合格的硬件设备目标。 向配置文件添加新的硬件设备涉及到developer.apple.com进行更新和下载新配置文件的烦人之旅。

如果您具有三种不同的构建配置(dev,staging,release),那么最终将有五种不同的构建配置来支持模拟器和物理设备。 如果您使用CodePush并具有两个目标密钥,则构建配置的数量将增加。

  • 开发人员 :模拟器,设备
  • 分期 :模拟器,设备
  • 发布 :设备

Fastlane可以使用CLI参数指定二进制目标来简化复杂性。 xcodebuild (内置的快速通道操作)与xcodebuild命令行工具进行接口。

在下面的代码中,我们定义了一个simulator变量,其值由环境,命令参数或默认值设置。 simulator在三元表达式中用作xcodebuild动作的参数,使我们可以灵活地选择应用程序目标。

  // Fastfile 
 模拟器= handle_env_and_options(ENV [“ SIMULATOR”], 
options [:simulator],false)
  xcodebuild( 
...
目的地:(模拟器?
“ generic / platform = iOS模拟器”:
“ generic / platform = iOS”),
),
...

按键和配置文件

Match可以自动创建,存储和更新iOS供应配置文件和签名证书。 然后,由Match生成的所有文件都将存储在加密的git存储库中,并具有开发团队共享的解密密钥。

如果您尚未为团队设置此功能,请参阅“比赛”教程以开始使用。

在我们的iOS通道中使用Match来验证配置文件和证书的有效性,并正确指定用于给定版本的密钥和配置文件。 在xcodebuild操作中使用凭证名称字符串来选择所需的凭证类型。

管理Xcode

接下来,我们将研究Xcode的内部结构,以及Xcode的流程如何适合我们RN项目的整体情况。 这里有两个很棒的资源,它们可以更深入地深入Xcode内部。

  • 管理Xcode
  • 堆栈溢出:用简单的语言讲,目标和方案是什么?

构型

配置在每个构建的基础上管理Xcode中的一组变量。 在我们的应用程序中,配置与我们为Fastlane构建创建的构建类型匹配1:1。

开箱即用的RN入门Xcode项目带有DebugRelease配置。 我们将添加Staging配置,并为每个配置修改一些参数。

添加了Staging ,我们将拥有与三种主要构建类型匹配的构建配置。 这些交叉引用了本教程第2部分中创建的env文件。 我们将在Android教程的第4部分中重复此设置。

方案

方案定义了xcodebuild采取何种步骤来生产最终产品。 在构建过程中,构建目标可以经历以下步骤:分析,测试,构建,运行,分析和存档。

通过减少每个构建中使用的这些步骤的数量,我们可以减少构建时间,尤其是对于开发和过渡构建。 如果您的项目主要是用Javascript编写的,那么即使没有测试/分析/配置文件发行版本,您也可以摆脱困境。

在方案构建选项卡中,取消选中要跳过的所有步骤。 对于大多数构建,我仅使用运行和存档步骤。 请注意,这是一个取决于项目的选择-如果您使用大量的Swift / Obj-C,则可能需要包含分析/测试/配置文件。

构建设置

用户定义的构建设置使我们可以基于给定的配置来设置变量。 RN项目有一些必须添加的选项,您可能除了这些之外还有其他选择。

在添加过渡配置+方案时,我们还必须调整每个变量的构建设置,以确保我们生成正确的产品。 这是重要的变量列表,添加新的方案+配置后,您将要查看它们。

构建位置:构建产品路径,中间构建文件路径

构建选项:验证构建产品

链接:死代码剥离

签名:代码签名身份,开发团队

Apple LLVM 9.0 —代码生成:优化级别,隐藏符号

Apple LLVM 9.90 —预处理:预处理器宏

搜索路径:框架,标题,库

包装:产品名称

用户定义: MTL_ENABLE_DEBUG_INFO,SWIFT_OPTIMIZATION_LEVEL,捆绑包ID后缀

添加束ID后缀是测试和验证所必需的。 通过添加捆绑软件ID后缀,您可以在同一部手机或模拟器上并排安装应用程序的开发,登台和发布版本。 没有后缀,您一次只能使用一个应用程序版本。

您还必须编辑Info.plist,将${BUNDLE_ID_SUFFIX}添加到Bundle Identifier键中。 有关更多信息,请参见Chris Miles的这篇文章。

建立阶段

最后要讨论的是构建阶段。 构建阶段允许您定义构建前和构建后的操作,例如捆绑JS,管理Cocoapod,将调试符号上载到跟踪提供程序等等。

Bundle React Native code and images步骤中有三个重要更改。

  • 为可预测的行为设置已知的外壳程序-使用运行CLI操作的外壳程序。
  • 获取自定义节点可执行文件路径
    source “${SRCROOT}/../env/node_binary
  • 自定义react-native-xcode.sh

Xcode在Bundle React Native code and images步骤中调用react-native-xcode.sh。 该脚本只需要开发和发布两个构建配置/方案。

为了确保在阶段中正确捆绑JS,请创建一个自定义脚本react-native-xcode-custom.sh并将此文件放在项目根目录的子目录中。 编辑文件以支持暂存配置/方案(或者,从示例存储库中克隆)。

基本应用程序的捆绑阶段如下所示:

新建系统

苹果公司最近首次发布了一个新的构建系统,该系统包含在最新版本的Xcode中(自2017年11月起)。 有报告称,构建时间有所缩短。 我尚未尝试使用RN项目构建该系统。 如果您感到好奇,请查看此仓库以获取更多信息。

概念—快速通道

快速文件中iOS通道的主要目标是管理复杂性并创建可重复的构建过程。 我们将继续使用dev / staging / release作为主要的构建类型。 通过配置文件提供的其他构建目标,我们还将创建用于指定模拟器或设备构建的通道选项。

高层次:

  • Xcode提供了无限的可配置性
  • Fastlane在与Xcode进行交互时强制使用重复的模式,从而减少了选项的数量,但仍提供了高配置性
  • Jenkins通过参数化作业来限制Fastlane的可配置性。 选项应该很少更改。

快速通道阶段

对于每个构建,fastlane都经历以下阶段:

  • 解析选项
  • 预构建:徽章,比赛,cocoapods
  • 构建:xcodebuild,健身房
  • postbuild:安装到模拟器,交付,webhook

车道

iOS有3条主要通道,如果在项目中使用CodePush,则可能更多。

  • dev :调试配置,模拟器或设备,debug = true
  • 登台 :登台配置,模拟器或设备,debug = false
  • release :发布配置,设备,debug = false,适用于应用商店

选件

选项使我们可以在执行时调整通道变量。 这是与Jenkins互操作性的关键组成部分。 通过Jenkins构建参数传递给fastlane CLI调用的选项,将使我们能够从上面列出的3条主要iOS通道中生产各种产品。

我使用以下选项:

  • 徽章 (布尔):在应用程序图像上生成带有版本,修订以及devbeta标志的徽章覆盖图
  • 模拟器 (布尔):将产品定位为在模拟器上运行
  • clean (bool):在执行xcodebuild操作之前清理项目工作区
  • xcargs (字符串):传递给xcbuild任何其他构建时cli参数
  • install (bool):将应用安装为正在运行的模拟器,以进行后期构建操作
  • app_store (布尔):在成功release版本之后将应用程序提交到iTunes Connect
  • 钩子 (布尔):将Webhook成功/失败消息发送到已定义的Webhook端点(在fastfile中)
  • 通道 (字符串):定义Slack Webhook集成的通道名称

App Store元数据

在Fastlane样板和项目存储库中,您会找到用于与App Store一起使用的预生成的元数据文件。 编辑AppfileDeliverfile并使用您的项目特定信息进行更新。

Deliverfile存储所有元数据和相关信息,以上传到Play商店。 在开始使用Fastlane将完整的构建版本交付给App Store之前,您需要更新所有这些信息,因为通过iTunes Connect上的手动数据输入可以节省您的时间。

Fastlane +詹金斯

现在我们有了通道和选项来进一步控制每个通道的行为,我们将利用此设置来执行Jenkins作业。 此外,我们可以将多个快速通道操作聚合到一个Jenkins作业中,从而简化构建流程。

通过从基本作业转移到参数化作业,我们现在可以在调用快速通道时通过环境变量传递作业参数。

fastlane ios staging xcargs:$XCARGS simulator:$SIMULATOR

触发作业时,单击“ Build now with parameters ,然后根据自己的喜好调整构建。

为您创建的每个作业都包含每个选项是没有意义的。 大多数时候,不需要对构建进行参数化,尤其是在您建立一致的流程之后。

让我们以mobile-staging-simulator为例。 在这里,我们将使用暂存配置触发针对模拟器的iOS和Android构建。 在这项工作中并不需要参数化。 构建步骤如下所示:

  #!/ usr / local / bin / zsh 
源$ HOME / .zshrc
  fastlane ios登台模拟器:true 
Fastlane Android分期

这是使用此技术构建的一些示例快速通道聚合。 在第5部分中,我们将充分利用您的Jenkins代理。

  • mobile-scheduled-compile :开发版,android + ios,验证二进制产品是否存在
  • 每晚移动一次:分阶段进行构建,Android + ios,设备目标,对构建产品进行存档,在专用的夜间办公桌上安装至电话以供员工进行测试
  • mobile-staging-simulator:分段构建,android + ios,模拟器目标
  • mobile-staging-device:分段构建,android + ios,设备目标
  • mobile-prod-binary:发布版本,android + ios,上传到各自的商店

演练

建议您在学习本教程时克隆配套的存储库,以进行比较和参考。 此处使用的示例项目称为myCoolApp

  1. 创建登台配置

在Xcode中打开您的项目。 在“ Navigator窗格中单击项目名称,导航到“ Info选项卡,然后从子导航器窗格中突出显示您的项目名称。 按下+号,然后单击Duplicate "Release" Configuration 。 将配置重命名为Staging

2. 创建开发,暂存和发布方案

从状态栏中下拉“ Product菜单,选择“ Scheme ,然后单击位于方案列表最底部的“管理方案”。

您将看到默认的项目方案,它与您的项目同名。 突出显示该方案,然后单击重复。 将方案重命名为myCoolApp-staging 。 重复myCoolApp-release

现在,我们将修改所有三个方案。 从调试/开发方案myCoolApp (未重命名,如果愿意,可以重新命名)。 突出显示该方案,然后单击编辑。

对于每个阶段( Run, Test, Profile, Analyze, and Archive ,请确保“ Build Configuration下拉选择与配置匹配。

我们不会为每种方案使用所有阶段。 如果以后需要添加这些阶段之一,则最好现在将它们全部设置为相同的配置。

现在,单击左侧导航器窗格中的“ Build菜单。 对于调试/开发方案,我优先考虑构建速度而不是完整性。 因此,我将仅在此方案期间使用Run

另外,请注意,我从参与构建步骤中删除了myCoolAppTests 。 有关使用此方法进行权衡的更深入讨论,请参见上面的概念部分。

简而言之,如果您有一个主要基于JS领域的项目,那么我发现分析,测试和概要分析步骤会增加时间而没有很多好处。 如果您有一个Swift / Obj-C繁重的应用程序,那么通过包括这些步骤,您可能会获得更多价值。

完成后,单击“ close ,然后返回到方案编辑器。 对myCoolApp-stagingmyCoolApp-release重复相同的流程。 单击左侧导航器窗格上方的myCoolApp ,作为访问其他方案的快捷方式。

3. 编辑构建设置

返回项目编辑器。 在左侧的子导航器窗格中,单击myCoolApp下的myCoolApp 。 然后,从顶部菜单中选择“ Build Settings选项卡。 单击选项卡菜单中的AllCombined 。 现在,我们将基于方案选择进行更改以构建变量。

每个构建配置都可以修改所有变量。 如果所有三个值都相同,则变量名左侧将没有可见的下拉箭头。 如果将鼠标悬停在变量名称的左侧,则会出现一个下拉箭头,以便您可以进行特定于配置的更改。

我将以粗体显示搜索词,并在下面建议进行更改。

  • 构建位置:确保一切看起来像预期的发布和发布。 Per-config Build Products Path Release Per-config Build Products Path应类似于Build/Release-iphoneos
  • 验证内置产品DebugStaging设置为NO。 这是速度优化。
  • 无效代码剥离: Staging设置为YES。
  • 签名 :设置Staging的代码签名身份以匹配Debug 。 如果尚未设置签名配置,则可以返回此步骤。 我们将在后面介绍。
  • 代码生成:Optimization Level设置为与“ Staging配置的Release相匹配。 我还将Symbols Hidden by Default将“ Symbols Hidden by Default设置为“是”。
  • 预处理程序宏:编辑Staging以匹配发行版。 这将删除调试标志。 要进行更改,请双击该值并删除$(inherited)
  • 搜索路径/框架:双击“ Framework Search Paths旁边的值,一次编辑所有三个配置。 使用左下角的加号按钮将$(PROJECT_DIR)添加到列表中,作为非递归搜索。

登台配置的重要更改
我们需要进行一些改动,以使Framework search paths在登台配置中正常工作。 双击“ Framework search paths下“ Staging旁边的值。 使用加号将$(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)为递归搜索。

为了与为React Native构建的第三方模块具有互操作性,需要进行此更改。 由于许多人不支持暂存配置,因此暂存构建会将重要框架放在Release下的目录中。 因此,通过更改框架搜索路径以查看发行版目录,即使在使用第三方模块时,我们也可以正确链接所有内容。

现在, Framework search paths旁边的值应为

  • 搜索路径/标题: dd $(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)/include作为Staging搜索路径的非递归搜索。
  • 搜索路径/库:$(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)作为非递归搜索添加到Staging搜索路径。
  • 产品名称:修改产品名称以匹配构建配置。
    重要说明:如果确实使用Xcode的内置测试,则还需要修改测试产品名称目标。 在不修改测试目标产品名称的情况下构建Debug ,构建将失败,因为Xcode找不到myCoolApp 。 产品名称现在为myCoolApp-debug ,但是测试目标仍在寻找myCoolApp
  • MTL_ENABLE_DEBUG_INFO:设置调试=是, 登台和发布=否
  • 优化级别:修改登台密钥以匹配发布密钥, Fastest, Smallest [-Os]
  • BUNDLE_ID_SUFFIX:清除所有现有搜索词,然后滚动到“ Build Settings选项卡的最底部。 在页面顶部搜索框左侧的过滤器行中按+号。 将BUNDLE_ID_SUFFIX添加为新变量,并为DebugStaging添加值。

4. 查看签名配置

导航到“ General选项卡,在左侧子导航器窗格myCoolApp作为目标。 至此,您将需要设置Match来管理您的证书和配置文件,以及一个共享的加密git存储库。

取消选中Automatically manage signing ,然后确认您的操作。 现在,为这三种构建类型的每一种修改Provisioning ProfileSigning certificate 。 只有“ Release应该使用发布配置文件和证书。

5. 编辑构建阶段

导航到Build Phases选项卡,并在左侧子导航器窗格myCoolApp作为目标。 单击Bundle React Native code and images旁边的下拉箭头。

首先,将外壳更改为熟悉的外壳。 我在所有系统上都使用zsh ,所以我也在这里使用它。 接下来,在系列的第2部分中定义的自定义节点可执行文件中提供source 。 这将加载到NODE_BINARY环境变量中,因此我们正在使用NVM设置的节点。

最后,我们将使用自定义的捆绑脚本react-native-xcode-custom.sh ,该脚本增加了对Staging构建方案的支持。 您可以自己编辑和保存此文件,也可以从配套存储库中复制它。

6. 编辑Info.plist

在最左侧的导航器窗格中,打开myCoolApp文件夹,然后双击Info.plist。

  • 编辑Bundle display name ,并将其更改为$(PRODUCT_NAME)
  • 编辑Bundle identifier并将其更改为$(PRODUCT_BUNDLE_IDENTIFIER)$(BUNDLE_ID_SUFFIX)

保存并关闭文件。

7. 运行测试版本

使用顶部状态栏左上角的方案导航器选择所需的方案。 运行所有三个方案的构建,并验证所构建的产品是否正常运行以及所有搜索路径是否正确匹配。

如果您遇到构建问题,请重新访问步骤3并确保所有修改都是正确的。

8. 与Fastlane集成

至此,您应该已经能够通过Xcode生成3种不同的版本。 现在,我们将采用此流程并将其通过Fastlane移至CLI。

克隆react-native-fastlane-boilerplate并将存储库放置在项目根目录中。 如果要避免管理子模块,请删除.git子文件夹。

编辑fastlane/Fastfile ,将常量值更改为与您的项目匹配的值。 另外,编辑Appfile, Deliverfile, and Gymfile以匹配您的项目值和路径。

另外,请查看示例repo react-native-dev-ops-guide并更新您自己的Fastlane实现,以匹配我们在此处构建的流程。

假设您已经按照本教程进行了学习,那么您应该能够以最少的更改基于样板运行一些Fastlane测试。

在继续执行Jenkins步骤之前,请确保您已成功从CLI运行以下命令。

fastlane ios dev clean:true simulator:true

fastlane ios staging clean:true simulator:true

额外功能

  • 将内置产品直接安装到模拟器。
    打开iOS模拟器并使其运行,然后运行以下命令。 这将卸载所有具有匹配捆绑软件ID的捆绑软件,然后安装并启动您新建的二进制文件。
    fastlane ios dev clean:true simulator:true install:true
  • 在构建之前对应用程序图标进行徽章
    badge:true标志添加到您的构建命令中。 您的图标将带有devbeta徽标,具体取决于您运行的是dev还是staging版本。
    fastlane ios dev clean:true simulator:true install:true badge:true

故障排除说明

  • 如果您没有付费的开发者帐户,则将无法生成配置文件以在设备上运行您的应用程序。 确保在构建时使用simulator:true标志,以避免错误。
  • 确保已正确更新fastlane/Fastfile常数值以匹配您的项目。
  • 确保所有路径都是正确的,包括区分大小写。 您可能有一个自定义的构建产品路径,该路径在Xcode首选项的系统级别以及工作区设置的项目级别设置。

9. 创建詹金斯职位

现在我们有了Fastlane,可以通过命令行运行Xcode构建,我们可以将相同的功能移植到我们的Jenkins代理中!

我们将创建三个工作:

  • mobile-compile :验证最新代码是否可以成功构建
  • 移动阶段:生成阶段构建(以后将功能扩展到在手机上自动安装)
  • 移动生产:生成发行版本并上传到应用商店

对于每个:

  • 创造新工作
  • 设置github访问权限
  • 设置为参数作业,因此我们可以传入fastlane参数
  • 确保在构建开始之前删除工作空间(每次都从新的节点模块开始)
  • Execute shell步骤添加到构建阶段

现在,编辑每个作业的shell脚本以匹配以下内容:

  #### mobile-compile #### 
  #!/ usr / local / bin / zsh 
源$ HOME / .zshrc
  fastlane ios dev clean:$ CLEAN模拟器:$ SIMULATOR 
  #### 移动阶段 #### 
  #!/ usr / local / bin / zsh 
源$ HOME / .zshrc
  fastlane ios暂存干净:$ CLEAN模拟器:$ SIMULATOR 
  #### 移动制作 #### 
  #!/ usr / local / bin / zsh 
源$ HOME / .zshrc
  fastlane ios版本app_store:$ APP_STORE 

确保为每个作业设置了每个参数变量。 对于发行版,出于安全性考虑,应将$APP_STORE变量默认设置为false。 这样,您就不会在准备就绪之前意外地上传发行版本。

10. 测试詹金斯职位

现在,测试每个作业。 单击Build with Parameters ,然后运行每种作业类型的完整构建。

如果您在构建类型方面遇到问题,请调试该问题,直到获得构建一致性为止。

请注意,fastlane喜欢在遇到错误后重新构建日志的最后X行。 您可能需要在控制台日志中进行一些挖掘,以找到遇到的确切构建错误。

如果您仍然遇到问题,请随时发表评论,我们可以一起看看。

工作顺利完成后,请深呼吸,然后轻拍一下自己! 将构建操作转移到Jenkins上很耗时,但从长远来看会有所收获,尤其是随着您的团队的成长和您的应用程序变得更加复杂。

接下来,我们将在第4部分中对Android进行相同的处理。