This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

使用 EAS Workflows 自动化开发构建

编辑页面

了解如何使用 EAS Workflows 自动化 Android 和 iOS 开发构建,并在仅 JavaScript 更改时使用指纹跳过重新构建。


每次向 GitHub 仓库推送时都手动重建开发客户端可能会很慢。团队成员或拉取了原生更改(新增模块、新权限、SDK 升级)的新贡献者,需要等待一次全新的构建后才能运行项目。

main 分支上自动化开发构建可以保持一个可随时安装的最新构建。我们可以运行 eas build:dev 来安装最新的兼容构建。如果项目指纹与现有构建匹配,EAS 会下载该构建,而不是创建一个新的。

学习目标

  • 使用 build 作业类型为 Android 和 iOS 自动化 开发构建
  • 使用 fingerprintget-build 作业在本地代码未更改时跳过重新构建
  • 添加一个自定义单元测试作业,在测试通过后再继续工作流

Prerequisites

1 requirement

已配置用于开发的 EAS Build

当我们第一次为某个配置文件触发构建时,EAS CLI 会提示生成凭据。请先为 Android 和 iOS 手动触发开发构建,这样在工作流运行之前就已经存在这些凭据:

Terminal
eas build --profile development --platform all

build 作业类型用于开发构建

build 作业类型是 EAS Workflows 提供的 预打包作业 之一。我们不需要定义构建过程的每一步,而是使用 build 作业类型来运行 Android 和 iOS 的 EAS Build。

在本章中,我们使用 eas.json 中的 development 构建配置。我们在 Expo 应用开发期间使用此配置。

1

添加一个 build.yml

.eas/workflows/ 中,添加一个名为 build.yml 的新文件。它使用带有 profileplatform 参数的 build 作业类型,为 Android 和 iOS 创建开发构建。

将以下代码添加到 build.yml 文件中:

.eas/workflows/build.yml
name: 开发构建 jobs: build_android: name: 构建 Android type: build params: platform: android profile: development build_ios: name: 构建 iOS type: build params: platform: ios profile: development

我们添加了两个作业:build_androidbuild_ios。它们都属于 build 类型,但针对平台和构建配置使用了不同的参数。

每个作业中的 params 键包括:

  • platform 设置构建的目标操作系统(androidios
  • profile 指定 eas.json 中的构建配置

2

手动运行工作流

让我们使用以下命令手动运行工作流:

Terminal
eas workflow:run .eas/workflows/build.yml

3

在 EAS 仪表板中验证

在 EAS 仪表板中,注意在 Workflow graph 选项卡下显示的是 “Triggered manually”。只要 Trigger 显示 Manual,就表示该工作流是通过 eas workflow:run 命令启动的。

每个构建的日志都会显示在工作流界面中。点击某个构建的 ID 即可打开其 EAS Build 页面。

在进入下一步之前,请等待两个构建都完成。完成后,我们就可以使用 InstallOpen with Orbit 按钮,或者从 Artifacts 下载,以便在我们的设备/模拟器/仿真器上安装。

使用指纹跳过不必要的构建

当我们的项目只有 TypeScript/JavaScript 变更时,现有的开发构建仍然兼容,因此我们不需要新的构建。

Expo Fingerprint 自动化了这个判断。它会对项目的原生特征(依赖项、原生项目文件、配置)进行哈希计算。如果该哈希与现有构建匹配,说明原生代码没有变化,EAS 就会跳过重新构建。如果哈希不同,说明原生代码已变更,EAS 就会创建一个新构建。

让我们一步一步更新 build.yml,以检测原生变更,并且只在需要时构建。

1

添加 fingerprint 任务

fingerprint 预打包任务会对项目的原生特征进行哈希计算,并为每个平台输出一个 fingerprint 哈希。environment 字段告诉 EAS 应该使用哪种环境变量配置。请注意,environmentprofile 可能同名,但它们指代的是不同的内容。profile 指向 eas.json 中的构建配置文件(如何构建)。environment 指向在 EAS 上配置的环境变量(构建时注入哪些值)。

更新 build.yml,在构建任务之前添加 fingerprint 任务:

.eas/workflows/build.yml
name: Development builds jobs: fingerprint: name: Fingerprint type: fingerprint environment: development build_android: # ... build_ios: # ...

fingerprint 任务会产生两个输出:android_fingerprint_hashios_fingerprint_hash。我们会在下一步中使用这些哈希来检查是否已经存在兼容的构建。

2

添加 get-build 任务

get-build 预打包任务会检查针对给定 fingerprint 哈希和 profile 是否已经存在构建。如果存在匹配的构建,它会输出一个 build_id。如果不存在,build_id 为空。

在我们的工作流文件中,让我们在 fingerprint 和构建任务之间添加 get_android_buildget_ios_build 任务。每个任务都使用 needs: [fingerprint] 等待 fingerprint 任务完成,并获取其输出:

.eas/workflows/build.yml
name: Development builds jobs: fingerprint: # ... get_android_build: name: Check for existing Android build needs: [fingerprint] type: get-build params: fingerprint_hash: ${{ needs.fingerprint.outputs.android_fingerprint_hash }} profile: development get_ios_build: name: Check for existing iOS build needs: [fingerprint] type: get-build params: fingerprint_hash: ${{ needs.fingerprint.outputs.ios_fingerprint_hash }} profile: development build_android: # ... build_ios: # ...

在上面的工作流中,get-build 任务通过 ${{ needs.fingerprint.outputs.* }} 表达式语法接收来自上一个任务的 fingerprint 哈希。

3

添加条件构建

if 字段控制任务是否运行。表达式 ${{ !needs.get_android_build.outputs.build_id }} 的意思是:仅当 get-build 没有找到匹配的构建时才运行该任务! 是取反运算符。如果针对这个 fingerprint 已经存在兼容的构建,则会跳过构建任务。

让我们更新每个构建任务,使其依赖对应的 get-build 任务,并添加 if 条件:

.eas/workflows/build.yml
name: Development builds jobs: fingerprint: # ... get_android_build: # ... get_ios_build: # ... build_android: name: Build Android needs: [get_android_build] if: ${{ !needs.get_android_build.outputs.build_id }} type: build params: platform: android profile: development build_ios: name: Build iOS needs: [get_ios_build] if: ${{ !needs.get_ios_build.outputs.build_id }} type: build params: platform: ios profile: development

4

添加触发器并运行工作流

让我们为工作流添加 on.push 触发器,这样它就会在每次推送到 main 时自动运行:

.eas/workflows/build.yml
name: Development builds on: push: branches: ['main'] jobs: fingerprint: name: Fingerprint type: fingerprint environment: development get_android_build: name: Check for existing Android build needs: [fingerprint] type: get-build params: fingerprint_hash: ${{ needs.fingerprint.outputs.android_fingerprint_hash }} profile: development get_ios_build: name: Check for existing iOS build needs: [fingerprint] type: get-build params: fingerprint_hash: ${{ needs.fingerprint.outputs.ios_fingerprint_hash }} profile: development build_android: name: Build Android needs: [get_android_build] if: ${{ !needs.get_android_build.outputs.build_id }} type: build params: platform: android profile: development build_ios: name: Build iOS needs: [get_ios_build] if: ${{ !needs.get_ios_build.outputs.build_id }} type: build params: platform: ios profile: development

假设我们对 Expo 项目做了一些 TypeScript/JavaScript 变更,比如修改按钮颜色或更新某个界面上的文本。完成后,我们可以向 main 分支推送一个提交,以便从 GitHub 仓库触发工作流:

Terminal
git add .
git commit -m "Update button label and tweak styling"
git push origin main

这会触发一个新的工作流,并在几秒钟内完成。在 EAS 仪表盘上,Android 和 iOS 构建都会被跳过,因为上一节中已经存在一个匹配的构建。

我们从 main 分支拉取最新代码,然后运行 npx expo start。现有的开发构建会应用这些 JS 变更。

单元测试的自定义任务

在团队协作时,我们希望推送到 main 分支的每一次变更都能先通过测试,然后再触发新的构建。

如果没有自动化,团队成员就必须记得在推送到 main 之前先在本地运行测试。万一忘记了,而且代码中存在失败的测试,下一次工作流就可能基于有问题的代码创建构建。

借助 EAS Workflows,我们可以将自定义任务与现有的预置任务组合起来,从而自动化这个过程。这个自定义任务会在 fingerprint 和构建任务之前运行。如果测试失败,EAS 会停止工作流,并且不会创建任何构建。

1

为单元测试添加一个自定义任务

在我们的 build.yml 工作流文件中,先添加一个在构建开始前运行单元测试的自定义任务:

.eas/workflows/build.yml
name: Development builds on: push: branches: ['main'] jobs: run_tests: name: Run unit tests steps: - uses: eas/checkout # 检出仓库 - uses: eas/install_node_modules - run: npx jest --ci fingerprint: name: Fingerprint needs: [run_tests] type: fingerprint environment: development get_android_build: # ... get_ios_build: # ... build_android: # ... build_ios: # ...

自定义的 run_tests 任务会执行以下操作:

  • uses: eas/checkout 从 GitHub 仓库中检出项目源文件。自定义任务会在一台新的虚拟机上运行,因此默认情况下代码不可用。在访问任何项目文件之前,这一步是必需的。
  • uses: eas/install_node_modules 使用项目中检测到的包管理器(bun、npm、pnpm 或 Yarn)安装依赖。在运行任何依赖 node_modules 中包的命令之前都需要这一步,例如 Jest。
  • run: npx jest --ci 执行测试套件。run 键可以运行任意 shell 命令,类似于 echo 命令。--ci 标志告诉 Jest 以 CI 模式运行,这会跳过对文件变更的监听,并在所有测试运行完成后退出。

现在,fingerprint 任务具有 needs: [run_tests],因此它只会在测试通过后运行。如果测试失败,EAS 会跳过工作流的其余部分。

2

触发工作流

将更新后的工作流与测试文件一起提交并推送到 main

Terminal
git add .
git commit -m "Add unit tests to development builds workflow"
git push origin main

触发工作流后,打开 EAS 仪表盘,注意我们工作流中各个任务的执行流程。

摘要

Chapter 2: Development builds

We automated development builds using pre-packaged jobs, added fingerprints to skip unnecessary rebuilds, and integrated unit tests as a custom job before the build pipeline.

In the next chapter, learn how to create preview builds with Slack notifications and PR preview updates.

Next: Chapter 3: Preview builds