feat(deploy): 接入全自动生产发布校验
This commit is contained in:
@@ -191,6 +191,14 @@ V2 接入后端后改为基于 `ProjectMember` 表的 RBAC(Owner/Admin/Member/
|
||||
- `task-category.ts`:DevTask/TestCase 共用任务类型字典,`id` 用于存储,AI 输出的 `taskTypeName` 必须是可复用类型;可复用开发类型可在采纳时自动追加到字典,测试用例未知类型回退到已有测试分类,`code` 仅作可选语义映射。
|
||||
|
||||
页面组件只消费规则层输出,不直接拼完成条件或候选筛选条件。
|
||||
## Production Runtime Version Layer (2026-07-06)
|
||||
|
||||
Production deployment now treats CI-built Docker images as the release artifact. `Dockerfile.web` and `Dockerfile.server` accept `APP_VERSION`, `APP_BUILD_TIME`, and image tag build metadata; `docker-compose.prod.yml` pulls immutable `WEB_IMAGE` and `SERVER_IMAGE` tags instead of relying on deployment-side rebuilds.
|
||||
|
||||
The server exposes `GET /api/v1/health/version`, returning the running server commit/version metadata. The web app embeds `NEXT_PUBLIC_APP_VERSION` at build time and shows a refresh prompt when the browser is still on an older frontend bundle than the server runtime.
|
||||
|
||||
GitHub Actions is the production release orchestrator: build and push images, SSH to the server, update `.env.production` image tags, pull images, run `pnpm --filter server db:deploy`, restart Compose services, and verify `/api/v1/health/version` against the current commit SHA.
|
||||
|
||||
## Work Activity Daily Report Layer (2026-06-26)
|
||||
|
||||
The personal daily report is derived from two inputs:
|
||||
|
||||
@@ -477,6 +477,20 @@
|
||||
|
||||
**理由**:Docker Compose 足够覆盖当前单机云服务器和本地服务器形态,部署成本低、可读性强,也符合现阶段 2 核 4G 云主机目标。同域反代能减少 CORS 和公网端口暴露面。本地服务器默认 8080,避免占用 80 端口或要求管理员权限;云服务器继续使用 80 作为外层入口。HTTPS 证书自动续期和域名接入在不同云环境差异较大,先作为外层能力处理,避免把生产部署模板绑死在某一种证书方案上。
|
||||
|
||||
## 38.1. 生产发布改为 CI 镜像制品 + 运行版本校验
|
||||
|
||||
**问题**:仅让部署侧 `git pull` 最新代码并不能保证线上用户看到新前端。Next.js 前端需要重新构建,Docker 容器也需要重新创建;如果对方只拉代码、不 `build/up`,就会出现仓库是新的、运行容器仍是旧的情况,需求池搜索、成员用户名、性能改动等都无法靠肉眼判断是否已经上线。
|
||||
|
||||
**决策**:
|
||||
- GitHub Actions 在 `master` 更新时构建 `web` / `server` Docker 镜像,并推送到 GHCR。
|
||||
- 镜像以 commit SHA 作为不可变 tag,同时更新 `master` tag。
|
||||
- `docker-compose.prod.yml` 使用 `WEB_IMAGE` / `SERVER_IMAGE` 拉取镜像,保留 `build` 仅作为本地兜底。
|
||||
- `APP_VERSION` 使用 commit SHA,构建时写入前端 `NEXT_PUBLIC_APP_VERSION` 和后端运行环境。
|
||||
- 后端提供 `GET /api/v1/health/version`,Actions 发布结束后必须校验返回版本等于本次 commit SHA。
|
||||
- 前端定时比较自身构建版本和服务端运行版本,不一致时提示刷新页面。
|
||||
|
||||
**理由**:发布物必须是 CI 产出的镜像,而不是服务器上的源码目录。版本号打进镜像后,部署问题可以被机器判断:如果 Actions 校验通过,说明线上容器已经运行本次提交;如果校验失败,问题就在部署链路而不是业务代码。前端刷新提示解决的是浏览器仍持有旧 bundle 的尾部问题,不能替代容器更新,但能让用户明确知道需要刷新。
|
||||
|
||||
## 39. AppData 文档写入采用乐观锁,先阻止静默覆盖
|
||||
|
||||
**问题**:V2.1 阶段业务数据仍按模块存成 `app_data.value` 整份 JSON 文档。多人同时打开同一模块后,如果 A 和 B 都基于旧副本编辑,原来的无条件 `upsert` 会让后保存的人覆盖先保存的人,尤其是任务、Bug、成员等高频写入数据。
|
||||
|
||||
@@ -144,6 +144,45 @@ docker compose --env-file .env.production -f docker-compose.prod.yml ps
|
||||
curl http://localhost/api/v1/config/ai
|
||||
```
|
||||
|
||||
## 全自动生产发布(推荐)
|
||||
|
||||
生产环境推荐走 `.github/workflows/deploy-production.yml`,不再要求部署侧手工执行 `docker compose build` 或手工判断是否需要 `up`。
|
||||
|
||||
GitHub 仓库需要配置这些 Secrets:
|
||||
|
||||
- `PROD_HOST`:生产服务器地址。
|
||||
- `PROD_USER`:SSH 用户。
|
||||
- `PROD_SSH_KEY`:SSH 私钥。
|
||||
- `PROD_APP_DIR`:服务器上的项目目录。
|
||||
- `GHCR_READ_TOKEN`:可选。GHCR 镜像为私有包时,用于服务器 `docker login ghcr.io` 拉镜像。
|
||||
|
||||
服务器首次准备仍然需要完成一次:
|
||||
|
||||
```bash
|
||||
git clone <repo-url> ftb-project-management
|
||||
cd ftb-project-management
|
||||
cp .env.production.example .env.production
|
||||
```
|
||||
|
||||
然后按实际环境改好 `.env.production` 里的数据库密码、域名、`NEXTAUTH_SECRET`、AI key 等。`APP_VERSION`、`APP_BUILD_TIME`、`WEB_IMAGE`、`SERVER_IMAGE` 会由 GitHub Actions 在每次发布时自动更新。
|
||||
|
||||
之后只要代码合并或 push 到 `master`,Actions 会自动执行:
|
||||
|
||||
1. 用当前 commit SHA 构建 `web` 和 `server` Docker 镜像。
|
||||
2. 推送镜像到 GHCR,镜像 tag 同时包含 commit SHA 和 `master`。
|
||||
3. SSH 到生产服务器,`git pull --ff-only origin master` 更新 Compose 和部署脚本。
|
||||
4. 写入 `.env.production` 的 `APP_VERSION`、`APP_BUILD_TIME`、`WEB_IMAGE`、`SERVER_IMAGE`。
|
||||
5. 执行 `docker compose --env-file .env.production -f docker-compose.prod.yml pull web server` 拉取本次 SHA 镜像。
|
||||
6. 启动数据库与 Redis,执行 `pnpm --filter server db:deploy`。
|
||||
7. 执行 `docker compose --env-file .env.production -f docker-compose.prod.yml up -d --remove-orphans` 重启服务。
|
||||
8. 通过 `/api/v1/health/version` 校验运行中的后端版本是否等于本次 commit SHA。
|
||||
|
||||
如果最后一步失败,Actions 会红掉,说明“代码已合并”不等于“线上容器已更新”。本地或服务器也可以手工运行:
|
||||
|
||||
```bash
|
||||
pnpm deploy:check-runtime http://localhost/api/v1/health/version <expected-commit-sha>
|
||||
```
|
||||
|
||||
## Nginx 路由
|
||||
|
||||
`deploy/nginx/default.conf.template` 使用官方 Nginx 镜像的模板机制生成配置:
|
||||
|
||||
@@ -6,6 +6,11 @@ V2.3 在 V2.2 快读路径之后补上写入闭环:前端仍保留现有 AppDa
|
||||
|
||||
### 已完成(按时间倒序)
|
||||
|
||||
**2026-07-06**
|
||||
- Added production CI/CD flow: GitHub Actions builds `web` and `server` Docker images, pushes immutable commit-SHA tags to GHCR, deploys by SSH, pulls images on the server, runs `pnpm --filter server db:deploy`, restarts Compose, and verifies `/api/v1/health/version`.
|
||||
- Added runtime version metadata: backend `GET /api/v1/health/version`, Docker build args/env, and a frontend refresh banner when browser assets are older than the server runtime.
|
||||
- Added `pnpm deploy:check-runtime` and expanded `pnpm deploy:verify` so deployment artifacts include workflow, image metadata, and runtime version checks.
|
||||
|
||||
**2026-07-03**
|
||||
- V2.3 AppData write-side bridge added: successful `PUT /api/v1/data/:key` calls now trigger `AppDataV23SyncService` relation-table sync after optimistic-lock AppData writes.
|
||||
- Relation sync reuses the V2.2 mapper and replaces current-state rows by partition scope: requirements by `product_id`, version plans/dev tasks/test cases/bugs by `version_id`.
|
||||
|
||||
@@ -240,6 +240,20 @@ AI 估时约束:
|
||||
- 产品方案和 UI 设计的引用需求不再用 checkbox 直接标记完成,必须通过 `requirementCoverage[]` 记录 `not_started / partial / completed`、本次已完成内容和剩余内容;只有 `completed` 计入成果提交门禁。
|
||||
- 产品/UI 计划右侧展示计划日志,需求进度更新和 AI 拆解触发/完成/失败都写入 `VersionPlan.logs[]`,页面只消费日志数据,不临时拼历史。
|
||||
- 调研/产品方案/UI 设计的计划级 `actualStartAt` 只表示计划容器已开始,不直接作为具体任务日报耗时。具体调研方向或引用需求需要先点击「开始任务」,写入当前行的 `currentWorkStartedAt`;提交「记录」时日志和 `work-activities` 保留 `workStartedAt`,日报耗时按 `workStartedAt -> 记录提交时间` 计算,提交后清空当前行的开始时间。完全完成可直接提交结束本次耗时,部分完成才需要填写本次已完成内容和剩余未完成内容。
|
||||
## Production Release Workflow (2026-07-06)
|
||||
|
||||
Production releases use GitHub Actions as the default path. The deployment side should not manually rebuild frontend assets after every change; it keeps `.env.production` and Docker volumes, while Actions builds immutable images and updates the running containers.
|
||||
|
||||
Standard flow:
|
||||
|
||||
1. Merge or push to `master`.
|
||||
2. GitHub Actions builds `web` and `server` images with `APP_VERSION=<commit-sha>`.
|
||||
3. Actions pushes the images to GHCR.
|
||||
4. Actions SSHes into the server, updates `.env.production` image tags, pulls the images, runs `pnpm --filter server db:deploy`, and restarts Compose.
|
||||
5. Actions verifies `/api/v1/health/version` equals the commit SHA.
|
||||
|
||||
If a user reports "latest code pulled but UI is still old", first compare the running version endpoint with the expected commit. A mismatch means deployment did not update the running container. A match means the code is deployed and the remaining issue is likely browser cache, data, or business logic.
|
||||
|
||||
## Work Activity Daily Report Flow (2026-06-26)
|
||||
|
||||
The daily report flow uses mixed evidence:
|
||||
|
||||
Reference in New Issue
Block a user