EAS Workflows 语法
编辑页面
EAS Workflows 配置文件语法参考指南。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
工作流是一个可配置的自动化流程,由一个或多个作业组成。你必须创建一个 YAML 文件来定义你的工作流配置。
要开始使用工作流,请参见 EAS Workflows 入门 或查看 示例 以获取完整的工作流配置。
工作流文件
工作流文件使用 YAML 语法,文件扩展名必须是 .yml 或 .yaml。如果你是 YAML 新手并想进一步了解,请参见 一分钟学习 YAML。
工作流文件位于项目中的 .eas/workflows 目录下。.eas 目录应与你的 eas.json 文件处于同一级别。
例如:
my-app.easworkflowscreate-development-builds.ymlpublish-preview-update.ymldeploy-to-production.ymleas.json配置参考
下面是工作流配置文件语法的参考说明。
name
工作流的人类可读名称。它会显示在 EAS 控制台的工作流列表页面上,并作为工作流详情页的标题。
name: My workflow
on
on 键定义哪些 GitHub 事件会触发该工作流。无论 on 键如何设置,任何工作流都可以通过 eas workflow:run 命令触发。
on: # 在推送到 main 分支时触发 push: branches: - main # 以及在以 'version-' 开头的拉取请求时触发 pull_request: branches: - version-*
你可以在提交信息中包含[eas skip]、[skip eas]或[no eas]来跳过由push和pull_request触发的工作流运行。
on.push
当你将提交推送到匹配的分支和/或标签时运行你的工作流。
使用 branches 列表,你可以仅在推送到指定分支时触发工作流。例如,如果你使用 branches: ['main'],只有推送到 main 分支时才会触发工作流。支持 glob。通过使用 ! 前缀,你可以指定要忽略的分支(你仍需要提供至少一个不带 ! 的分支模式)。
使用 tags 列表,你可以仅在推送指定标签时触发工作流。例如,如果你使用 tags: ['v1'],只有推送 v1 标签时才会触发工作流。支持 glob。通过使用 ! 前缀,你可以指定要忽略的标签(你仍需要提供至少一个不带 ! 的标签模式)。
使用 paths 列表,你可以仅在文件变更匹配指定路径时触发工作流。例如,如果你使用 paths: ['apps/mobile/**'],只有 apps/mobile 目录中的文件发生变化时才会触发工作流。支持 glob。默认情况下,任何路径的变化都会触发工作流。
当未提供 branches 和 tags 时,branches 默认为 ['*'],tags 默认为 [],这意味着工作流会在所有分支的 push 事件上触发,而不会在标签推送时触发。如果只提供了两个列表中的一个,另一个默认为 []。
on: push: branches: - main - feature/** - !feature/test-** # 其他分支名称和 glob tags: - v1 - v2* - !v2-preview** # 其他标签名称和 glob paths: - apps/mobile/** - packages/shared/** - !**/*.md # 忽略 markdown 文件
on.pull_request
当你创建或更新一个目标分支匹配的拉取请求时运行你的工作流。
使用 branches 列表,你可以仅在拉取请求的目标分支是指定分支时触发工作流。例如,如果你使用 branches: ['main'],只有合并到 main 分支的拉取请求才会触发工作流。支持 glob。未提供时默认为 ['*'],这意味着工作流会在所有分支的拉取请求事件上触发。通过使用 ! 前缀,你可以指定要忽略的分支(你仍需要提供至少一个不带 ! 的分支模式)。
使用 types 列表,你可以仅在指定的拉取请求事件类型上触发工作流。例如,如果你使用 types: ['opened'],只有 pull_request.opened 事件(即拉取请求首次打开时发送的事件)才会触发工作流。未提供时默认为 ['opened', 'reopened', 'synchronize']。支持的事件类型:
openedready_for_reviewreopenedsynchronizelabeled
使用 paths 列表,你可以仅在文件变更匹配指定路径时触发工作流。例如,如果你使用 paths: ['apps/mobile/**'],只有 apps/mobile 目录中的文件发生变化时才会触发工作流。支持 glob。默认情况下,任何路径的变化都会触发工作流。
on: pull_request: branches: - main - feature/** - !feature/test-** # 其他分支名称和 glob types: - opened # 其他事件类型 paths: - apps/mobile/** - packages/shared/** - !**/*.md # 忽略 markdown 文件
on.pull_request_labeled
当拉取请求被赋予匹配的标签时运行你的工作流。
使用 labels 列表,你可以指定当哪些标签被添加到拉取请求时会触发工作流。例如,如果你使用 labels: ['Test'],只有给拉取请求添加 Test 标签时才会触发工作流。未提供时默认为 [],这意味着没有任何标签会触发工作流。
为了更简洁的语法,你也可以直接向 on.pull_request_labeled 提供一个匹配标签列表。
on: pull_request_labeled: labels: - Test - Preview # 其他标签
或者:
on: pull_request_labeled: - Test - Preview # 其他标签
on.app_store_connect
当所选的 App Store Connect 事件之一发生时运行你的工作流。
要使用此触发器,请在 EAS 控制台 中配置你的 App Store Connect 连接。设置步骤请参见 App Store Connect 触发器设置 部分。
当存在 on.app_store_connect 时,你必须至少指定一个事件域(app_version、build_upload、external_beta 或 beta_feedback)。在已配置的事件域中,你可以指定哪些状态应触发你的工作流。
on.app_store_connect.app_version.states
过滤 App Store 应用版本状态变更事件。未提供时默认为所有支持的应用版本状态。
支持的值:
accepteddeveloper_rejectedin_reviewinvalid_binarymetadata_rejectedpending_apple_releasepending_developer_releaseprepare_for_submissionprocessing_for_distributionready_for_distributionready_for_reviewrejectedreplaced_with_new_versionwaiting_for_export_compliancewaiting_for_review
on.app_store_connect.build_upload.states
按状态过滤构建上传事件。未提供时默认为所有支持的构建上传状态。
支持的值:
completefailedprocessingawaiting_upload
on.app_store_connect.external_beta.states
按状态过滤外部测试版事件。未提供时默认为所有支持的外部测试版状态。
支持的值:
processingprocessing_exceptionmissing_export_complianceready_for_beta_testingin_beta_testingexpiredready_for_beta_submissionin_export_compliance_reviewwaiting_for_beta_reviewin_beta_reviewbeta_rejectedbeta_approved
on.app_store_connect.beta_feedback.types
按类型过滤测试人员报告的测试版反馈。未提供时默认为所有支持的测试版反馈类型。
支持的值:
crashscreenshot
所有过滤值必须为小写且区分大小写。
# 在以下情况触发: # - 应用版本进入审核, # - 构建上传完成或失败, # - 外部测试版构建已可供测试或已获批准, # - 测试人员通过 TestFlight 报告崩溃。 on: app_store_connect: app_version: states: - ready_for_review - waiting_for_review build_upload: states: - complete - failed external_beta: states: - ready_for_beta_testing - beta_approved beta_feedback: types: - crash
# 在任何应用版本或构建上传状态变更时触发。 on: app_store_connect: app_version: {} build_upload: {}
on.schedule.cron
使用 unix-cron 语法按计划运行你的工作流。你可以使用 crontab guru 及其 示例 来生成 cron 字符串。
- 计划任务工作流只会在仓库的默认分支上运行。在许多情况下,这意味着位于
main分支上的工作流文件中的 cron 会被调度,而特性分支中的工作流文件里的 cron 则不会被调度。 - 在高负载期间,计划任务工作流可能会延迟。高负载时段包括每个整点的开始。在极少数情况下,作业可能会被跳过或运行多次。请确保你的工作流是幂等的,并且不会产生有害副作用。
- 一个工作流可以有多个
cron计划。 - 计划任务工作流以 GMT 时区运行。
on: schedule: - cron: '0 0 * * *' # 每天 GMT 午夜运行
on.workflow_dispatch.inputs
定义可在使用 eas workflow:run 命令手动触发工作流时提供的输入。这使你能够创建参数化工作流,让它们每次运行时都可以接受不同的值。
on: workflow_dispatch: inputs: name: type: string required: false description: '要问候的人的姓名' default: 'World' choice_example: type: choice options: - to be - not to be required: true
| 属性 | 类型 | 必需 | 描述 |
|---|---|---|---|
type | string | 是 | 输入类型(string、boolean、number、choice 或 environment)。 |
description | string | 否 | 输入的说明。 |
required | boolean | 否 | 是否需要该输入。默认为 false。 |
default | varies | 否 | 输入的默认值。必须与输入类型匹配。 |
options | string[] | 是(针对 type: choice) | 可用于选择输入的选项。 |
提供输入
运行带有输入的工作流时,你可以通过以下几种方式提供它们:
-
命令行标志:
Terminal-eas workflow:run .eas/workflows/deploy.yml -F environment=production -F debug=true -F version=1.2.3 -
通过 stdin 传入 JSON:
Terminal-echo '{"environment": "production", "debug": true, "version": "1.2.3"}' | eas workflow:run .eas/workflows/deploy.yml -
交互式提示: 如果缺少必需输入且你未使用
--non-interactive,CLI 会提示你输入:Terminal-eas workflow:run .eas/workflows/deploy.yml
用法
输入值可在你的工作流作业中通过 ${{ inputs.<input_name> }} 语法使用:
on: workflow_dispatch: inputs: name: type: string required: true description: '要问候的人的姓名' jobs: deploy: steps: - name: Deploy to environment run: | echo "Hello, ${{ inputs.name }}!" # 注意:你可以使用 `||` 为 # 非 eas-workflow:run-run 工作流提供默认值。 echo "Hello, ${{ inputs.name || 'World' }}!"
jobs
一个 workflow 运行由一个或多个 job 组成。
jobs: job_1: # ... job_2: # ...
jobs.<job_id>
每个 job 都必须有一个 ID。该 ID 在 workflow 内应唯一,并且可以包含字母数字字符和下划线。例如,下面 YAML 中的 my_job:
jobs: my_job: # ...
jobs.<job_id>.name
在 workflow 详情页中显示的、对人类更友好的 job 名称。
jobs: my_job: name: Build app
jobs.<job_id>.environment
为 job 设置 EAS 环境变量 环境。有三种可能的值:
production(默认)previewdevelopment
environment 键可用于所有 job。
jobs: my_job: environment: production | preview | development
jobs.<job_id>.env
为 job 设置环境变量。该属性可用于所有在 VM 上运行的 job(除预打包的 require-approval、doc、get-build 和 slack job 外的所有 job)。
jobs: my_job: env: APP_VARIANT: staging RETRY_COUNT: 3 PREV_JOB_OUTPUT: ${{ needs.previous_job.outputs.some_output }}
jobs.<job_id>.defaults.run.working_directory
设置该 job 中所有步骤运行命令时所在的目录。
jobs: my_job: defaults: run: working_directory: ./my-app steps: - name: 我的第一步 run: pwd # 打印:/home/expo/workingdir/build/my-app
defaults
用于作为 workflow 配置中所有 job 默认值的参数。
defaults.run.working_directory
脚本运行的默认工作目录。像 "./assets" 或 "assets" 这样的相对路径会从应用的基础目录开始解析。
defaults.tools
应为此 workflow 配置中定义的 job 使用的特定工具版本。有关可用值,请遵循各工具的文档。
| 工具 | 描述 |
|---|---|
node | 通过 nvm 安装的 Node.js 版本。 |
yarn | 通过 npm -g 安装的 Yarn 版本。 |
corepack | 如果设为 true,corepack 将在构建过程开始时启用。默认为 false。 |
pnpm | 通过 npm -g 安装的 pnpm 版本。 |
bun | 通过向 Bun 安装脚本传入 bun-v$VERSION 安装的 Bun 版本。 |
ndk | 通过 sdkmanager 安装的 Android NDK 版本。 |
bundler | 将传递给 gem install -v 的 Bundler 版本。 |
fastlane | 将传递给 gem install -v 的 fastlane 版本。 |
cocoapods | 将传递给 gem install -v 的 CocoaPods 版本。 |
使用 defaults.tools 的 workflow 示例:
name: 设置自定义版本 defaults: tools: node: latest yarn: '2' corepack: true pnpm: '8' bun: '1.0.0' fastlane: 2.224.0 cocoapods: 1.12.0 on: push: branches: ['*'] jobs: setup: steps: - name: 检查 Node 版本 run: node --version # 应输出一个具体版本,例如 23.9.0 - name: 检查 Yarn 版本 run: yarn --version # 应输出一个具体版本,例如 2.4.3
concurrency
并发控制配置。目前只允许为同分支 workflow 设置 cancel_in_progress。
concurrency: cancel_in_progress: true group: ${{ workflow.filename }}-${{ github.ref }}
| 属性 | 类型 | 描述 |
|---|---|---|
cancel_in_progress | boolean | 如果为 true,GitHub 新启动的 workflow 运行将取消当前同一分支上正在进行的运行。 |
group | string | 我们暂不支持自定义并发组。请设置这个占位值,以便将来支持自定义组时,你的 workflow 仍然兼容。 |
控制流
你可以通过 needs 和 after 关键字控制某个 job 何时运行。另外,你还可以使用 if 关键字基于条件控制 job 是否应运行。
jobs.<job_id>.needs
在此 job 运行之前必须成功完成的 job ID 列表。
jobs: test: steps: - uses: eas/checkout - uses: eas/use_npm_token - uses: eas/install_node_modules - name: tsc run: yarn tsc build: needs: [test] # 只有当 'test' job 成功时,此 job 才会运行 type: build params: platform: ios
jobs.<job_id>.after
在此 job 运行之前必须完成(成功或失败均可)的 job ID 列表。
jobs: build: type: build params: platform: ios notify: after: [build] # 此 job 将在 build 完成后运行(无论 build 成功还是失败)
jobs.<job_id>.if
if 条件用于决定 job 是否应运行。当 if 条件满足时,job 将运行;当条件不满足时,job 将被跳过。被跳过的 job 不会算作成功完成,并且任何后续 job 如果在其 needs 列表中包含该 job,也不会运行。
jobs: my_job: if: ${{ github.ref_name == 'main' }}
插值
你可以根据 workflow 运行的上下文,自定义 workflow 的行为——包括要执行的命令、控制流、环境变量、构建配置、应用版本等。
使用 ${{ expression }} 语法来访问上下文属性和函数。例如:${{ github.ref_name }} 或 ${{ needs.build_ios.outputs.build_id }}。
上下文属性
在插值上下文中可用的属性如下:
after
当前 job 的 after 列表中指定的所有上游 job 的记录。每个 job 提供:
{ "status": "success" | "failure" | "skipped", "outputs": {} }
示例:
jobs: build: type: build params: platform: ios notify: after: [build] steps: - run: echo "Build status: ${{ after.build.status }}"
needs
当前 job 的 needs 列表中指定的所有上游 job 的记录。每个 job 提供:
{ "status": "success" | "failure" | "skipped", "outputs": {} }
大多数预打包 job 会暴露特定输出。你可以使用 set-output 函数 在自定义 job 中设置输出。
示例:
jobs: setup: outputs: date: ${{ steps.current_date.outputs.date }} steps: - id: current_date run: | DATE=$(date +"%Y.%-m.%-d") set-output date "$DATE" build_ios: needs: [setup] type: build env: # 你可以使用 process.env.VERSION_SUFFIX # 在动态 app 配置中自定义应用版本。 VERSION_SUFFIX: ${{ needs.setup.outputs.date }} params: platform: ios profile: development
steps
当前 job 中所有步骤的记录。每个步骤提供其通过 set-output 函数设置的输出。
注意:
steps上下文仅在 job 的 steps 内可用,而不在 workflow 级别可用。要将某个步骤的输出暴露给其他 job,请使用set-output函数 和 job 的outputs配置。
示例:
jobs: my_job: outputs: value: ${{ steps.step_1.outputs.value }} steps: - id: step_1 run: set-output value "hello" - run: echo ${{ steps.step_1.outputs.value }} another_job: needs: [my_job] steps: - run: echo "Value: ${{ needs.my_job.outputs.value }}"
inputs
手动通过 workflow_dispatch 触发 workflow 时提供的输入记录。在通过 eas workflow:run 命令并带有输入参数触发 workflow 时可用。
示例:
on: workflow_dispatch: inputs: name: type: string required: true jobs: greet: steps: - run: echo "Hello, ${{ inputs.name }}!"
github
为了便于从 GitHub Actions 迁移到 EAS Workflows,我们暴露了一些你可能会觉得有用的上下文字段。
type GitHubContext = { triggering_actor?: string; event_name: 'pull_request' | 'push' | 'schedule' | 'workflow_dispatch'; sha: string; ref: string; // 例如 refs/heads/main ref_name: string; // 例如 main ref_type: 'branch' | 'tag' | 'other'; commit_message?: string; // 仅对 push 和 schedule 事件可用 label?: string; repository?: string; repository_owner?: string; event?: { label?: { name: string; }; // 仅对 push 和 schedule 事件可用 head_commit?: { message: string; id: string; }; pull_request?: { number: number; title: string; body: string | null; state: 'open' | 'closed'; draft: boolean; merged: boolean | null; // ... 来自 GitHub Pull Request webhook payload 的其他字段 }; number?: number; schedule?: string; inputs?: Record<string, string | number | boolean>; }; };
信息
event对象包含完整的 GitHub webhook payload。对于pull_request事件,event.pull_request包含 GitHub Pull Request webhook payload 中的所有字段。上面展示的是常用字段,但user、labels、milestone等其他字段也同样可用。
如果 workflow 运行是通过 eas workflow:run 启动的,则其 event_name 为 workflow_dispatch,其余所有属性都将为空。
示例:
jobs: build_ios: type: build if: ${{ github.ref_name == 'main' }} params: platform: ios profile: production
查看 ${{ github }} 定义的源代码。
workflow
当前 workflow 的信息。
type WorkflowContext = { id: string; name: string; filename: string; url: string; };
示例:
jobs: notify_slack: after: [...] type: slack params: message: | Workflow 运行已完成:${{ workflow.name }} 查看详情:${{ workflow.url }}
app_store_connect
与 workflow 运行相关联的 App Store Connect 实体信息。此上下文仅适用于由 App Store Connect 事件触发的 workflow。参见 on.app_store_connect。
type AppStoreConnectContext = { app: { id: string; }; build_upload?: { id: string; state: 'awaiting_upload' | 'processing' | 'failed' | 'complete'; }; };
app_store_connect.build_upload 对象仅在 workflow 由 build_upload 事件域触发时存在。
示例:
on: app_store_connect: build_upload: states: - complete jobs: notify: type: slack params: webhook_url: ${{ env.SLACK_WEBHOOK_URL }} message: | App Store Connect 应用上传完成:${{ app_store_connect.app.id }} 上传 ID:${{ app_store_connect.build_upload.id }} 上传状态:${{ app_store_connect.build_upload.state }}
env
当前 job 上下文中可用的环境变量记录。
注意:
env上下文仅在 job 的上下文中可用,而不在 workflow 级别可用。
示例:
jobs: my_job: steps: - run: echo "API URL: ${{ env.API_URL }}"
上下文函数
在插值上下文中可用的函数如下:
success()
返回所有先前 job 是否都已成功。
jobs: notify: if: ${{ success() }} steps: - run: echo "所有 job 都已成功"
failure()
返回是否有任意先前 job 失败。
jobs: notify: if: ${{ failure() }} steps: - run: echo "有一个 job 失败了"
fromJSON(value)
解析 JSON 字符串。等同于 JSON.parse()。
示例:
jobs: publish_update: type: update print_debug_info: needs: [publish_update] steps: - run: | echo "First update group: ${{ needs.publish_update.outputs.first_update_group_id }}" echo "Second update group: ${{ fromJSON(needs.publish_update.outputs.updates_json || '[]')[1].group }}"
toJSON(value)
将值转换为 JSON 字符串。等同于 JSON.stringify()。
示例:
jobs: my_job: steps: - run: echo '${{ toJSON(github.event) }}'
contains(value, substring)
检查 value 是否包含 substring。
示例:
jobs: my_job: if: ${{ contains(github.ref_name, 'feature') }} steps: - run: echo "Feature branch"
startsWith(value, prefix)
检查 value 是否以 prefix 开头。
示例:
jobs: my_job: if: ${{ startsWith(github.ref_name, 'release') }} steps: - run: echo "Release branch"
endsWith(value, suffix)
检查 value 是否以 suffix 结尾。
示例:
jobs: my_job: if: ${{ endsWith(github.ref_name, '-production') }} steps: - run: echo "Production branch"
hashFiles(...globs)
返回与提供的 glob 模式匹配的文件哈希。适用于缓存键。
注意:
hashFiles函数仅在 job 的 steps 内可用,而不在 workflow 级别可用。
示例:
jobs: my_job: steps: - run: echo "Dependencies hash: ${{ hashFiles('package-lock.json', 'yarn.lock') }}"
replaceAll(input, stringToReplace, replacementString)
将 input 中所有 stringToReplace 的出现替换为 replacementString。
示例:
jobs: my_job: steps: - run: echo "${{ replaceAll(github.ref_name, '/', '-') }}"
substring(input, start, end)
从 input 中提取子字符串,起始位置为 start,结束位置为 end。如果未提供 end,则会从 start 一直提取到 input 的末尾。底层使用 String#substring 实现。
示例:
jobs: my_job: steps: - run: echo "${{ substring(github.ref_name, 0, 50) }}"
预打包任务
jobs.<job_id>.type
指定要运行的预打包任务类型。预打包任务会根据工作流详情页中的任务类型生成专门的 UI。
jobs: my_job: type: build
下面了解不同的预打包任务。
build
使用 EAS Build 为你的项目创建 Android 或 iOS 构建。有关详细信息和示例,请参阅 构建任务文档。
jobs: my_job: type: build params: platform: ios | android # required profile: string # optional, default: production message: string # optional
此任务输出以下属性:
{ "build_id": string, "app_build_version": string | null, "app_identifier": string | null, "app_version": string | null, "channel": string | null, "distribution": "internal" | "store" | null, "fingerprint_hash": string | null, "git_commit_hash": string | null, "platform": "ios" | "android" | null, "profile": string | null, "runtime_version": string | null, "sdk_version": string | null, "simulator": "true" | "false" | null }
deploy
使用 EAS Hosting 部署你的应用。有关详细信息和示例,请参阅 部署任务文档。
jobs: my_job: type: deploy params: alias: string # optional prod: boolean # optional
此任务输出以下属性:
{ "deploy_json": string, // 包含部署详情的 JSON 对象(`npx eas-cli deploy --json` 的输出)。 "deploy_url": string, // 部署的 URL。如果这是生产部署,则使用生产 URL。否则,使用第一个别名 URL 或部署 URL。 "deploy_alias_url": string, // 部署的别名 URL(例如,`https://account-project--alias.expo.app`)。 "deploy_deployment_url": string, // 部署的唯一 URL(例如,`https://account-project--uniqueid.expo.app`)。 "deploy_identifier": string, // 部署的标识符。 "deploy_dashboard_url": string, // 部署仪表板的 URL(例如,`https://expo.dev/projects/[project]/hosting/deployments`)。 }
fingerprint
计算你的项目指纹。有关详细信息和示例,请参阅 指纹任务文档。
jobs: my_job: type: fingerprint environment: production # 应与你的构建配置文件匹配
此任务输出以下属性:
{ "android_fingerprint_hash": string, "ios_fingerprint_hash": string, }
注意: 为了准确匹配指纹,请确保 fingerprint 任务的
environment与你的构建配置文件一致。为了让不同任务之间更一致,建议使用 EAS 环境变量 而不是env。
get-build
从 EAS 中检索与提供参数匹配的现有构建。有关详细信息和示例,请参阅 获取构建任务文档。
jobs: my_job: type: get-build params: platform: ios | android # optional profile: string # optional distribution: store | internal | simulator # optional channel: string # optional app_identifier: string # optional app_build_version: string # optional app_version: string # optional git_commit_hash: string # optional fingerprint_hash: string # optional sdk_version: string # optional runtime_version: string # optional simulator: boolean # optional wait_for_in_progress: boolean # optional
此任务输出以下属性:
{ "build_id": string, "app_build_version": string | null, "app_identifier": string | null, "app_version": string | null, "channel": string | null, "distribution": "internal" | "store" | null, "fingerprint_hash": string | null, "git_commit_hash": string | null, "platform": "ios" | "android" | null, "profile": string | null, "runtime_version": string | null, "sdk_version": string | null, "simulator": "true" | "false" | null }
submit
使用 EAS Submit 将 Android 或 iOS 构建提交到应用商店。有关详细信息和示例,请参阅 提交任务文档。
jobs: my_job: type: submit params: build_id: string # required profile: string # optional, default: production groups: string[] # optional
此任务输出以下属性:
{ "apple_app_id": string | null, // Apple App ID. https://expo.fyi/asc-app-id "ios_bundle_identifier": string | null, // 已提交构建的 iOS bundle identifier。https://expo.fyi/bundle-identifier "android_package_id": string | null // 已提交的 Android package ID。https://expo.fyi/android-package }
testflight
将 iOS 构建分发到 TestFlight 内部和外部测试组。有关详细信息和示例,请参阅 TestFlight 任务文档。
jobs: my_job: type: testflight params: build_id: string # required profile: string # optional, default: production internal_groups: string[] # optional external_groups: string[] # optional changelog: string # optional submit_beta_review: boolean # optional wait_processing_timeout_seconds: number # optional, default: 1800 (30 minutes)
此任务输出以下属性:
{ "apple_app_id": string | null, // Apple App ID. https://expo.fyi/asc-app-id "ios_bundle_identifier": string | null // 已提交构建的 iOS bundle identifier。https://expo.fyi/bundle-identifier }
update
使用 EAS Update 发布更新。有关详细信息和示例,请参阅 更新任务文档。
jobs: my_job: type: update params: message: string # optional platform: string # optional - android | ios | all, defaults to all branch: string # optional channel: string # optional - cannot be used with branch private_key_path: string # optional upload_sentry_sourcemaps: boolean # optional - defaults to "try uploading, but don't fail the job if it fails"
此任务输出以下属性:
{ "first_update_group_id": string, // 第一个更新组的 ID。你可以用它来例如为开发客户端深层链接构造更新 URL。 "updates_json": string // 更新组的字符串化 JSON 数组。`eas update --json` 的输出。 }
maestro
在构建上运行 Maestro 测试。有关详细信息和示例,请参阅 Maestro 任务文档。
重要 Maestro 测试处于 alpha。
jobs: my_job: type: maestro environment: production | preview | development # optional, defaults to preview image: string # optional. See https://docs.expo.dev/eas/workflows/syntax/#jobsjob_idruns_on for a list of available images. params: build_id: string # required flow_path: string | string[] # required shards: number # optional, defaults to 1 retries: number # optional, defaults to 1 record_screen: boolean # optional, defaults to false. If true, uploads a screen recording of the tests. include_tags: string | string[] # optional. Tags to include in the tests. Will be passed to Maestro as `--include-tags`. exclude_tags: string | string[] # optional. Tags to exclude from the tests. Will be passed to Maestro as `--exclude-tags`. maestro_version: string # optional. Version of Maestro to use for the tests. If not provided, the latest version will be used. android_system_image_package: string # optional. Android emulator system image package to use. device_identifier: string | { android?: string, ios?: string } # optional. Device identifier to use for the tests. output_format?: string # optional, defaults to junit. Maestro test report format. Will be passed to Maestro as `--format`. Can be `junit` or other supported formats.
maestro-cloud
在 Maestro Cloud 中的构建上运行 Maestro 测试。有关详细信息和示例,请参阅 Maestro Cloud 任务文档。
重要 在 Maestro Cloud 中运行测试需要 Maestro Cloud 账户和 Cloud Plan 订阅。前往 Maestro 文档 了解更多。
jobs: my_job: type: maestro-cloud environment: production | preview | development # optional, defaults to preview image: string # optional. See https://docs.expo.dev/eas/workflows/syntax/#jobsjob_idruns_on for a list of available images. params: build_id: string # required. ID of the build to test. maestro_project_id: string # required. Maestro Cloud project ID. Example: `proj_01jw6hxgmdffrbye9fqn0pyzm0`. flows: string # required. Path to the Maestro flow file or directory containing the flows to run. Corresponds to `--flows` param to `maestro cloud`. maestro_api_key: string # optional. The API key to use for the Maestro project. By default, `MAESTRO_CLOUD_API_KEY` environment variable will be used. Corresponds to `--api-key` param to `maestro cloud`. include_tags: string | string[] # optional. Tags to include in the tests. Will be passed to Maestro as `--include-tags`. exclude_tags: string | string[] # optional. Tags to exclude from the tests. Will be passed to Maestro as `--exclude-tags`. maestro_version: string # optional. Version of Maestro to use for the tests. If not provided, the latest version will be used. android_api_level: string # optional. Android API level to use for the tests. Will be passed to Maestro as `--android-api-level`. maestro_config: string # optional. Path to the Maestro `config.yaml` file to use for the tests. Will be passed to Maestro as `--config`. device_locale: string # optional. Device locale to use for the tests. Will be passed to Maestro as `--device-locale`. Run `maestro cloud --help` for a list of supported values. device_model: string # optional. Model of the device to use for the tests. Will be passed to Maestro as `--device-model`. Run `maestro cloud --help` for a list of supported values. device_os: string # optional. OS of the device to use for the tests. Will be passed to Maestro as `--device-os`. Run `maestro cloud --help` for a list of supported values. name: string # optional. Name for the Maestro Cloud upload. Corresponds to `--name` param to `maestro cloud`. branch: string # optional. Override for the branch the Maestro Cloud upload originated from. By default, if the workflow run has been triggered from GitHub, the branch of the workflow run will be used. Corresponds to `--branch` param to `maestro cloud`. async: boolean # optional. Run the Maestro Cloud tests asynchronously. If true, the status of the job will only denote whether the upload was successful, *not* whether the tests succeeded. Corresponds to `--async` param to `maestro cloud`.
slack
使用 webhook URL 向 Slack 频道发送消息。有关详细信息和示例,请参阅 Slack 任务文档。
jobs: my_job: type: slack params: webhook_url: string # required message: string # required if payload is not provided payload: object # required if message is not provided
github-comment
自动将你的工作流已完成的构建、更新和部署的综合报告发布到 GitHub 拉取请求或你提供的内容。有关详细信息和示例,请参阅 GitHub Comment 任务文档。
jobs: my_job: type: github-comment params: message: string # optional - custom message to include in the report build_ids: string[] # optional - specific build IDs to include, defaults to all related to the running workflow update_group_ids: string[] # optional - specific update group IDs to include, defaults to all related to the workflow deployment_ids: string[] # optional - specific deployment IDs to include, defaults to all related to the workflow # 不使用 message 以及构建、更新和部署表时,你也可以使用 `payload` 覆盖评论内容 custom_github_comment: type: github-comment params: payload: string # optional - 用于完全自定义评论的原始 markdown/HTML 内容
此任务输出以下属性:
{ "comment_url": string | undefined // 已发布的 GitHub 评论 URL }
require-approval
在继续工作流之前,需要用户批准。用户可以批准或拒绝,这分别对应任务成功或失败。有关详细信息和示例,请参阅 Require Approval 任务文档。
jobs: confirm: type: require-approval
doc
在工作流日志中显示一个 Markdown 部分。有关详细信息和示例,请参阅 Doc 任务文档。
jobs: next_steps: type: doc params: md: string
repack
基于现有构建重新打包应用。此任务会在不执行完整原生重建的情况下重新打包应用的元数据和 JavaScript bundle,这对于创建与特定指纹兼容的更快构建很有用。有关详细信息和示例,请参阅 Repack 任务文档。
jobs: next_steps: type: repack params: build_id: string # required profile: string # optional embed_bundle_assets: boolean # optional message: string # optional repack_version: string # optional
自定义作业
运行自定义代码,并且可以使用内置的 EAS 函数。不需要 type 字段。
jobs: my_job: steps: # ...
jobs.<job_id>.steps
一个作业包含一系列称为 steps 的任务。步骤可以运行命令。steps 只能在自定义作业和 build 作业中提供。
jobs: my_job: steps: - name: 我的第一步 run: echo "Hello World"
jobs.<job_id>.outputs
由作业定义的输出列表。这些输出对所有依赖于此作业的下游作业都可访问。要设置输出,请在作业步骤中使用 set-output 函数。
下游作业可以在 插值上下文 中使用以下表达式访问这些输出:
needs.<job_id>.outputs.<output_name>after.<job_id>.outputs.<output_name>
这里,<job_id> 指的是上游作业的标识符,<output_name> 指的是你想要访问的具体输出变量。
在下面的示例中,set-output 函数在 job_1 的 step_1 步骤中将名为 test 的输出设置为值 hello world。之后,在 job_2 中,它会在 step_2 中通过 needs.job_1.outputs.output_1 进行访问。
jobs: job_1: outputs: output_1: ${{ steps.step_1.outputs.test }} steps: - id: step_1 run: set-output test "hello world" job_2: needs: [job_1] steps: - id: step_2 run: echo ${{ needs.job_1.outputs.output_1 }}
jobs.<job_id>.image
指定要用于该作业的 VM 镜像。可用镜像请参见 基础设施。
jobs: my_job: image: auto | string # 可选,默认值为 'auto'
jobs.<job_id>.runs_on
指定将执行该作业的 worker。仅在自定义作业中可用。
jobs: my_job: runs_on: linux-medium | linux-large | linux-medium-nested-virtualization | linux-large-nested-virtualization | macos-medium | macos-large # 可选,默认值为 linux-medium
| Worker | vCPU | Memory (GiB RAM) | SSD (GiB) | 备注 |
|---|---|---|---|---|
| linux-medium | 4 | 16 | 14 | 默认 worker。 |
| linux-large | 8 | 32 | 28 | |
| linux-medium-nested-virtualization | 4 | 16 | 14 | 允许运行 Android 模拟器。 |
| linux-large-nested-virtualization | 4 | 32 | 28 | 允许运行 Android 模拟器。 |
| Worker | 效率核心 | 统一内存(GiB RAM) | SSD (GiB) | 备注 |
|---|---|---|---|---|
| macos-medium | 5 | 20 | 125 | 运行 iOS 任务,包括模拟器。 |
| macos-large | 10 | 40 | 125 | 运行 iOS 任务,包括模拟器。 |
注意: 对于 Android Emulator 任务,必须使用
linux-*-nested-virtualizationworker。对于 iOS 构建和 iOS Simulator 任务,必须使用macos-*worker。
jobs.<job_id>.steps.<step>.id
id 属性用于在作业中引用该步骤。适用于在下游作业中使用该步骤的输出。
jobs: my_job: outputs: test: ${{ steps.step_1.outputs.test }} # 引用 step_1 的输出 steps: - id: step_1 run: set-output test "hello world"
jobs.<job_id>.steps.<step>.name
步骤的人类可读名称,会显示在作业日志中。当步骤没有提供名称时,会使用 run 命令作为步骤名称。
jobs: my_job: steps: - name: 我的第一个步骤 run: echo "Hello World"
jobs.<job_id>.steps.<step>.run
要在该步骤中运行的 shell 命令。
jobs: my_job: steps: - run: echo "Hello World"
jobs.<job_id>.steps.<step>.shell
用于运行命令的 shell。默认为 bash。
jobs: my_job: steps: - run: echo "Hello World" shell: bash
jobs.<job_id>.steps.<step>.working_directory
运行命令的目录。当在步骤级别定义时,如果 jobs.<job_id>.defaults.run.working_directory 也有定义,它会覆盖作业中的该设置。
jobs: my_job: steps: - uses: eas/checkout - run: pwd # 打印:/home/expo/workingdir/build/my-app working_directory: ./my-app
jobs.<job_id>.steps.<step>.uses
EAS 提供了一组内置的可复用函数,你可以在工作流步骤中使用。uses 关键字用于指定要使用的函数。所有内置函数都以 eas/ 前缀开头。
jobs: my_job: steps: - uses: eas/checkout - uses: eas/install_node_modules - uses: eas/prebuild - name: 列出文件 run: ls -la
下面是你可以在工作流步骤中使用的内置函数列表。
eas/checkout
检出你的项目源文件。
jobs: my_job: steps: - uses: eas/checkout
在 GitHub 上查看 eas/checkout 函数的源代码。
eas/install_node_modules
使用根据你的项目检测到的包管理器(bun、npm、pnpm 或 Yarn)安装 node_modules。适用于 monorepo。
jobs: my_job: steps: - uses: eas/checkout - uses: eas/install_node_modules
在 GitHub 上查看 eas/install_node_modules 函数的源代码。
eas/download_build
下载指定构建的应用归档。默认情况下,下载的制品可以是 .apk、.aab、.ipa 或 .app 文件,也可以是包含其中一个或多个文件的 .tar.gz 归档。如果制品是 .tar.gz 归档,它将被解压,并返回第一个匹配指定扩展名的文件。如果构建没有生成任何应用归档,该步骤将失败。
jobs: my_job: steps: - uses: eas/download_build with: build_id: string # 必填。要下载的构建的 ID。 extensions: [apk, aab, ipa, app] # 可选。要查找的文件扩展名列表。默认为 ["apk", "aab", "ipa", "app"]。
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
build_id | string | Yes | – | 要下载的构建 ID。必须是有效的 UUID。 |
extensions | string[] | No | ["apk", "aab", "ipa", "app"] | 在下载的制品或归档中要查找的文件扩展名列表。 |
输出:
artifact_path:匹配的应用归档的绝对路径。该输出可作为工作流中其他步骤的输入。例如,用于进一步上传或处理该制品。
示例用法:
jobs: build_ios: type: build params: platform: ios profile: production my_job: needs: [build_ios] steps: - uses: eas/download_build id: download_build with: build_id: ${{ needs.build_ios.outputs.build_id }} - name: 打印制品路径 run: | echo "Artifact path: ${{ steps.download_build.outputs.artifact_path }}"
在 GitHub 上查看 eas/download_build 函数的源代码。
eas/prebuild
使用根据你的项目检测到的包管理器(bun、npm、pnpm 或 Yarn),并采用最适合你的构建类型和构建环境的命令运行 expo prebuild 命令。
jobs: my_job: steps: - uses: eas/checkout - uses: eas/install_node_modules - uses: eas/prebuild
jobs: my_job: steps: - uses: eas/checkout - uses: eas/install_node_modules - uses: eas/resolve_apple_team_id_from_credentials id: resolve_apple_team_id_from_credentials - uses: eas/prebuild with: clean: false apple_team_id: ${{ steps.resolve_apple_team_id_from_credentials.outputs.apple_team_id }}
| Property | Type | Description |
|---|---|---|
clean | boolean | 可选属性,定义在运行命令时该函数是否应使用 --clean 标志。默认为 false。 |
apple_team_id | string | 可选属性,定义在执行 prebuild 时应使用的 Apple 团队 ID。对于使用凭据的 iOS 构建,应指定该值。 |
在 GitHub 上查看 eas/prebuild 函数的源代码。
eas/restore_cache
从指定的 key 恢复之前保存的缓存。这对于通过复用已缓存的制品(如已编译的依赖项、构建工具或其他中间构建输出)来加速构建很有用。
jobs: my_job: steps: - uses: eas/checkout - uses: eas/install_node_modules - uses: eas/prebuild - uses: eas/restore_cache with: key: cache-${{ hashFiles('package-lock.json') }} restore_keys: cache path: /path/to/cache
jobs: my_job: steps: - uses: eas/checkout - uses: eas/install_node_modules - uses: eas/prebuild - uses: eas/restore_cache with: key: cache-${{ hashFiles('package-lock.json') }} path: /path/to/cache
| Property | Type | Required | Description |
|---|---|---|---|
key | string | Yes | 要恢复的缓存 key。你可以使用诸如 ${{ hashFiles('package-lock.json') }} 这样的表达式,根据文件哈希创建动态 key。 |
restore_keys | string | No | 当找不到精确匹配的 key 时使用的备用 key 或前缀。如果提供,缓存系统将查找任何以该前缀开头的缓存项。 |
path | string | Yes | 应恢复缓存的路径。该路径应与保存缓存时使用的路径一致。 |
在 GitHub 上查看 eas/restore_cache 函数的源代码。
eas/save_cache
将缓存保存到指定的 key 下。这使你可以持久化构建制品、已编译的依赖项或其他可在后续构建中复用的中间输出,以加快构建过程。
jobs: my_job: steps: - uses: eas/checkout - uses: eas/install_node_modules - uses: eas/prebuild - uses: eas/restore_cache with: key: cache-${{ hashFiles('package-lock.json') }} path: /path/to/cache - name: 构建 Android 应用 run: cd android && ./gradlew assembleRelease - uses: eas/save_cache with: key: cache-${{ hashFiles('package-lock.json') }} path: /path/to/cache
| Property | Type | Required | Description |
|---|---|---|---|
key | string | Yes | 将缓存保存到其下的缓存 key。你可以使用诸如 ${{ hashFiles('package-lock.json') }} 这样的表达式,根据文件哈希创建动态 key。该值应与恢复缓存时使用的 key 一致。 |
path | string | Yes | 应缓存的目录或文件路径。该值应与恢复缓存时使用的路径一致。 |
在 GitHub 上查看 eas/save_cache 函数的源代码。
eas/send_slack_message
向配置好的 Slack webhook URL 发送指定消息,然后它会将消息发布到相关的 Slack 频道。消息可以指定为纯文本或 Slack Block Kit 消息。
在这两种情况下,你都可以引用构建作业属性,并在消息中 使用其他步骤的输出 进行动态求值。例如,Build URL: https://expo.dev/builds/${{ needs.build_ios.outputs.build_id }}、Build finished with status: ${{ after.build_android.status }}。
必须指定 message 或 payload 之一,但不能同时指定两者。
jobs: my_job: steps: - uses: eas/send_slack_message with: message: 'This is a message to plain input URL' slack_hook_url: 'https://hooks.slack.com/services/[rest_of_hook_url]'
| Property | Type | Description |
|---|---|---|
message | string | 你想发送的消息文本。例如,'This is the content of the message'。注意: 必须提供 message 或 payload 之一,但不能同时提供两者。 |
payload | json | 你想发送的消息内容,使用 Slack Block Kit 布局定义。 注意: 必须提供 message 或 payload 之一,但不能同时提供两者。 |
slack_hook_url | string | 之前配置好的 Slack webhook URL,它会将你的消息发布到指定频道。你可以提供类似 slack_hook_url: 'https://hooks.slack.com/services/[rest_of_hook_url]' 这样的普通 URL,使用 EAS 环境变量 例如 slack_hook_url: ${{ env.ANOTHER_SLACK_HOOK_URL }},或者设置 SLACK_HOOK_URL 环境变量,它将作为默认的 webhook URL(在后一种情况下,不需要提供 slack_hook_url 属性)。 |
在 GitHub 上查看 eas/send_slack_message 函数的源代码。
eas/use_npm_token
为私有包配置 Node 包管理器(bun、npm、pnpm 或 Yarn),这些包可发布到 npm 或私有 registry。
在项目的 secrets 中设置 NPM_TOKEN,此函数将通过使用该 token 创建 .npmrc 来配置构建环境。
jobs: my_job: name: 安装私有 npm 模块 steps: - uses: eas/checkout - uses: eas/use_npm_token - name: 安装依赖 run: npm install # <---- 现在可以安装私有包了
在 GitHub 上查看 eas/use_npm_token 函数的源代码。
eas/download_artifact
根据制品的 ID 或名称从 EAS 下载一个制品。适用于将来自前面作业的制品发送到其他服务。
jobs: my_job: steps: - uses: eas/download_artifact with: name: string # 如果未提供 artifact_id,则为必填。要下载的制品名称。 artifact_id: string # 如果未提供 artifact_name,则为必填。要下载的制品 ID。
属性
| Property | Type | Required | Description |
|---|---|---|---|
name | string | No | 要下载的制品名称。如果未提供 artifact_id,则为必填。 |
artifact_id | string | No | 要下载的制品 ID。如果未提供 name,则为必填。 |
输出
| Property | Type | Description |
|---|---|---|
artifact_path | string | 已下载制品的路径。该输出可作为工作流中其他步骤的输入。例如,用于发送或处理该制品。 |
示例
jobs: maestro_tests: type: maestro params: build_id: '123-abc' flow_path: 'path/to/flow.yaml' my_job: needs: [maestro_tests] steps: - uses: eas/download_artifact id: download_artifact with: name: 'iOS Maestro Test Report (junit)' - name: 打印 Maestro 输出 run: echo ${{ steps.download_artifact.outputs.artifact_path }}
在 GitHub 上查看 eas/download_artifact 函数的源代码。
内置 shell 函数
EAS Workflows 提供了以下 shell 函数,你可以在工作流步骤中使用它来设置变量输出。
set-output
设置一个输出变量,可供工作流中的其他步骤或其他作业访问。
set-output <name> <value>
示例用法:与另一个步骤共享变量:
jobs: my_job: steps: - id: step_1 run: set-output variable_1 "变量 1" - id: step_2 run: echo ${{ steps.step_1.outputs.variable_1 }} # 打印:变量 1
示例用法:与另一个作业共享变量:
jobs: job_1: outputs: variable_1: ${{ steps.step_1.outputs.variable_1 }} steps: - id: step_1 run: set-output variable_1 "变量 1" job_2: needs: [job_1] steps: - run: echo ${{ needs.job_1.outputs.variable_1 }} # 打印:变量 1
set-env
设置一个环境变量,该变量可供同一作业中的后续步骤使用。在一个步骤的命令中使用 export 导出的环境变量不会自动暴露给其他步骤。要与其他步骤共享环境变量,请使用 set-env 可执行文件。
set-env <name> <value>
set-env 期望传入两个参数:环境变量的名称和值。例如,set-env NPM_TOKEN "abcdef" 会将 $NPM_TOKEN 变量的值 abcdef 暴露给后续步骤。
注意: 使用
set-env共享的变量不会自动在本地导出。如果你想在当前步骤中使用该变量,需要自行调用export。
示例用法:与另一个步骤共享环境变量:
jobs: my_job: steps: - name: Set environment variables run: | # 仅使用 export 只会让它在当前步骤中可用 export LOCAL_VAR="仅在此步骤中" # 使用 set-env 会让它在后续步骤中可用 set-env SHARED_VAR "在后续步骤中可用" # SHARED_VAR 在当前步骤的环境中仍不可用 echo "LOCAL_VAR: $LOCAL_VAR" # 打印:仅在此步骤中 echo "SHARED_VAR: $SHARED_VAR" # 打印:(空) - name: Use shared variable run: | # SHARED_VAR 现在可用 # @info # echo "SHARED_VAR: $SHARED_VAR" # 打印:在后续步骤中可用 # @end #
在作业之间共享环境变量
set-env 函数只会在同一作业内与其他步骤共享环境变量。要在不同作业之间共享值,请使用作业的 outputs 和 set-output,并通过接收作业上的 env 属性传递它们:
jobs: job_1: outputs: my_value: ${{ steps.step_1.outputs.my_value }} steps: - id: step_1 run: set-output my_value "来自 job_1 的值" job_2: needs: [job_1] env: MY_VALUE: ${{ needs.job_1.outputs.my_value }} steps: - run: echo "MY_VALUE: $MY_VALUE" # 打印:来自 job_1 的值