dreame-action/docs/shopify-deployment-runbook.md

308 lines
9.5 KiB
Markdown
Raw Normal View History

2026-06-19 15:03:31 +08:00
# Shopify 真实环境部署上线说明
本文档用于测试人员和上线人员把当前代码部署到真实测试环境和生产环境。仓库里的默认 `shopify.app.toml` 是模板配置,不应保留个人账号测试时生成的 `client_id`、extension `uid`、`.shopify/` 本地 link 状态或任何 `.env` 密钥。
## 1. 环境边界
- 个人验证环境只用于本地 CLI 校验,验证完成后必须移除个人账号生成的 app 绑定信息。
- 真实测试环境和生产环境必须分别使用各自 Shopify Partner / Developer Dashboard 中的 app。
- 不要把 `SHOPIFY_API_SECRET`、第三方 `api_secret`、Admin access token、数据库密码提交到 Git。
- `client_id` 和 extension `uid` 虽不是密钥,但属于环境绑定信息;若项目要求保密,放在私有部署配置或 CI/CD secret 里,不提交到公开仓库。
- `.shopify/` 是 Shopify CLI 本地状态目录,已在 `.gitignore` 中忽略;不要复制到其他环境。
## 2. 前置条件
在部署机器或 CI/CD 环境中准备:
```bash
node -v
npm -v
shopify version
```
要求:
- Node.js 20 或更高版本。
- Shopify CLI 可用。
- 真实测试/生产 Shopify 账号已具备创建、配置和部署 app 的权限。
- 已准备公网 HTTPS 后端域名,例如 `https://staging-app.example.com``https://app.example.com`
- 已准备数据库连接、Dreame 第三方接口地址和密钥。
## 3. 安装和基础校验
```bash
cd "/path/to/dreame-shopify-app"
npm install
npx prisma generate
npx prisma validate --schema prisma/schema.prisma
npm test
npm run typecheck
npm run build
```
如果使用 CI/CD建议把以上命令作为部署前质量门槛。
## 4. 创建或链接 Shopify app
建议测试和生产使用命名配置,避免互相覆盖:
```bash
shopify app config link --config staging --reset
shopify app config link --config production --reset
```
CLI 会提示输入 app name。建议使用
- 测试环境:`Dreame Activity Staging`
- 生产环境:`Dreame Activity`
如果真实 app 已经存在,使用对应 app 的 Client ID 链接:
```bash
shopify app config link --config staging --client-id <staging-client-id>
shopify app config link --config production --client-id <production-client-id>
```
链接后检查生成的配置文件:
- `shopify.app.staging.toml`
- `shopify.app.production.toml`
- `extensions/thank-you-activity/shopify.extension.toml` 中的 `uid`
## 5. 修改环境配置
在对应 `shopify.app.<env>.toml` 中确认:
```toml
application_url = "https://<public-backend-domain>"
[access_scopes]
scopes = "read_orders,read_metaobjects,write_metaobjects,write_metaobject_definitions"
2026-06-19 15:03:31 +08:00
[auth]
redirect_urls = [
"https://<public-backend-domain>/auth/callback",
"https://<public-backend-domain>/auth/shopify/callback",
"https://<public-backend-domain>/api/auth/callback"
]
```
`extensions/thank-you-activity/shopify.extension.toml` 保留 CLI 为真实 app 生成的 `uid`。不要使用个人账号测试时生成的 `uid`
## 6. 运行官方配置校验
```bash
shopify app config use staging
shopify app config validate --config staging --json
shopify app info --config staging --json
```
生产环境:
```bash
shopify app config use production
shopify app config validate --config production --json
shopify app info --config production --json
```
非交互环境中,如果还没有本地 link 状态,直接带目标 app Client ID
```bash
shopify app config validate --client-id <client-id> --json
```
2026-06-19 15:03:31 +08:00
验收标准:
- `shopify app config validate --json` 返回 `valid: true`
- `issues` 为空。
- `app info` 中的 `client_id`、`application_url`、`redirect_urls`、`scopes` 与目标环境一致。
## 7. 准备运行时环境变量
部署后端服务时配置:
```env
SHOPIFY_API_KEY=<client_id>
SHOPIFY_API_SECRET=<app_secret_from_dashboard>
SHOPIFY_APP_URL=https://<public-backend-domain>
SCOPES=read_orders,read_metaobjects,write_metaobjects,write_metaobject_definitions
2026-06-19 15:03:31 +08:00
DATABASE_URL=<database_connection_string>
THIRD_PARTY_MODE=live
THIRD_PARTY_TIMEOUT_MS=5000
LOG_RETENTION_DAYS=7
METAOBJECT_TYPE=$app:dreame_activity
2026-06-19 15:03:31 +08:00
METAOBJECT_HANDLE=dreame-activity-config
```
Shopify CLI 可拉取 app 相关环境变量:
```bash
shopify app env pull --config staging --env-file .env.staging
shopify app env pull --config production --env-file .env.production
```
不要把 `.env.staging`、`.env.production` 提交到 Git。
## 8. 数据库和 Prisma
当前本地开发默认使用 SQLite
```env
DATABASE_URL="file:./dev.sqlite"
```
真实环境必须先确认数据库方案。若使用 Postgres需要在上线前完成 Prisma datasource 和迁移策略调整,并在目标环境执行迁移。部署前至少确认以下表已经创建:
- `Session`
- `ActivityPushLog`
- `ActivityPushIdempotency`
## 9. Metaobject 配置
Metaobject definition 已声明在 `shopify.app.toml`,由 Shopify CLI 在 `shopify app dev/deploy` 时应用:
2026-06-19 15:03:31 +08:00
- TOML key: `[metaobjects.app.dreame_activity]`
- Admin API type: `$app:dreame_activity`
2026-06-19 15:03:31 +08:00
- Handle: `dreame-activity-config`
- Admin access: `merchant_read_write`
- Storefront access: `none`
如果目标店铺已经存在旧的 merchant-owned type `dreame_activity`,可以通过 `METAOBJECT_TYPE=dreame_activity` 兼容,但新环境建议使用 app-owned `$app:dreame_activity`
2026-06-19 15:03:31 +08:00
字段:
| Key | Type | Required |
| --- | --- | --- |
| `activity_id` | `number_integer` | yes |
| `api_app_id` | `single_line_text_field` | yes |
| `api_secret` | `single_line_text_field` | yes |
| `status_api_url` | `url` | yes |
| `push_api_url` | `url` | yes |
| `status_success_code` | `number_integer` | no |
| `status_active_required` | `boolean` | no |
| `push_success_code` | `number_integer` | no |
2026-06-19 15:03:31 +08:00
| `redirect_url` | `url` | yes |
| `button_text` | `json` | yes |
| `shop` | `single_line_text_field` | no |
`api_secret` 只能由后端读取,不应暴露给 Checkout UI Extension。
可选字段默认值:
- `status_success_code`: `0`
- `status_active_required`: `true`
- `push_success_code`: `0`
若第三方确认接口②成功码不是 `0`,只需修改 Metaobject entry 的 `push_success_code`,不需要改代码。
写入或更新 entry
```bash
SHOPIFY_SHOP_DOMAIN=<shop>.myshopify.com \
SHOPIFY_ADMIN_ACCESS_TOKEN=shpat_xxx \
npx tsx scripts/setup-metaobject.ts
```
脚本使用 `metaobjectUpsert`,重复执行会更新同一个 handle不会创建重复 entry。
2026-06-19 15:03:31 +08:00
## 10. 部署后端服务
Shopify CLI 的 `app deploy` 不会部署 Remix 后端服务。需要先把 web app 部署到自有托管环境,并确认:
```bash
curl -i https://<public-backend-domain>/
curl -i -X OPTIONS https://<public-backend-domain>/api/action/activity/check
```
期望:
- 首页或健康页返回 200。
- OPTIONS 返回 204并包含 CORS headers。
- 未带 Shopify checkout session token 的 POST 应返回 `{"success":false}`
## 11. 部署 Shopify 配置和扩展
测试环境:
```bash
shopify app deploy --config staging --allow-updates --message "staging deployment"
```
生产环境建议先创建未发布版本:
```bash
shopify app deploy --config production --no-release --message "production candidate"
```
确认版本无误后,再发布生产版本:
```bash
shopify app deploy --config production --allow-updates --message "production release"
```
不要在生产环境使用 `--allow-deletes`,除非已经明确确认要删除远端扩展或配置。
## 12. Checkout UI Extension 设置
在目标 app 的 Checkout UI Extension 配置中,把 setting `app_url` 设置为当前环境后端地址:
```text
https://<public-backend-domain>
```
确认 extension target
```text
purchase.thank-you.block.render
```
该 target 是 Thank You Page block target商家可在 checkout and accounts editor 控制展示位置。若改为 `purchase.thank-you.header.render-after` 等静态 target需要修改 `shopify.extension.toml` 并重新部署 app extension。
当前 TOML 设置:
```toml
default_placement = "ORDER_STATUS1"
```
首次推荐位置为订单状态卡片上方;商家仍可在编辑器移动该 block。
2026-06-19 15:03:31 +08:00
## 13. 上线验收
测试订单验收:
1. 在目标店铺完成一笔测试订单。
2. Thank You Page 加载 extension。
3. Extension 调用 `/api/action/activity/check`
4. 后端通过 Shopify checkout session token 校验。
5. 后端读取订单、Metaobject 配置和 Dreame 状态接口。
6. `status=true` 时只推送一次 `order_end`
7. 页面展示本地化按钮。
8. 点击按钮跳转到 Metaobject 配置的 `redirect_url`
9. 重复刷新订单完成页不会重复 push。
10. `ActivityPushLog``ActivityPushIdempotency` 有对应记录,且不含 `api_secret` 或签名明文。
## 14. 回滚
- Shopify app 配置或扩展异常:在 Developer Dashboard 回滚到上一个 app version。
- 后端异常:回滚托管平台的 web app release。
- 第三方接口异常:临时切回 `THIRD_PARTY_MODE=mock` 只能用于测试环境,不允许作为生产长期方案。
## 15. 交付检查清单
- [ ] 代码测试通过:`npm test`
- [ ] TypeScript 通过:`npm run typecheck`
- [ ] 构建通过:`npm run build`
- [ ] Shopify config validate 通过
- [ ] 后端公网 URL 与 redirect URLs 一致
- [ ] 数据库迁移完成
- [ ] Metaobject definition 和 entry 已创建
- [ ] Checkout UI Extension 已部署并配置 `app_url`
- [ ] 真实测试订单通过
- [ ] 日志和幂等记录已核验
- [ ] 未提交 `.env`、`.shopify/`、个人 `client_id` 或个人 extension `uid`
参考:
- Shopify CLI: https://shopify.dev/docs/api/shopify-cli
- App configuration: https://shopify.dev/docs/apps/tools/cli/configuration