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

EAS 工作流的 PostHog 秘诀

从在 PostHog 标记你的第一次部署开始,到使用 EAS 工作流进行分阶段发布、自动终止开关和审批控制的发布,一条完整的指导路径。


EAS 工作流 可以在你的 CI 管道中以步骤的形式运行 PostHog 操作。下面的每个示例都是一个完整的工作流,你可以直接复制使用,它们一起构建了一个完整的渐进式交付管道:

一个紧凑的更多秘诀列表覆盖更狭窄的需求。有关每个函数接受的每个输入,请参阅EAS 工作流语法参考。

🌐 A compact list of more recipes covers narrower needs. For every input each function accepts, see the EAS Workflows syntax reference.

开始使用

🌐 Get started

一条命令就能搭建这些秘诀所需的一切。在你的项目目录下运行它:

🌐 One command sets up everything these recipes need. Run it from your project directory:

Terminal
- eas integrations:posthog:connect

它将 PostHog 项目与你的 Expo 项目关联,并保存这些函数读取的凭据作为 EAS 环境变量。使用 PostHog 指南会详细介绍完整的设置过程。

🌐 It links a PostHog project to your Expo project and saves the credentials these functions read as EAS environment variables. The Using PostHog guide walks through the full setup.

当命令要求提供个人 API 密钥时,使用“Source map upload”预设并加上 feature_flag:read、feature_flag:write、query:read 和 annotation:write 权限来创建。这个密钥可以涵盖本页上的所有用法。如果你之前用的是权限更窄的密钥,创建一个新的,并将其设置为具有 Sensitive 可见性的 POSTHOG_CLI_API_KEY 环境变量。

🌐 When the command asks for a personal API key, create it with the "Source map upload" preset plus the feature_flag:read, feature_flag:write, query:read, and annotation:write scopes. That one key covers every recipe on this page. If you connected earlier with a narrower key, create a new one and set it as the POSTHOG_CLI_API_KEY environment variable with the Sensitive visibility.

在你的 PostHog 时间线上标记一次部署

🌐 Mark a deploy on your PostHog timeline

每次发布更新时发送一个 PostHog 事件。每次部署都会出现在你的 PostHog 数据中,这样你就可以查看某个指标的变化是否与发布同步。

🌐 Send a PostHog event every time you publish an update. Each deploy then shows up in your PostHog data, so you can check whether a change in a metric lines up with a release.

.eas/workflows/mark-deploy.yml
name: Publish update and mark it in PostHog on: push: branches: ['main'] jobs: publish: type: update params: branch: main mark_deploy: needs: [publish] steps: - uses: eas/posthog_capture_event with: event: ota_update_published properties: eas/account: ${{ account.name }} eas/project_id: ${{ app.id }} eas/workflow_id: ${{ workflow.id }} eas/update_id: ${{ needs.publish.outputs.first_update_group_id }} eas/runtime_version: ${{ fromJSON(needs.publish.outputs.updates_json || '[]')[0].runtimeVersion }} branch: main

工作原理

🌐 How it works

  1. update 任务会向 main 分支发布 EAS 更新。
  2. eas/posthog_capture_event 跟着它运行,并用 标准 EAS 属性 记录部署。eas/account、eas/project_id 和 eas/workflow_id 来自始终可用的工作流上下文;eas/update_id 和 eas/runtime_version 来自更新任务的 输出。使用 fingerprint 运行时版本策略 时,运行时版本会随着你的原生运行时变化而变化,基于你的项目 指纹。
  3. 因为没有设置 distinct_id,这个事件是匿名的,并不会创建个人档案。

标注一个版本

🌐 Annotate a release

在发布更新时创建一个 PostHog 注释。注释会以标记的形式出现在项目中的每个图表上,这样你就可以直接在受影响的图表上看到每次发布。

🌐 Create a PostHog annotation when you publish an update. Annotations appear as markers on every chart in the project, so you can see each release directly on the graphs it affects.

.eas/workflows/annotate-release.yml
name: Annotate release in PostHog on: push: branches: ['main'] jobs: publish: type: update params: branch: main annotate: needs: [publish] steps: - uses: eas/posthog_annotation with: content: Published update for runtime ${{ fromJSON(needs.publish.outputs.updates_json || '[]')[0].runtimeVersion }} to main

工作原理

🌐 How it works

  1. update 任务发布了更新。
  2. eas/posthog_annotation 将注释固定在当前时间,内容中的运行时版本用来标识发布版本。

上传源映射以追踪错误

🌐 Upload source maps for error tracking

上传你的源映射,这样错误追踪就可以将崩溃符号化回你的原始代码。它们如何被上传取决于生成包的预打包任务。两种方式都需要按照 使用 PostHog 指南进行 PostHog 设置。

🌐 Upload your source maps so error tracking can symbolicate crashes back to your original code. How they get uploaded depends on the pre-packaged job that produced the bundle. Both paths need the PostHog setup from the Using PostHog guide.

一个 build 会自己上传源映射。posthog-react-native/expo 配置插件会在本地构建时上传它们,所以这个任务不需要额外操作:

🌐 A build uploads source maps on its own. The posthog-react-native/expo config plugin uploads them during the native build, so the job needs nothing extra:

.eas/workflows/build-production.yml
name: Build for production on: push: branches: ['main'] jobs: build: type: build params: platform: ios profile: production

一次更新只包含 JavaScript,所以你在发布后上传它的源映射。update 任务不能运行额外步骤,并且源映射必须保存在上传它们的任务的磁盘上。因此,可以在自定义任务中使用 eas update 为一个平台发布,然后在那里添加上传步骤:

🌐 An update ships JavaScript only, so you upload its source maps after publishing. The update job can't run an extra step, and the source maps have to be on disk in the job that uploads them. So publish with eas update for one platform in a custom job and add the upload step there:

.eas/workflows/update-with-sourcemaps.yml
name: Publish update with source maps on: push: branches: ['main'] jobs: publish_update: steps: - uses: eas/checkout - uses: eas/install_node_modules - run: npx eas-cli@latest update --branch main --platform ios --auto --non-interactive - uses: eas/posthog_upload_sourcemaps with: directory: dist

工作原理

🌐 How it works

  1. eas update --platform ios 发布更新并将导出内容(包括源映射)放在 dist 目录中。每个任务只导出一个原生平台:完整导出还会包含Webpack,但 PostHog 的 Hermes 上传会拒绝这个。
  2. eas/posthog_upload_sourcemaps 会把那些地图上传到 PostHog 错误跟踪,这样更新的堆栈追踪就可以回溯到你的原始代码。它使用 PostHog Metro 配置,为每个包提供与其源地图匹配的 chunk ID。查看 错误跟踪 了解符号化的工作原理。

在功能开关后发布一个功能

🌐 Release a feature behind a flag

把功能的发布状态保存在你仓库里的一个文件中,让工作流把它应用到 PostHog。发布一个功能或扩大它的发布范围就变成一个编辑这个文件的拉取请求。

🌐 Keep a feature's rollout state in a file in your repo and let the workflow apply it to PostHog. Shipping a feature or widening its rollout becomes a pull request that edits one file.

.eas/feature-rollout.json
{ "flag": "new-checkout", "rollout_percentage": 10 }
.eas/workflows/feature-release.yml
name: Apply the feature rollout from the repo on: push: branches: ['main'] paths: ['.eas/feature-rollout.json'] jobs: publish: type: update params: branch: main read_rollout: outputs: flag: ${{ steps.rollout.outputs.flag }} percent: ${{ steps.rollout.outputs.percent }} steps: - uses: eas/checkout - id: rollout run: | set-output flag "$(node -p "require('./.eas/feature-rollout.json').flag")" set-output percent "$(node -p "require('./.eas/feature-rollout.json').rollout_percentage")" apply_rollout: needs: [publish, read_rollout] steps: - uses: eas/posthog_flag_rollout with: flag: ${{ needs.read_rollout.outputs.flag }} active: true rollout_percentage: ${{ needs.read_rollout.outputs.percent }}

工作原理

🌐 How it works

  1. paths 过滤器只有在 .eas/feature-rollout.json 发生变化时才会运行这个工作流,所以文件就是你定义滚动发布状态的地方。
  2. read_rollout 使用 set-output 读取文件,并通过作业的 outputs 提供这些值。
  3. eas/posthog_flag_rollout 会在两个依赖都完成后应用标志状态,所以标志只有在读取它的代码运行时才会翻转。

在错误率上推进或回退

🌐 Roll out or roll back on your error rate

先只对一小部分用户发布,观察错误率,让工作流程自己决定。当错误率保持低时,就扩大标记到所有人。当错误率不低时,就关闭标记。无论哪种情况,中间都不用有人盯着仪表盘。

🌐 Release to a small percentage of users, watch the error rate, and let the workflow decide. When errors stay low, it widens the flag to everyone. When they don't, it turns the flag off. Either way, nobody has to watch a dashboard in between.

.eas/workflows/canary-rollout.yml
name: Canary rollout that rolls forward or back on: push: branches: ['main'] jobs: publish: type: update params: branch: main canary: needs: [publish] steps: - uses: eas/posthog_flag_rollout with: flag: new-checkout active: true rollout_percentage: 25 error_gate: needs: [canary] steps: - uses: eas/posthog_wait_for_metric with: query: SELECT count() FROM events WHERE event = '$exception' AND timestamp > now() - INTERVAL 30 MINUTE operator: lte threshold: 5 interval_seconds: 60 timeout_seconds: 1800 full_rollout: needs: [error_gate] steps: - uses: eas/posthog_flag_rollout with: flag: new-checkout rollout_percentage: 100 roll_back: after: [error_gate] if: ${{ failure() }} steps: - uses: eas/posthog_flag_rollout with: flag: new-checkout active: false

工作原理

🌐 How it works

  1. [update](/eas/workflows/pre-packaged-jobs#update) 任务负责部署代码,然后 eas/posthog_flag_rollout 向 25% 的用户开放访问。
  2. [eas/posthog_wait_for_metric](/eas/workflows/syntax/#easposthog_wait_for_metric) 运行一个 HogQL 查询,并等待过去 30 分钟内的异常次数降到 5 次或以下。一旦关卡通过,full_rollout 就会将标记扩展到 100%。如果错误的发布导致次数一直居高不下,关卡会超时并失败,full_rollout 永远不会运行。
  3. 在失败时,roll_back 会关闭标志。它使用 after 和 if: ${{ failure() }},因为 needs 依赖在这里不起作用。当 needs 依赖失败时,该任务会在评估其 if 条件之前被跳过。failure() 反映整个工作流程运行情况,所以保持这个工作流程专注于发布及其门控。

推出 EAS 更新通道,失败则回滚

🌐 Roll out an EAS Update channel, or revert on failure

上面的推送是通过 PostHog 功能标志来控制暴露。如果你改用 EAS 更新渠道百分比 来推送,同样的门控会控制 eas channel:rollout:发布更新,让一部分用户使用它,观察错误率,然后决定是向所有人扩展还是回滚。它涉及 EAS 的部分比这里任何其他方案都多:更新任务、渠道推送、指标门控,以及结果事件。

🌐 The rollout above controls exposure with a PostHog feature flag. If you roll out with EAS Update channel percentages instead, the same gate drives eas channel:rollout: publish an update, send a fraction of users to it, watch the error rate, then widen the rollout to everyone or revert it. It touches more of EAS than any other recipe here: the update job, channel rollouts, the metric gate, and an outcome event.

.eas/workflows/channel-rollout.yml
name: Channel rollout that widens or reverts on: push: branches: ['main'] jobs: publish: type: update params: branch: rollout start_rollout: needs: [publish] steps: - run: npx eas-cli@latest channel:rollout production --action create --branch rollout --percent 10 --runtime-version 1.0.0 --non-interactive error_gate: needs: [start_rollout] steps: - id: gate uses: eas/posthog_wait_for_metric with: query: SELECT count() FROM events WHERE event = '$exception' AND timestamp > now() - INTERVAL 15 MINUTE operator: lt threshold: 10 interval_seconds: 60 timeout_seconds: 900 - uses: eas/posthog_capture_event with: event: channel_rollout_cleared properties: eas/account: ${{ account.name }} eas/project_id: ${{ app.id }} eas/workflow_id: ${{ workflow.id }} error_count: ${{ steps.gate.outputs.value }} widen: needs: [error_gate] steps: - run: npx eas-cli@latest channel:rollout production --action end --outcome republish-and-revert --non-interactive revert: after: [error_gate] if: ${{ failure() }} steps: - run: npx eas-cli@latest channel:rollout production --action end --outcome revert --non-interactive

工作原理

🌐 How it works

  1. update 任务会发布到 rollout 分支,然后 eas channel:rollout 会在 production 通道启动一个推出,把 10% 的用户送到新更新。--runtime-version 的值必须和发布的更新的运行时版本匹配。
  2. eas/posthog_wait_for_metric 会一直保持,直到过去 15 分钟内的异常次数保持在 10 以下,然后通过步骤的 value 输出记录通过门控的次数。
  3. 当关卡通过后,widen 用 --outcome republish-and-revert 结束了发布,这会把新的更新推送给所有人。
  4. 当门控失败时,revert 会用 --outcome revert 结束发布,将用户送回到上一个更新。它使用与 flag rollback 相同的 after 加 if: ${{ failure() }} 模式。

在人工批准后将标志推向全面发布

🌐 Take a flag to full rollout with human approval

在 EAS 仪表板中暂停工作流以获取明确批准,然后再让标志达到 100%。对你不想全自动执行的发布使用这个方法。

🌐 Pause the workflow for an explicit approval in the EAS dashboard before a flag goes to 100%. Use this for rollouts you don't want to automate end to end.

.eas/workflows/approved-ga.yml
name: Take a feature to GA with human approval jobs: approve: name: Approve new-checkout GA? type: require-approval go_full: needs: [approve] steps: - uses: eas/posthog_flag_rollout with: flag: new-checkout active: true rollout_percentage: 100 bookkeeping: needs: [go_full] steps: - uses: eas/posthog_capture_event with: event: feature_went_ga properties: eas/account: ${{ account.name }} eas/project_id: ${{ app.id }} eas/workflow_id: ${{ workflow.id }} flag: new-checkout

工作原理

🌐 How it works

  1. require-approval 任务会暂停工作流,直到有人在 EAS 仪表板上批准或拒绝它。
  2. 如果批准,eas/posthog_flag_rollout 会将标志推广到 100%。如果被拒绝,作业会失败并且会跳过 go_full。
  3. 后续事件会记录这个标志何时完成全面推出。

用紧急开关关闭某个功能

🌐 Turn a feature off with a kill switch

用一个命令就可以为所有人关闭一个功能。这个工作流没有 on 触发器,所以只有在你启动它时才会运行,比如在发生事故时。

🌐 Turn a feature off for everyone with a single command. This workflow has no on trigger, so it runs only when you start it, such as during an incident.

.eas/workflows/kill-switch.yml
name: Disable new-checkout now jobs: disable_flag: steps: - uses: eas/posthog_flag_rollout with: flag: new-checkout active: false audit_trail: needs: [disable_flag] steps: - uses: eas/posthog_capture_event with: event: kill_switch_pulled properties: eas/account: ${{ account.name }} eas/project_id: ${{ app.id }} eas/workflow_id: ${{ workflow.id }} flag: new-checkout

工作原理

🌐 How it works

  1. 运行方式:

    Terminal
    - eas workflow:run kill-switch.yml
  2. eas/posthog_flag_rollout 关闭了标志,后续事件记录了它发生了。

在错误激增时自动关闭一个功能

🌐 Turn a feature off automatically on an error spike

这是前一个秘诀里的杀手开关,接到一个错误门上,所以当部署后错误率飙升时,它会自己关闭这个功能。

🌐 This is the kill switch from the previous recipe wired to an error gate, so it turns the feature off on its own when the error rate spikes after a deploy.

.eas/workflows/auto-kill-switch.yml
name: Turn off new-checkout automatically on an error spike on: push: branches: ['main'] jobs: publish: type: update params: branch: main error_gate: needs: [publish] steps: - uses: eas/posthog_wait_for_metric with: query: SELECT count() FROM events WHERE event = '$exception' AND timestamp > now() - INTERVAL 10 MINUTE operator: lt threshold: 20 interval_seconds: 60 timeout_seconds: 600 auto_kill_switch: after: [error_gate] if: ${{ failure() }} steps: - uses: eas/posthog_flag_rollout with: flag: new-checkout active: false - uses: eas/posthog_capture_event with: event: auto_kill_switch_pulled properties: eas/account: ${{ account.name }} eas/project_id: ${{ app.id }} eas/workflow_id: ${{ workflow.id }} flag: new-checkout

工作原理

🌐 How it works

  1. update 任务会发布更新,而 eas/posthog_wait_for_metric 会等到过去 10 分钟的异常次数低于 20。如果一次错误的更新导致次数持续偏高,闸门就会超时并失败。
  2. auto_kill_switch 任务使用与 flag rollback 相同的 after 加 if: ${{ failure() }} 模式。
  3. eas/posthog_flag_rollout 关闭了标志,和手动杀开关的操作一样,并记录了它是自动触发的。

一旦用户采纳,就发布公告

🌐 Announce a release once users adopt it

等足够多的用户使用新更新后再在 Slack 上发消息。这个工作流会等真正有人采用之后再通知,而不是部署一完成就公告。

🌐 Post a Slack message once enough users are on the new update. The workflow waits for real adoption instead of announcing as soon as the deploy finishes.

.eas/workflows/announce-on-adoption.yml
name: Announce release once adopted on: push: branches: ['main'] jobs: publish: type: update params: branch: main adoption_gate: needs: [publish] steps: - uses: eas/posthog_wait_for_metric with: query: SELECT count(DISTINCT distinct_id) FROM events WHERE timestamp > now() - INTERVAL 1 HOUR operator: gte threshold: 50 interval_seconds: 120 timeout_seconds: 3600 announce: needs: [adoption_gate] type: slack environment: production params: webhook_url: ${{ env.SLACK_WEBHOOK_URL }} message: The latest update is live and 50 or more users are on it.

工作原理

🌐 How it works

  1. update 任务发布了更新。
  2. eas/posthog_wait_for_metric 会等到最近一小时至少有 50 个不同的用户发送过事件。
  3. [slack](/eas/workflows/pre-packaged-jobs#slack) 作业在门禁放行时会发布新的版本。在 EAS 上将 SLACK_WEBHOOK_URL 设置为 环境变量`。

更多秘诀

🌐 More recipes

为更有限需求准备的简短秘诀。

🌐 Shorter recipes for narrower needs.

等一个特定的事件

🌐 Wait for a specific event

暂停工作流,直到特定事件到来,比如部署后冒烟测试报告成功,而不是依赖一个综合指标。

🌐 Hold the workflow until a specific event arrives, such as a post-deploy smoke test reporting success, instead of gating on an aggregate metric.

.eas/workflows/wait-for-smoke-test.yml
name: Wait for smoke test to pass jobs: wait_for_smoke_test: steps: - uses: eas/posthog_wait_for_query with: query: SELECT count() > 0 FROM events WHERE event = 'smoke_test_passed' AND timestamp > now() - INTERVAL 30 MINUTE interval_seconds: 15 timeout_seconds: 600

eas/posthog_wait_for_query 会在查询返回 true 时清除。30 分钟的时间窗口可以防止旧的烟雾测试事件立即清除门控。

检查你晚上的错误预算

🌐 Check your nightly error budget

按计划运行一个门禁,而不是在部署后运行,作为独立的健康检查。

🌐 Run a gate on a schedule instead of after a deploy, as a standalone health check.

.eas/workflows/error-budget.yml
name: Nightly error-budget check on: schedule: - cron: '0 6 * * *' jobs: assert_error_budget: steps: - uses: eas/posthog_wait_for_metric with: query: SELECT count() FROM events WHERE event = '$exception' AND timestamp > now() - INTERVAL 24 HOUR operator: lt threshold: 100 interval_seconds: 30 timeout_seconds: 60

on.schedule.cron 触发器会独立于任何部署运行,因此它更像是一种持续的健康检查,而不是对特定发布的门控。

🌐 The on.schedule.cron trigger runs this independently of any deploy, so it works as a standing health check rather than a gate on a specific rollout.

标记一个商店提交

🌐 Mark a store submission

eas/posthog_capture_event 对于原生版本和更新的工作方式是一样的。

.eas/workflows/store-release.yml
name: Build, submit to the store, mark it in PostHog jobs: build: type: build params: platform: ios profile: production submit: needs: [build] type: submit params: build_id: ${{ needs.build.outputs.build_id }} profile: production mark_release: needs: [submit, build] steps: - uses: eas/posthog_capture_event with: event: store_build_submitted properties: eas/account: ${{ account.name }} eas/project_id: ${{ app.id }} eas/workflow_id: ${{ workflow.id }} eas/build_id: ${{ needs.build.outputs.build_id }} eas/channel: ${{ needs.build.outputs.channel }} platform: ios profile: production

重要说明

🌐 Important notes

  • 凭证来自 connect 命令。 每个函数默认使用 eas integrations:posthog:connect 设置的环境变量,当你需要覆盖它们时,每个函数都可以接受 api_key 输入。要自己设置它们,可以将这些作为 EAS 环境变量 添加:EXPO_PUBLIC_POSTHOG_API_KEY 用于 eas/posthog_capture_event,以及 POSTHOG_CLI_API_KEY 和 POSTHOG_CLI_PROJECT_ID 用于其他所有函数。语法参考 列出了每个函数所需的作用域。
  • 一个超时的门会导致步骤失败。 eas/posthog_wait_for_metric 和 eas/posthog_wait_for_query 没有 ignore_error 输入,所以一个永远不通过的门会停止发布,而不是让它继续。
  • 只要条件满足,闸门就会通过。 检查错误计数较低的闸门可以在第一次检查时就通过,包括在部署之后、用户还没有使用新更新之前。当你希望错误有机会先被发现时,可以将其与采用闸门结合使用,比如在用户采用后再发布中的那种。
  • 将查询范围限制到当前运行。 事件和指标查询会返回历史数据。添加 timestamp > now() - INTERVAL ... 过滤器,或当前运行独有的属性,这样旧事件就不会立即清除一个门控。设置 发布标记 会将 eas/update_id、eas/channel 和 eas/runtime_version 附加到每个客户端事件上,这样你就可以在 properties['eas/update_id'] 上过滤门控,将其范围限定到具体发布。