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

使用 EAS 工作流自动化开发构建

学习如何使用 EAS 工作流程自动化 Android 和 iOS 的开发构建,并在只有 JavaScript 发生变化时使用指纹跳过重建。


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

🌐 Manually rebuilding a development client on every push to a GitHub repository can be slow. Team members or new contributors who pull native changes (a new module, a new permission, an SDK upgrade) wait for a fresh build before they can run the project.

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

🌐 Automating development builds on the main branch keeps a current build ready to install. We can run eas build:dev to install the latest compatible build. If the project fingerprint matches an existing build, EAS downloads that build instead of creating a new one.

学习成果

🌐 Learning outcomes

  • 使用 build 工作类型自动化 Android 和 iOS 的 开发构建
  • 使用 fingerprint 和 get-build 任务在本地代码没变时跳过重建
  • 添加一个自定义单元测试任务,只有测试通过才会继续工作流

先决条件

1 要求

EAS Build 已配置为开发模式

第一次为某个配置触发构建时,EAS CLI 会提示生成凭证。在工作流运行之前,手动触发 Android 和 iOS 的开发构建,以确保凭证已经存在:

🌐 EAS CLI prompts to generate credentials the first time we trigger a build for a profile. Trigger the development build manually for both Android and iOS so the credentials exist before the workflow runs:

Terminal
- eas build --profile development --platform all

开发版本的 build 工作类型

🌐 The build job type for development builds

build 作业类型是 EAS 工作流中的预打包作业之一。我们不用定义构建过程的每个步骤,而是使用 build 作业类型来运行 Android 和 iOS 的 EAS 构建。

🌐 The build job type is one of the pre-packaged jobs from EAS Workflows. Instead of defining each step of the build process, we use the build job type to run an EAS Build for Android and iOS.

在本章中,我们使用 eas.json 中的 development 构建配置文件。在开发 Expo 应用时,我们会使用这个配置文件。

🌐 For this chapter, we use the development build profile from our eas.json. We use this profile during Expo app development.

1

添加一个 build.yml

🌐 Add a build.yml

在 .eas/workflows/ 里面,添加一个名为 build.yml 的新文件。它使用 build 作业类型,配合 profile 和 platform 参数来为 Android 和 iOS 创建开发构建。

🌐 Inside .eas/workflows/, add a new file called build.yml. It uses the build job type with profile and platform parameters to create development builds for Android and iOS.

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

🌐 Add the following code to the build.yml file:

.eas/workflows/build.yml
name: Development builds jobs: build_android: name: Build Android type: build params: platform: android profile: development build_ios: name: Build iOS type: build params: platform: ios profile: development

我们添加了两个任务:build_android 和 build_ios。它们都是 build 类型的,但平台和构建配置参数不同。

🌐 We add two jobs: build_android and build_ios. Both are of type build with different parameters for platform and build profile.

每个工作的 params 键包括:

🌐 The params key for each job includes:

  • platform 设置构建的目标操作系统(android 或 ios)
  • profile 指定了我们 eas.json 中的构建配置文件

2

手动运行工作流

🌐 Run the workflow manually

让我们用命令手动运行这个工作流:

🌐 Let's run the workflow manually using the command:

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

3

在EAS仪表板上确认

🌐 Verify on the EAS dashboard

在 EAS 仪表板上,注意在 Workflow graph 标签下显示“Triggered manually”。每当 Trigger 显示 Manual 时,这意味着工作流是通过 eas workflow:run 命令启动的。

🌐 On the EAS dashboard, notice that it says "Triggered manually" under the Workflow graph tab. Any time the Trigger shows Manual, that means the workflow was started with the eas workflow:run command.

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

🌐 The logs for each build appear inside the workflow interface. Click a build's ID to open its EAS Build page.

在进行下一步之前,先等两个构建都完成。完成后,我们可以使用安装或用 Orbit 打开按钮,或者从Artifacts下载来安装到我们的设备/模拟器/模拟器上。

🌐 Wait for both builds to complete before moving to the next step. Once they complete, we can use the Install or Open with Orbit buttons, or download from Artifacts to install on our device/emulator/simulator.

通过指纹跳过不必要的构建

🌐 Skip unnecessary builds with fingerprints

当我们的项目只有 TypeScript/JavaScript 的修改时,现有的开发构建仍然兼容,所以我们不需要新的构建。

🌐 When our project has only TypeScript/JavaScript changes, the existing development build is still compatible, so we do not need a new one.

Expo 指纹 会自动做出这个决定。它会对项目的原生特性(依赖、原生项目文件、配置)进行哈希。如果哈希值与现有构建匹配,说明原生代码没有变化,EAS 就会跳过重建。如果哈希值不同,说明原生代码有变化,EAS 就会创建一个新的构建。

让我们一步步更新 build.yml,以检测本地更改并仅在需要时构建。

🌐 Let's update build.yml step by step to detect native changes and build only when needed.

1

添加指纹任务

🌐 Add a fingerprint job

fingerprint 预打包任务会对项目的原生特性进行哈希处理,并为每个平台输出一个指纹哈希。environment 字段告诉 EAS 使用哪个 环境变量配置。注意,environment 和 profile 可以同名,但指的是不同的东西。profile 指向 eas.json 中的构建配置文件(如何构建)。environment 指向在 EAS 上配置的环境变量(构建时注入哪些值)。

🌐 The fingerprint pre-packaged job hashes the project's native characteristics and outputs a fingerprint hash for each platform. The environment field tells EAS which environment variable configuration to use. Note that environment and profile can share the same name but refer to different things. profile points to a build profile in eas.json (how to build). environment points to environment variables configured on EAS (which values to inject at build time).

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

🌐 Update build.yml to add the fingerprint job before the build jobs:

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

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

🌐 The fingerprint job produces two outputs: android_fingerprint_hash and ios_fingerprint_hash. We use these hashes in the next step to check if a compatible build already exists.

2

添加获取构建任务

🌐 Add get-build jobs

get-build 预打包作业会检查指定的指纹哈希和配置是否已有构建存在。如果存在匹配的构建,它会输出一个 build_id。如果没有,build_id 则为空。

🌐 The get-build pre-packaged job checks if a build already exists for a given fingerprint hash and profile. If a matching build exists, it outputs a build_id. If not, build_id is empty.

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

🌐 In our workflow file, let's add get_android_build and get_ios_build jobs between fingerprint and the build jobs. Each one uses needs: [fingerprint] to wait for the fingerprint job to complete and access its output:

.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.* }} 表达式语法从上一个任务接收指纹哈希。

🌐 In the above workflow, get-build jobs receive the fingerprint hash from the previous job using the ${{ needs.fingerprint.outputs.* }} expression syntax.

3

添加条件构建

🌐 Add conditional builds

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

🌐 The if field controls whether a job runs. The expression ${{ !needs.get_android_build.outputs.build_id }} means: run a job only if get-build did not find a matching build. The ! is a negation operator. If a compatible build already exists for this fingerprint, the build job is skipped.

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

🌐 Let's update each build job to depend on its get-build job and add the if condition:

.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

添加一个触发器并运行工作流程

🌐 Add a trigger and run the workflow

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

🌐 Let's add the on.push trigger to the workflow so it runs automatically on every push to 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 仓库触发工作流:

🌐 Let's assume we made some TypeScript/JavaScript changes to our Expo project, like changing a button's color or updating the text on a screen. After doing so, we can push a commit to the main branch to trigger the workflow from our GitHub repository:

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

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

🌐 This triggers a new workflow that completes in seconds. On the EAS dashboard, both Android and iOS builds are skipped because a matching build already exists from the previous section.

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

🌐 We pull the latest from the main branch and run npx expo start. The existing development build picks up the JS changes.

单元测试的自定义任务

🌐 Custom jobs for unit testing

在团队工作时,我们希望每次推送到 main 分支的修改在触发新构建之前都能通过测试。

🌐 When working in a team, we want every change pushed to the main branch to pass tests before triggering a new build.

没有自动化的话,团队必须记得在推送到 main 之前本地运行测试。如果他们忘了,而且代码有测试失败,下一个工作流程可能会从有问题的代码创建构建。

🌐 Without automation, the team has to remember to run tests locally before pushing to main. If they forget and the code has a failing test, the next workflow can create a build from broken code.

通过 EAS 工作流,我们可以通过将自定义任务与现有的预封装任务混合来自动化这个过程。这个自定义任务会在指纹和构建任务之前运行。如果测试失败,EAS 会停止工作流并且不会创建构建。

🌐 With EAS Workflows, we can automate this process by mixing a custom job with our existing pre-packaged jobs. This custom job runs before fingerprint and build jobs. If a test fails, EAS stops the workflow and creates no build.

1

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

🌐 Add a custom job for unit tests

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

🌐 In our build.yml workflow file, let's add a custom job that runs unit tests before the builds start:

.eas/workflows/build.yml
name: Development builds on: push: branches: ['main'] jobs: run_tests: name: Run unit tests steps: - uses: eas/checkout # Check out the repo - 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 任务会执行以下操作:

🌐 The custom run_tests job does the following:

  • 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 会跳过剩下的工作流程。

🌐 Now, the fingerprint job has needs: [run_tests], so it only runs after the tests pass. If tests fail, EAS skips the rest of the workflow.

2

触发工作流程

🌐 Trigger the workflow

提交并推送更新后的工作流以及测试文件到 main:

🌐 Commit and push the updated workflow along with the test file to main:

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

触发工作流后,打开 EAS 仪表板,看看我们工作流中作业的流动情况。

🌐 After triggering the workflow, open the EAS dashboard and notice the flow of the jobs inside our workflow.

概括

🌐 Summary

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.

下一个:Chapter 3: Preview builds