尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
EAS Workflows 实战指南:从 0 到 1 搭建 Expo 应用商店发布 CI/CD 流水线
EAS Workflows 实战指南从 0 到 1 搭建 Expo 应用商店发布 CI/CD 流水线【免费下载链接】skillsA collection of AI agent skills for working with Expo projects and Expo Application Services项目地址: https://gitcode.com/GitHub_Trending/skills9/skills如果每次发版你还靠在本地手敲eas build和eas submit这套流程慢、难复现、也很难交接给同事。本文以 EAS Workflows 为主线从 0 到 1 带出一套可版本化、可复现的 Expo 应用商店发布 CI/CD 流水线先跑通推送即构建再叠加 PR 预览与双平台生产发布最后用服务端校验和凭据托管收尾读完后你可以独立写出并验证一条面向 App Store / Google Play 的发布流水线。EAS Workflows 能自动化什么、不能自动化什么先定边界写 YAML 之前先把三条边界钉死比背字段省心得多。主技能文件把它的定位说得很干脆EAS Workflows 是 the build → submit → update pipeline 的自动化层见 eas-app-stores/SKILL.md。它是编排层不是新的构建系统。type: build作业仍然调用 EAS Buildtype: submit仍然调用 EAS Submitprofile字段指向eas.json里已存在的构建/提交配置。工作流只负责三件事顺序、触发条件、并行关系。它不包办所有场景。workflows.md 开头就划好了分工需要写、改或校验超出示例范围的 workflow YAML 时改用eas-workflows技能网站与 API 路由的部署工作流type: deploy归eas-hosting技能管。成功只到 EAS 服务为止。技能原文有一句值得逐字记住A successful EAS build or a queued submission does not establish Apple acceptance, tester access, or an App Store release. EAS 构建成功或提交已排队都不代表 Apple 已接受、测试者可获得访问、或 App Store 发布生效。这句话写 YAML 时同样成立submit作业变绿只说明上传被排队了。这一点后文别把作业成功当已上架会展开。计费与账号前提触发前先看一眼EAS Workflows 跑在 Expo Application Services 上属于计费产品每个作业消耗所属计划的 build/compute minutes执行构建或提交的作业还需要付费的 Apple Developer 与 Google Play 开发者账号触发前建议先确认所请求服务的免费额度与付费限制。维护这个仓库的同学还会注意到scripts/check-skill-limits.ts 会在 CI 中强制校验所有eas-*技能在 H1 之后紧接成本声明——所以每个eas-开头的技能正文都以成本提示开场。这是仓库约束不是写作风格。另外工作流跑在 EAS 服务端读不到你本地的隐式状态。按 expo-overview 的共享约定两个连接状态必须提前就位登录态用eas whoami检查、eas login建立项目已链接应用配置中存在extra.eas.projectId缺失时用eas init创建。动笔前固定的格式底线以下是纯机械性约束违反了连语法校验都过不去快速过一遍即可。文件位置与体积工作流放在.eas/workflows/*.yml或.yaml每个文件不得超过 16 KiB。仓库示例都遵循这一约定例如 ios-app-store.md 与 app-store-metadata.md 中的片段均标注为.eas/workflows/release.yml。顶层键一共五个顶层键作用是否必需name工作流展示名称示例均提供on触发条件至少一个jobs作业定义必需defaults所有作业共享的默认值可选concurrency控制并行运行可选动态值统一用${{ }}语法schema 定义了github.*、inputs.*、needs.*、jobs.*、steps.*、workflow.*六族上下文。本文四个发布场景实际只用到其中三种${{ github.event.pull_request.number }}、needs.job、needs.job.outputs.*。eas-workflows技能反复提醒每个分区的完整规范应以 workflow schema 为准别凭记忆填字段。第一步先跑通推送即构建别用复杂场景开局。最简单的起点是推送到指定分支就构建# .eas/workflows/build.yml name: Build on: push: branches: - main - release/* jobs: build: type: build params: platform: all profile: production出处见 workflows.md。这里有两个新值platform: all—— 一个作业覆盖双平台代价是失去按平台单独重试、单独诊断的粒度生产发布再讲拆分写法。release/*通配—— 所有发布分支共享同一条流水线不必逐个枚举。这个示例刻意不带submit典型用途是每次合并主干都产出一个可安装验证的产物把提交动作留给人工决策或后面的 tag 流水线。跑通这一步后先验证两件事eas.json里的productionprofile 能被作业解析、产物确实能下载。这两点通过后再往复杂场景走。第二步加一条 PR 预览分支——为什么是 type: update同样是PR 预览Web 与原生是两条完全不同的路别混用网站与 API 路由走type: deploy搭配prod: false目标是 EAS HostingCloudflare Workers见 eas-hosting/SKILL.md原生 App 走type: updateOTA 发布 JS bundle 与资源不产生新的原生二进制。PR 预览示例# .eas/workflows/pr-preview.yml name: PR Preview on: pull_request: types: [opened, synchronize] jobs: publish: type: update params: branch: pr-${{ github.event.pull_request.number }} message: PR #${{ github.event.pull_request.number }}为什么 update 就够用PR 预览改的通常是 JS 与样式正好落在 OTA 能力范围内。eas-update 技能给出的模型是——build是装到设备上的原生 Appupdate是面向某平台与 runtime version 的 JS/资源包branch是有序的更新流channel是构建时嵌入的部署目标。一旦改动涉及原生代码或原生配置OTA 就兜不住了必须重新构建。这也解释了为什么下节的生产发布用buildsubmit而不是update。一行值得抄的写法branch: pr-${{ github.event.pull_request.number }}让每个 PR 拥有独立更新分支、互不覆盖message里带上 PR 号之后在 EAS 面板排查这个预览包来自哪个 PR时能直接对上。这里有个容易踩的坑预览构建的 channel 必须指向这条分支更新才能下发。eas-update 的判断条件是平台匹配、runtime version 匹配、且已安装构建的 channel 指向包含该更新的 branch三者同时成立。channel 与 branch 虽然常常同名但在服务端是两个独立对象——eas channel:edit改的是 channel 的服务端分支映射不会改变已安装构建里嵌入的 channel。所以 PR 预览方案要单独规划预览构建的 channel/分支映射策略别指望pr-123这个分支名自动生效。第三步生产发布——双平台并行构建与提交结构最完整的场景Complete release workflow for both platforms# .eas/workflows/release.yml name: Release on: push: tags: [v*] jobs: build-ios: type: build params: platform: ios profile: production build-android: type: build params: platform: android profile: production submit-ios: type: submit needs: [build-ios] params: platform: ios profile: production submit-android: type: submit needs: [build-android] params: platform: android profile: production依赖图怎么读四个作业构成两条互不相交的链build-ios → submit-ios、build-android → submit-android。链之间没有needs关系所以 iOS 与 Android 并行推进每个submit只等自己的build。这比先构建两个平台、再统一提交的串行写法快也避免单平台失败干扰另一条链的诊断。profile 是引用不是定义profile: production必须在项目eas.json中存在对应条目否则作业启动时才失败。注意一个语义上的惊喜build.production与submit.production是两个不同分区下的同名 profile。示例不区分分区地写profile是因为type已经决定了查哪张表——type: build读buildtype: submit读submit。主技能文件里的完整示例{ build: { production: { autoIncrement: true, ios: { resourceClass: m-medium } } }, submit: { production: { ios: { appleId: youremail.com, ascAppId: 1234567890 }, android: { serviceAccountKeyPath: ./google-service-account.json, track: internal } } } }关键改进显式传 build_id上面示例的 submit 作业只传了platform和profile默认会去选最新构建来提交。在每天都触发构建的项目里最新构建很可能不是你刚构建出来的那一个。ios-app-store.md 给了更严谨的写法submit: type: submit needs: [build] params: build_id: ${{ needs.build.outputs.build_id }} profile: productiontestflight.md 的理由很直接For separate jobs, pass the explicit build ID rather than selecting whichever unrelated build is newest.拆分的作业之间要显式传构建 ID而不是选最新的那个无关构建。用needs.build.outputs.build_id把两者绑定可以防止把错误二进制推到商店发布流程有可审计性要求的话建议直接把build_id写进 submit 作业。触发方式用 tag 驱动版本化发布on.push.tags: [v*]让流水线只在打标签时运行发布点与代码版本一一对应出问题时能直接 checkout 对应 commit 复查。参考文档 Tips 建议两种触发搭配tag 做版本化发布workflow_dispatch处理手动生产发布。第四步按需触发——条件作业前两条流水线都是无条件触发README 改一个字也消耗一次构建额度。加一层探测来过滤# .eas/workflows/conditional-release.yml name: Conditional Release on: push: branches: [main] jobs: check-changes: type: run params: command: | if git diff --name-only HEAD~1 | grep -q ^src/; then echo has_changestrue $GITHUB_OUTPUT fi build: type: build needs: [check-changes] if: needs.check-changes.outputs.has_changes true params: platform: all profile: production三段结构一目了然type: run作业执行 shell 命令做探测needs: [check-changes]声明依赖if决定是否真正开工。这是只在源码目录变化时才发布的标准写法——文档、README、CI 配置的改动不会白白消耗构建额度。两个细节if的比较用字符串true而非布尔true与其上游$GITHUB_OUTPUT的文本性质一致eas-workflows 的生成清单要求确保if条件符合 schema 的长度约束说明该字段并非无限制的自由文本。⚠️ 这里有一处需要自行验证的细节check-changes用 GitHub Actions 约定$GITHUB_OUTPUT写出结果下游读的是 EAS 表达式上下文needs.check-changes.outputs.has_changes。这两者是否在同一次运行中直接打通取决于run作业类型对输出的实际处理方式——仓库文档没有进一步说明而eas-workflows反复强调不要依赖记忆中的字段值先取 schema 再写。建议照搬进生产前按这个顺序做取 schema确认run作业的输出声明方式与needs.*.outputs的可用性用下一节的workflow:validate做服务端校验在一条非生产分支上跑一次确认has_changes取值符合预期再接入main。写完必做的一步服务端 workflow:validate 校验四条 YAML 写完必须落到一个能给出确定性结论的动作上。eas-workflows技能给的命令npx -y eas-clilatest workflow:validate .eas/workflows/workflow.yml --non-interactive围绕这条命令有几条约束值得展开逐个文件运行每个被修改的工作流都单独执行一次校验需要登录态与已链接项目它不是纯离线工具会检查 profile 引用与纯 schema 校验不同它还会把profile与项目的eas.json对照——正好能拦下profile: production写错或不存在这类错误会做服务端校验在这里修复成本远低于上线后发现成功标志是固定文案命令打印Workflow configuration YAML is valid.才算通过反复修复并重跑直到出现该输出明确禁止替代文档直接写明 Do not replace this command with a local YAML or JSON Schema validator.为什么强调取实时 schema同样的谨慎也体现在资料获取上。写之前eas-workflows技能要求先拉取三份资源JSON Schema—— 文档用大写强调 It is NECESSARY to fetch this schema。它是作业类型、参数、触发类型、runner 类型的权威来源最终校验仍以 EAS CLI 为准语法文档—— YAML 概览、示例、表达式与上下文预打包作业文档—— 各 job type 的参数与输出。为避免 Agent 反复抓取被限流技能自带一个缓存抓取脚本 scripts/fetch.js按 URL 哈希落缓存、带 ETag 条件请求支持 304 复用、无缓存头时兜底 15 分钟 TTL。正因为 schema 的新鲜度由服务端缓存头控制每次写 YAML 前都取 schema在实践中才是可行的。五项自查清单同一份技能还给出写作阶段的自查可直接当 review checklist先取 schema拿到当前 job type、参数与允许值核对每种 job type 的必填字段是否齐全确认needs与after中引用的作业确实存在于本文件——删掉一个 job 却忘了清理别处的needs是这类 YAML 最常见的翻车点检查表达式引用的上下文与输出是否有效确认if条件符合 schema 的长度约束。别把作业成功当成已上架工作流只编排作业真正的商店行为由type: submit背后的 EAS Submit 决定。要让流水线可靠得理解下游两个特性。提交只是排队主技能文件列出提交相关的只读命令并标注了版本差异# 列表与查看提交作业 eas submit:list -p ios --json eas submit:view SUBMISSION_ID --json这些命令在 EAS CLI 23.2.0 中可用但在测试过的 18.6.0 中不存在不想改全局安装时可以用npx eas-cli23.2.0这类固定版本调用。testflight.md 进一步区分了两个命令的语义submit:view报告的是EAS 作业submit:status才读取 App Store Connect反映 App Store 版本与 TestFlight 处理/内测/外测状态并且需要对应 profile 或环境中的 App Store Connect API key。同文件的状态推进表把验证到了哪一步的边界说得很清楚已验证状态它证明了什么下一步检查EAS 构建完成产出了产物确认 build ID、来源提交与 profile提交已排队EAS 安排了上传跟踪 submission URL 与 worker 日志Apple 上传/处理成功Apple 接受了二进制TestFlight 可用性与合规事项分配给测试者并可用目标测试者可安装在真机安装验证App Review 批准并发布公开 App Store 分发仅属于已授权的生产发布实际含义是不要在submit作业成功后立即宣布已上架。文档还特别提醒不能仅凭--no-wait返回成功就认定上传完成。元数据推送顺序里有业务含义参考示例以单作业两步的形式给出# .eas/workflows/release.yml jobs: submit-and-metadata: steps: - name: Submit to App Store run: eas submit -p ios --latest - name: Push Metadata run: eas metadata:push见 app-store-metadata.md。注意这种写法与前面作业类型 params的风格不同——它依赖作业内的steps列表而steps.*正是可用表达式上下文之一所以这种写法在 schema 中有对应位置。该片段本身未声明作业类型实际接入时以 schema 与workflow:validate的结果为准。两个 step 的先后不能随意调换metadata:push之前必须先有二进制。元数据文档的常见问题里就有一条 Binary not found解法是 Push a binary witheas submitbefore pushing metadata。Android 侧同一份 YAML 服务不同发布策略type: submit在 Android 上落到 Play Console 的某个 trackinternal→alpha→beta→production由eas.json中submitprofile 的track与releaseStatus控制暂停进行中的发布用releaseStatus: halted做灰度用inProgress搭配rollout: 0.1先放 10%。这意味着同一份工作流 YAML 可以为不同的发布策略服务只需在eas.json里换 track 与 rollout 参数不必改 YAML。还有一条容易忽略的边界submit:status目前只读取 Apple 的状态EAS 作业成功并不能证明 Play Console 上的发布已生效见 play-store.md。排查 Android 发布时去 Play Console 看 track 与发布状态。凭据别进仓库参考文档 Tips 的最后一条Keep sensitive values in EAS Secrets, not workflow files. 工作流文件会进 Git 仓库任何写死的凭据都会随之扩散。Android 服务账号是最典型的需要处理的凭据。它可以以文件形式存进 EAS Secrets再被eas.json引用eas secret:create --name GOOGLE_SERVICE_ACCOUNT \ --value $(cat google-service-account.json) --type file{ submit: { production: { android: { serviceAccountKeyPath: secret:GOOGLE_SERVICE_ACCOUNT } } } }见 play-store.md。注意serviceAccountKeyPath里放的是secret:引用而非真实路径——这样工作流 YAML 与eas.json都可以安全提交密钥只在 EAS 服务端解析。CI 环境下的另一种做法是EXPO_ANDROID_SERVICE_ACCOUNT_KEY_BASE64环境变量服务账号 JSON 的 base64。排错速查表把参考文档 Tips 与各参考文件中的故障条目合并按先查什么组织现象先查什么出处工作流 YAML 校验不通过用workflow:validate逐个文件重跑确认profile存在于eas.jsoneas-workflows/SKILL.md作业引用的前置作业不存在检查needs/after是否指向本文件中真实存在的 jobeas-workflows/SKILL.mdPR 预览更新下发不到设备核对构建的 channel 是否指向pr-n分支、平台与 runtime version 是否匹配eas-update/SKILL.md提交推到了错误的构建改用build_id: ${{ needs.build.outputs.build_id }}显式绑定testflight.mdsubmit成功但无可安装包查 TestFlight 处理/合规状态与测试组分配testflight.md元数据推送报 Binary not found先跑一次eas submit再eas metadata:pushapp-store-metadata.mdAndroid 版本号冲突autoIncrement: true配合appVersionSource: remoteplay-store.mdiOS 上传被拒大图标 alpha 通道移除默认 AppIcon PNG 的 alpha 通道后重新构建testflight.mdAndroid 提交报权限不足在 Play Console → API access 给服务账号 Release to productionplay-store.md主技能文件还写了一条通用汇报纪律报告时给出确切的 build ID / 版本号以及已验证到的最远状态不要把作业成功等同于商店可下载。落地六步清单第一次接入工作流的项目建议按这个顺序推进每步都有明确的验证动作对齐账号状态eas whoami确认登录检查应用配置中的extra.eas.projectId缺失则eas init先写非生产流水线从推送到 main 即构建开始只跑type: build确认profile能被解析、产物能下载加上校验环节把npx -y eas-clilatest workflow:validate .eas/workflows/file.yml --non-interactive作为提交前的固定动作接入 PR 预览先确认预览构建的 channel/分支映射策略再打开pull_request触发避免一开就产生大量无效分支最后接生产发布tag 触发 显式build_id的 submit 作业并在流水线之外保留 TestFlight / Play Console 的人工核验把凭据移出仓库所有服务账号、API key 走 EAS SecretsYAML 与eas.json只保留引用。收尾记住的是四个技能的边界eas-app-stores负责构建什么、提交到哪eas-workflows负责YAML 怎么写、怎么校验eas-update负责OTA 的通道与兼容性eas-hosting负责网页与 API 路由的部署。把这四个技能的边界分清比记住任何一个字段名都更有长期价值。【免费下载链接】skillsA collection of AI agent skills for working with Expo projects and Expo Application Services项目地址: https://gitcode.com/GitHub_Trending/skills9/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

DeepSeek新模型编程基准超Claude,还开放了搜索API:RAG玩家先别急,AI话题解读

DeepSeek新模型编程基准超Claude,还开放了搜索API:RAG玩家先别急,AI话题解读

昨天 AI 圈最大的新闻,DeepSeek 把 V4.1 Flash 更新到了 1017 版本,还开放了自研搜索 API。编程基准 DeepSWE 拿了 77.0 分,超过了 Claude Opus 5。数字看着吓人,今天聊聊这事到底意味着什么,尤其是对做 RAG 的人。 先…

📅 2026/10/31 14:38:30
零基础搭建 OpenClaw ,本地 AI 智能体完整部署避坑指南

零基础搭建 OpenClaw ,本地 AI 智能体完整部署避坑指南

📖 前言 本文面向 Windows 系统用户,系统梳理 OpenClaw 的标准化部署流程。全程无需输入任何命令行,所有操作均依托可视化向导完成,即便是零基础用户也能独立走完整套部署。文中同时汇总了高频报错的对应解决方案,力求…

📅 2026/10/31 14:38:30
长庚大学Desalination:3.2 A焦耳热6秒合成CuNiPtRu,用电化学把硝酸盐转化为铵

长庚大学Desalination:3.2 A焦耳热6秒合成CuNiPtRu,用电化学把硝酸盐转化为铵

1. 背景氨既是化肥、化工和医药的重要原料,也被视为潜在的低碳储氢与能源载体;但传统 Haber-Bosch 工艺依赖高温高压和化石能源供氢,能耗与碳排放压力突出。与此同时,农业和工业活动造成的水体硝酸盐污染日益严重。电化学硝酸盐还…

📅 2026/10/31 14:33:29
MORE NEWS

更多资讯

📰

语音社交产品冷启动策略与内容增长引擎设计

1. 语音社交产品的冷启动困境与破局点2023年全球语音社交市场规模已达47.8亿美元,但新产品的90日留存率普遍低于15%。这个数据背后反映的是语音社交产品面临的典型增长困境:用户获取成本高、内容沉淀难、社交关系链脆弱。我在操盘多款语音社交产品时发现…

📰

终端Raw模式与ANSI语法高亮实现指南

终端里做界面,最让人又爱又恨的东西就是 ANSI 转义序列。爱它,是因为只要一行 \e[38;5;208m ,你就能在任何支持颜色的终端里画出想要的层次;恨它,是因为大多数 UI 框架会把你的字符串当作纯文本处理,帮你…

📰

可解释AI在孤独症诊断中的突破与应用

1. 项目概述:AI如何解码孤独症的大脑密码 在精神健康领域,孤独症谱系障碍(ASD)的诊断一直面临重大挑战。传统诊断主要依赖行为观察和量表评估,存在主观性强、早期识别困难等问题。这项发表在《eClinicalMedicine》的研…

📰

京东价格API接入与动态定价策略实战

1. 京东价格API技术实现概述 在电商运营领域,商品定价策略直接影响转化率和利润率。京东价格API(jd.union.open.goods.price.query)为开发者提供了获取商品历史价格数据的官方通道,通过系统化分析这些数据,可以建立科学…

📰

context-mode 上下文模式设计:从工程概念到落地实践

1. 从“context-mode”说起:一个被低估的工程概念 第一次看到“context-mode”这个词,很多人会下意识地把它归到某个具体框架的配置项里,觉得无非是切换一下运行模式、改个参数的事。但我在实际项目里反复踩坑之后发现,这个词背后…

📰

Minecraft Forge 1.20.1 模组安装指南:从零基础到精通

简介:这份资源是面向 Minecraft 模组开发者的 Forge 1.20.1 模组开发工具包(MDK),适合具备一定 Java 与 Gradle 基础、希望上手或迁移到 1.20.1 版本的开发者使用,可解决从零搭建模组工程、配置构建环境与了解版本变更…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬