GitHub Actions 发布
配置 GitHub Environments 和 Cloudflare secrets,通过 workflow 发布 staging 与 production
WeMail 的标准发布入口是:
.github/workflows/deploy-cloudflare.yml它支持手动触发,输入参数是目标环境:
stagingproduction

这是示意截图。真实 GitHub UI 可能不同,但你要点击的是 Deploy Cloudflare workflow 的 Run workflow。
1. 创建 GitHub Environments
在 GitHub 仓库中进入:
Settings -> Environments创建:
staging
production建议:
- staging 可以不加审批,方便快速验证。
- production 建议加 required reviewers,避免误发。
2. 配置 Environment secrets
每个 environment 至少配置:
| Secret | 用途 |
|---|---|
CLOUDFLARE_API_TOKEN | 部署 Worker、Pages、执行 D1 migrations |
CLOUDFLARE_ACCOUNT_ID | Cloudflare Account ID |
CLOUDFLARE_PAGES_PROJECT_NAME | Cloudflare Pages 项目名 |
CLOUDFLARE_D1_DATABASE_ID | 当前 environment 的 D1 database ID |
CLOUDFLARE_KV_NAMESPACE_ID | 当前 environment 的 KV namespace ID |
CLOUDFLARE_KV_PREVIEW_NAMESPACE_ID | 当前 environment 的 KV preview namespace ID |
GITHUB_TOKEN 是 GitHub Actions 内建 token,不需要手动配置。
RATE_LIMITER 的 Rate Limiting namespace_id 已写在 apps/worker/wrangler.toml,要求是 Cloudflare 账号内唯一的整数形式字符串。它不是 GitHub secret,也不是需要单独创建的 Cloudflare 资源;只有当你的账号中已有 Worker 使用相同数字时,才需要换成其他整数。
3. 配置 Environment variables
当前 Cloudflare workflow 会在构建 Pages 前校验并注入:
VITE_API_BASE_URL它应该指向 Worker API 根地址,例如:
https://wemail-api.example.com不要在末尾添加 /api。构建后的浏览器请求会访问:
${VITE_API_BASE_URL}/api/...这个值可以放 GitHub Environment variable,也可以放同名 secret。URL 本身通常不是 secret,优先使用 variable。
生产建议使用同站 API 自定义域,例如 https://wemail-api.example.com。workers.dev 适合临时 smoke test,但如果 Pages 在 https://wemail.example.com,Worker 在 https://*.workers.dev,浏览器会把它们视为跨站请求,session cookie 更容易受限制。
如果你选择同域 /api 模式,需要在 Cloudflare 里让 /api/* 指向 Worker,并确保 workflow 不注入其他 API base。
4. 创建 Cloudflare API Token
建议使用最小权限 token。需要覆盖:
| 权限 | 级别 |
|---|---|
| Workers Scripts | Edit |
| D1 | Edit |
| Pages | Edit |
| Workers Routes | Edit, zone 级别;wrangler.toml 配了 /api/* routes 时必需 |
| Zone | Read, zone 级别;使用 zone_name route 时用于解析 zone ID |
| Workers Tail | Read,可选 |
如果团队权限允许,staging 和 production 使用不同 token,减少误操作风险。
如果 deploy-worker 在 wrangler deploy 阶段提示 Some triggers failed to deploy 或 /zones/.../workers/routes 失败,通常就是 CLOUDFLARE_API_TOKEN 缺少 Workers Routes: Edit,或者 token 没有被授权到 wrangler.toml 中 route 所属的 zone。
GitHub Environment variable 不会自动进入 shell。你需要在 workflow 的 build 步骤显式传入:
env:
VITE_API_BASE_URL: ${{ vars.VITE_API_BASE_URL || secrets.VITE_API_BASE_URL }}5. workflow 做了什么
prepare
作用:
- 校验 production 只能从
main触发。 - 检查 Cloudflare deploy secrets 和 D1 / KV 绑定 ID secrets 是否存在。
- 根据 environment 输出 D1 database name、Worker deploy command、Pages deploy mode。
production 分支保护逻辑:
if [[ "${GITHUB_REF}" != "refs/heads/main" ]]; then
echo "Production deployments are only allowed from the main branch." >&2
exit 1
fiverify
作用:
- 安装依赖。
- 执行版本检查。
- 执行测试、类型检查、lint 和 build。
- 上传
apps/web/dist作为 artifact。
实际命令:
pnpm version:check
pnpm test
pnpm typecheck
pnpm lint
pnpm builddeploy-worker
作用:
- 安装依赖。
- 对远端 D1 执行 migrations。
- 部署 Worker。
staging 使用:
wrangler d1 migrations apply wemail-staging --env staging --remote
wrangler deploy --env stagingproduction 使用:
wrangler d1 migrations apply wemail-production --env production --remote
wrangler deploy --env productiondeploy-pages
作用:
- 下载
apps/web/distartifact。 - 部署 Cloudflare Pages。
staging:
pages deploy apps/web/dist --project-name=<project> --branch=stagingproduction:
pages deploy apps/web/dist --project-name=<project>6. 发布 staging
进入 GitHub:
Actions -> Deploy Cloudflare -> Run workflow选择:
| 项 | 值 |
|---|---|
| Branch | 当前待验证分支 |
| environment | staging |
等待以下 job 全部通过:
prepareverifydeploy-workerdeploy-pages
完成后在 Job Summary 里记录:
- Worker deployment URL。
- Pages deployment URL。
- Pages alias URL,如果有。
- Git ref。
- D1 database name。
7. staging 冒烟
先检查 API:
curl -i "$STAGING_API_BASE_URL/api/system/health"再打开 staging Pages URL,验证:
- 首页。
- 登录。
- 注册。
- 创建邮箱账号。
- 邮件列表。
- 系统设置。
- Webhook / Telegram / 公告等启用的页面。
如果 staging 没验收,不要发 production。
8. 发布 production
production 只能从 main 发。
发布前确认:
- 当前发布 commit 已合入
main。 - staging 已验证通过。
CHANGELOG.md已更新。- production Environment secrets 已配置 D1 / KV 真实 ID。
wrangler.toml没有提交真实 D1 / KV ID。- production secrets 已写入。
- 回滚目标 commit 或 tag 已明确。
触发 workflow:
| 项 | 值 |
|---|---|
| Branch | main |
| environment | production |
如果 production environment 配置了审批,审批后 workflow 才会继续。
常见失败
Missing required secrets
prepare job 会检查:
CLOUDFLARE_API_TOKENCLOUDFLARE_ACCOUNT_IDCLOUDFLARE_PAGES_PROJECT_NAMECLOUDFLARE_D1_DATABASE_IDCLOUDFLARE_KV_NAMESPACE_IDCLOUDFLARE_KV_PREVIEW_NAMESPACE_ID
缺哪个就去对应 GitHub Environment 补哪个。
production 从非 main 分支触发
workflow 会直接失败。这是预期保护。
解决方式:
- 先把 release commit 合入
main。 - 从
main重新触发 production。
D1 migrations 失败
不要跳过 migrations 继续部署。先看失败 SQL 和远端 D1 状态。
常见原因:
- 当前 GitHub Environment 的
CLOUDFLARE_D1_DATABASE_ID配错。 - migrations 已部分执行。
- migration 文件与当前 schema 不兼容。
Some triggers failed to deploy
如果 Worker 已经上传,但 deploy-worker 在 route trigger 阶段失败,检查当前 environment 的 CLOUDFLARE_API_TOKEN 是否有目标 zone 权限:
Zone / Workers Routes: EditZone / Zone: Read
apps/worker/wrangler.toml 里 staging 和 production 都配置了 zone_name route。缺少这些权限时,Wrangler 可以部署到 workers.dev,但不能更新 wemail.example.com/api/* 这类自定义域名路由。
Pages 部署成功但页面请求错 API
看 Pages 前端部署 的 API 地址模式。多数情况下是:
- 没有配置同域
/api/*Worker route。 - 选择独立 API 域名,但构建时没有传入
VITE_API_BASE_URL。
发布记录建议
每次 production 发布都记录:
| 字段 | 示例 |
|---|---|
| 环境 | production |
| commit | abc1234 |
| tag | v0.1.2 |
| Worker URL | workflow 输出 |
| Pages URL | workflow 输出 |
| D1 database | wemail-production |
| 发布人 | GitHub actor |
| staging 验收结论 | 通过 / 不通过 |
| 回滚目标 | 上一个稳定 tag |