fix(GOV-009): 完成仅源码部署最终复审
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
<!-- gitnexus:start -->
|
||||
# GitNexus — Code Intelligence
|
||||
|
||||
This project is indexed by GitNexus as **a-share-analysis** (1589 symbols, 2211 relationships, 47 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||
This project is indexed by GitNexus as **a-share-analysis** (1606 symbols, 2253 relationships, 50 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||
|
||||
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
|
||||
|
||||
|
||||
@@ -23,16 +23,20 @@ pnpm verify:release
|
||||
生产配置放在 `/etc/a-share-analysis/api.env`、`scheduler.env`、`worker.env`,建议权限 `root:a-share 0640`;Web 的 `VITE_` 公开变量在构建前注入。三个 systemd 单元通过各自的 `EnvironmentFile=` 只读取本进程需要的键,运行用户为非登录系统用户 `a-share`。
|
||||
|
||||
```bash
|
||||
sudo install -m 0644 deploy/systemd/a-share-*.service.example /etc/systemd/system/
|
||||
sudo install -m 0644 deploy/systemd/a-share-api.service.example /etc/systemd/system/a-share-api.service
|
||||
sudo install -m 0644 deploy/systemd/a-share-scheduler.service.example /etc/systemd/system/a-share-scheduler.service
|
||||
sudo install -m 0644 deploy/systemd/a-share-worker.service.example /etc/systemd/system/a-share-worker.service
|
||||
sudo install -m 0644 deploy/nginx/a-share-analysis.conf.example /etc/nginx/conf.d/a-share-analysis.conf
|
||||
sudo systemd-analyze verify /etc/systemd/system/a-share-api.service.example
|
||||
sudo systemd-analyze verify /etc/systemd/system/a-share-scheduler.service.example
|
||||
sudo systemd-analyze verify /etc/systemd/system/a-share-worker.service.example
|
||||
sudo systemd-analyze verify /etc/systemd/system/a-share-api.service
|
||||
sudo systemd-analyze verify /etc/systemd/system/a-share-scheduler.service
|
||||
sudo systemd-analyze verify /etc/systemd/system/a-share-worker.service
|
||||
sudo nginx -t
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart a-share-api.service.example
|
||||
sudo systemctl restart a-share-scheduler.service.example
|
||||
sudo systemctl restart a-share-worker.service.example
|
||||
sudo systemctl restart a-share-api.service
|
||||
sudo systemctl restart a-share-scheduler.service
|
||||
sudo systemctl restart a-share-worker.service
|
||||
sudo systemctl status a-share-api.service a-share-scheduler.service a-share-worker.service
|
||||
sudo journalctl -u a-share-api.service -u a-share-scheduler.service -u a-share-worker.service --since '5 minutes ago'
|
||||
curl --fail http://127.0.0.1:3000/api/v1/health
|
||||
curl --fail http://127.0.0.1/
|
||||
```
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
|
||||
- 记录时间:2026-08-13 GMT+8
|
||||
- 分支:`main`
|
||||
- 实现提交:`95b8611bd9bbc282193591e472e2e19c617e5035`
|
||||
- 远端:`origin/main` 已核对为同一 SHA
|
||||
- 仅源码实现提交:`47d0e0d248eb9b21cbd12f1625d3bd0e9c266dc9`
|
||||
- 远端:`origin/main` 已核对为同一 SHA;最终 Review 证据提交将在验证后同步
|
||||
|
||||
```text
|
||||
Repository: a-share-analysis
|
||||
Indexed commit: 95b8611
|
||||
Current commit: 95b8611
|
||||
Indexed commit: 47d0e0d
|
||||
Current commit: 47d0e0d
|
||||
Status: up-to-date
|
||||
Nodes: 1568
|
||||
Relationships: 2190
|
||||
Clusters: 46
|
||||
Execution flows: 47
|
||||
Nodes: 1606
|
||||
Relationships: 2253
|
||||
Clusters: 48
|
||||
Execution flows: 50
|
||||
```
|
||||
|
||||
图谱已包含 Web、API、Scheduler、Worker、配置加载、健康检查、OpenAPI、消息信封、Schema、Docker 验证和治理门禁。GitNexus 本地索引未提交仓库。
|
||||
图谱已包含 Web、API、Scheduler、Worker、配置加载、健康检查、OpenAPI、消息信封、Schema、外部 Redis 预检、源码产物/systemd/Nginx 发布验证和治理门禁。旧 Docker 验证符号已删除,GitNexus 本地索引未提交仓库。
|
||||
|
||||
@@ -16,3 +16,16 @@
|
||||
- Schema 空库、MySQL 5.7.42、契约漂移和 `.vue` 工程边界均有自动门禁。
|
||||
|
||||
新增关系数量符合“从占位目录建立应用基线”的预期。后续市场概览功能应在这些边界内增加业务模块,不应把 Web 与 Server 重新耦合。
|
||||
|
||||
## 仅源码部署调整对比
|
||||
|
||||
| 项目 | 调整设计提交 `cfcd7f1` | 实现与 Review 后 | 变化 |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| 符号 | 1589 | 1606 | +17 |
|
||||
| 关系 | 2211 | 2253 | +42 |
|
||||
| 执行流程 | 47 | 50 | +3 |
|
||||
|
||||
- 删除 Docker 构建、镜像引用和容器生命周期校验符号,新增源码发布校验流程。
|
||||
- 新增 `checkLocalRedis` 与 `runTestApi`,Playwright 只依赖现有本机 Redis,不拥有基础设施生命周期。
|
||||
- `verifySourceDeployment` 校验 Web、API、Scheduler、Worker 产物以及 systemd/Nginx;递归阻断任意活动 Dockerfile、`.dockerignore` 和 Compose YAML。
|
||||
- GitNexus compare 检测风险为 MEDIUM,98 个变更符号、3 个受影响符号,影响集中在部署门禁与 E2E 启动链;未影响业务 API、市场模块、生产数据库或 RocketMQ 消息发送。
|
||||
|
||||
@@ -13,3 +13,14 @@ Review 整改前对具体符号分别执行上游影响分析:三进程 bootst
|
||||
最终代码复审补充发现无引号 Vue 外部 `script src` 可绕过早期正则门禁;影响分析为 LOW,只有 1 个直接调用者和 1 条边界检查流程。`95b8611` 改用 Vue 3.5.41 官方 SFC 解析器,并以单双引号、无引号和属性换序用例验证,未扩大应用运行影响面。
|
||||
|
||||
检测范围与开发前影响计划一致,未出现用户体系、生产数据库、外部消息写入或其他项目流程。
|
||||
|
||||
## 仅源码部署调整
|
||||
|
||||
- 对比基线:`cfcd7f13d9a6a35173d01bd8ca1458911190e70f`
|
||||
- 实现提交:`47d0e0d248eb9b21cbd12f1625d3bd0e9c266dc9`
|
||||
- 变更范围:27 个已索引文件、98 个变更符号、3 个受影响符号
|
||||
- 风险:MEDIUM
|
||||
|
||||
开发前对 `assertImmutableImageReferences`、旧 Docker 辅助函数和 `forwardSignal` 的上游影响均为 LOW,0 条业务执行流受影响。最终 compare 的 MEDIUM 来自部署门禁整体替换:旧 Docker 验证删除,源码发布与 Redis 预检新增,并非应用业务依赖扩散。
|
||||
|
||||
Review 中 `verifySourceDeployment` 和 `assertDockerArtifactsAbsent` 的影响分析均为 LOW;后者只影响 1 条源码部署校验流程。递归活动资产扫描与 systemd 正式目标名测试完成后,部署 6/6、环境 10/10 和完整 `verify:release` 通过。
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
### GREEN
|
||||
|
||||
- 源码部署夹具:5/5;覆盖完整发布、Docker 活动文件、Worker 产物缺失、systemd root 用户和 Nginx 错误配置。
|
||||
- 源码部署夹具:初始 5/5;最终 Review 加入任意新 Dockerfile/Compose 路径回归后为 6/6。
|
||||
- 环境与部署契约:10/10;活动 Docker 入口不存在,本地外部 Redis和唯一 Ubuntu 源码部署规则通过。
|
||||
- Redis 预检:2/2;OS 分配的本机 TCP 端口分别验证可达和不可达,不安装或启动外部服务。
|
||||
- 本机 `redis-cli -h 127.0.0.1 -p 6379 ping` 返回 `PONG`。
|
||||
@@ -65,3 +65,18 @@
|
||||
- Playwright 桌面与移动视口共 4/4,通过真实本机 Redis、API 健康接口和 Web 同源代理链路。
|
||||
|
||||
前述 `pnpm verify:docker` 及镜像验证内容是调整前的真实历史证据。2026-08-13 用户确认仅源码部署后,这些能力已被取代并从活动仓库删除,不再执行或作为发布依据。
|
||||
|
||||
### 最终源码发布验证
|
||||
|
||||
`pnpm verify:release`:passed。
|
||||
|
||||
- Node.js 22.11.0、pnpm 10.25.0 运行时检查通过。
|
||||
- 环境 10/10、Schema 28/28、契约 3/3、工程边界 8/8、源码部署 6/6。
|
||||
- Web 8/8;Server Vitest 30/30,Redis 预检 Node 测试 2/2。
|
||||
- Web、API、Scheduler、Worker 生产构建通过。
|
||||
- Playwright 桌面/移动共 4/4,通过现有本机 Redis 和真实 API 健康链路。
|
||||
- `verify:source` 确认四类产物、三份 systemd 单元与 Nginx 配置一致;未调用 Docker。
|
||||
|
||||
应用内浏览器补充验证 1440×900 与 390×844:两种视口页面均非空,页面宽度等于视口宽度,无横向溢出、文字重叠或控制台 warning/error;DOM 中导航与“应用就绪”区域完整。
|
||||
|
||||
最终 Review 发现并修复两项 Important:systemd 模板曾以 `.service.example` 目标名安装,任意新路径的 Dockerfile/Compose 文件曾可绕过固定清单。两项均先增加失败测试,再修复至 GREEN。
|
||||
|
||||
@@ -22,3 +22,25 @@
|
||||
Critical、Important、Minor 均无未关闭问题。
|
||||
|
||||
最终结论:passed
|
||||
|
||||
## 仅源码部署调整复审
|
||||
|
||||
- 审查范围:`cfcd7f13d9a6a35173d01bd8ca1458911190e70f..47d0e0d248eb9b21cbd12f1625d3bd0e9c266dc9` 及其后 Review 修复
|
||||
- 审查重点:发布门禁绕过、子进程与信号、Redis 失败语义、systemd/Nginx 真实命令、历史证据和测试缺口
|
||||
|
||||
### 发现与处置
|
||||
|
||||
1. **Important:systemd 模板目标名不可执行。** 初版源码手册把 `*.service.example` 原样安装并以该名称重启,真实 systemd 单元名不正确。新增环境契约测试先 RED,随后改为分别安装成 `a-share-api.service`、`a-share-scheduler.service`、`a-share-worker.service`,并统一 verify/restart/status/journalctl 命令;环境 10/10 GREEN。
|
||||
2. **Important:Docker 禁止清单可被新路径绕过。** 初版只阻断已删除的固定旧路径,`ops/Dockerfile` 或新 Compose YAML 会被放行。新增未列举路径测试先 RED,随后用递归活动资产扫描阻断任意 Dockerfile、`.dockerignore`、`docker-compose*.yml` 和 `compose/` YAML;部署测试 6/6 GREEN。
|
||||
|
||||
### 最终证据
|
||||
|
||||
- `pnpm verify:release` 完整通过,包含静态检查、类型、全部测试、四类构建、Playwright 4/4 和源码发布校验。
|
||||
- Redis 不可达时只返回脱敏的固定本机服务提示;无安装、启动、停止或删除基础设施的分支。
|
||||
- API 子进程只接收公开禁用态测试夹具,SIGINT/SIGTERM 只转发给该子进程。
|
||||
- 源码门禁要求 Web 与三个 Server 入口、三份最小权限 systemd 单元和 Nginx Web/API 配置完整。
|
||||
- 当前跟踪文件没有 Dockerfile、Compose、`.dockerignore` 或 Docker 专用脚本;历史文档事实仍可追溯。
|
||||
|
||||
Critical、Important、Minor 均无未关闭问题。
|
||||
|
||||
最终结论:passed
|
||||
|
||||
@@ -19,3 +19,17 @@
|
||||
Critical、Important、Minor 均无未关闭问题。
|
||||
|
||||
最终结论:passed
|
||||
|
||||
## 仅源码部署调整复审
|
||||
|
||||
- 实施计划、TDD RED/GREEN、GitNexus 前置影响、开发后 compare 和回退说明均已写入 GOV-009 档案。
|
||||
- 新增关键函数包含外部基础设施所有权和安全边界中文注释,文件按“源码发布门禁”和“E2E 启动器”稳定职责组织,未过度拆分。
|
||||
- MySQL 仍固定 5.7.42、`utf8mb4`、`utf8mb4_general_ci`、`+08:00`;本次没有连接、探测或读取生产数据库,也没有创建迁移或业务表。
|
||||
- 本机 Redis 只执行 `PING` 与 TCP 可达性检查;RocketMQ 保持禁用,没有创建 Topic、生产或消费消息。
|
||||
- 现行架构、开发规范、流程规范和部署手册只宣称 Ubuntu 源码部署;GOV-006 与早期 GOV-009 Docker 记录保留为历史并明确被取代。
|
||||
- `47d0e0d` 为带 GOV-009 的中文 Conventional Commit,已推送项目专用 Gitea;最终 Review 修复和证据将在验证后以独立中文提交推送。
|
||||
- manifest 保持 `reviewing/unreleased`,本地与远端均不存在 `v0.0.8`,等待用户完成总体架构确认。
|
||||
|
||||
Critical、Important、Minor 均无未关闭问题。
|
||||
|
||||
最终结论:passed
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
- 功能编号:GOV-009
|
||||
- 决策日期:2026-08-13
|
||||
- 状态:设计已确认,待实施
|
||||
- 状态:已实施并通过 Review,等待总体架构确认
|
||||
- 取代范围:GOV-006、GOV-009 中仍有效的 Docker 部署约定
|
||||
|
||||
## 结论
|
||||
|
||||
+30
-30
@@ -54,7 +54,7 @@
|
||||
- Consumes: repository paths and the existing `deploy/systemd/`, `deploy/nginx/`, `web/dist/`, and `server/dist/` conventions.
|
||||
- Produces: root scripts `test:deployment` and `verify:source`; failing tests that define the source-only repository contract before implementation.
|
||||
|
||||
- [ ] **Step 1: Add failing fixture tests for the source verifier**
|
||||
- [x] **Step 1: Add failing fixture tests for the source verifier**
|
||||
|
||||
Create tests that import the not-yet-existing module and define these exact behaviors:
|
||||
|
||||
@@ -96,7 +96,7 @@ test('Nginx 未代理 API 或未指向 Web dist 时会阻断源码发布', async
|
||||
|
||||
The local `createSourceReleaseFixture` helper must create only the minimum paths needed by the verifier: four build outputs, three unit files with distinct `EnvironmentFile`, and one Nginx file. It must accept `omit`, `apiUser`, and `invalidNginx` options so each negative test changes one condition.
|
||||
|
||||
- [ ] **Step 2: Replace Docker assertions in the environment baseline with source-only assertions**
|
||||
- [x] **Step 2: Replace Docker assertions in the environment baseline with source-only assertions**
|
||||
|
||||
Keep env-template and RocketMQ tests unchanged. Replace Compose/Docker tests with explicit active-path assertions:
|
||||
|
||||
@@ -123,7 +123,7 @@ test('活动仓库不再包含 Docker 运行构建或部署入口', async () =>
|
||||
|
||||
Add focused checks that current docs describe external local Redis, Ubuntu 22.04/24.04, Node 22.x, pnpm 10.25.0, immutable releases, health checks, and rollback. Do not scan historical feature archives for the word Docker because those files are intentional evidence.
|
||||
|
||||
- [ ] **Step 3: Point root deployment scripts at the not-yet-existing source verifier**
|
||||
- [x] **Step 3: Point root deployment scripts at the not-yet-existing source verifier**
|
||||
|
||||
Change root scripts to the following contract:
|
||||
|
||||
@@ -135,7 +135,7 @@ Change root scripts to the following contract:
|
||||
|
||||
Remove `check:images` and `verify:docker`.
|
||||
|
||||
- [ ] **Step 4: Run RED tests and record expected failures**
|
||||
- [x] **Step 4: Run RED tests and record expected failures**
|
||||
|
||||
Run:
|
||||
|
||||
@@ -167,11 +167,11 @@ Expected: the deployment test fails because `verify-source-deployment.mjs` does
|
||||
- Consumes: `verifySourceDeployment(repositoryRoot?: string | URL): Promise<void>` inputs and the existing build/deployment paths.
|
||||
- Produces: an importable verifier plus the CLI command `pnpm verify:source`, which exits non-zero on incomplete or unsafe source releases.
|
||||
|
||||
- [ ] **Step 1: Run GitNexus impact before modifying or deleting deployment symbols**
|
||||
- [x] **Step 1: Run GitNexus impact before modifying or deleting deployment symbols**
|
||||
|
||||
Run upstream impact for `assertImmutableImageReferences`, `docker`, and `verifyLongRunningProcess`, including tests. Report direct callers, affected processes, and risk to the user. If risk is HIGH or CRITICAL, stop before editing and ask for confirmation as required by `AGENTS.md`.
|
||||
|
||||
- [ ] **Step 2: Implement the minimal source verifier**
|
||||
- [x] **Step 2: Implement the minimal source verifier**
|
||||
|
||||
Implement these exports in one readable file:
|
||||
|
||||
@@ -206,11 +206,11 @@ The implementation must:
|
||||
- produce errors that identify the missing or invalid file without printing env values;
|
||||
- print `源码发布产物与 systemd/Nginx 配置验证通过` only in direct CLI mode.
|
||||
|
||||
- [ ] **Step 3: Delete the obsolete Docker artifacts**
|
||||
- [x] **Step 3: Delete the obsolete Docker artifacts**
|
||||
|
||||
Delete only the paths listed in this task. Do not delete env templates, systemd units, the production Nginx template, or historical GOV-006/GOV-009 evidence.
|
||||
|
||||
- [ ] **Step 4: Run GREEN deployment tests after creating build outputs**
|
||||
- [x] **Step 4: Run GREEN deployment tests after creating build outputs**
|
||||
|
||||
Run:
|
||||
|
||||
@@ -223,7 +223,7 @@ pnpm verify:source
|
||||
|
||||
Expected: all commands pass; `verify:source` confirms all four build outputs and the deployment templates.
|
||||
|
||||
- [ ] **Step 5: Detect scope, commit, and push the executable deployment change**
|
||||
- [x] **Step 5: Detect scope, commit, and push the executable deployment change**
|
||||
|
||||
Run GitNexus `detect_changes(scope: "all")`. Review that only deployment validation and environment-policy flows are affected, then run:
|
||||
|
||||
@@ -246,11 +246,11 @@ git push origin "$(git branch --show-current)"
|
||||
- Consumes: TCP endpoint `127.0.0.1:6379` and the existing public production API fixture.
|
||||
- Produces: `checkLocalRedis({ host, port, timeoutMs }): Promise<void>` and `runTestApi(): Promise<void>`; direct execution launches only the API process after Redis succeeds.
|
||||
|
||||
- [ ] **Step 1: Run GitNexus upstream impact for launcher symbols**
|
||||
- [x] **Step 1: Run GitNexus upstream impact for launcher symbols**
|
||||
|
||||
Run impact for `forwardSignal` and the `run-test-api.mjs` file, including tests. Report the Playwright web-server dependency and any API health flows before editing. Stop for confirmation only if the graph reports HIGH or CRITICAL risk.
|
||||
|
||||
- [ ] **Step 2: Write failing launcher tests**
|
||||
- [x] **Step 2: Write failing launcher tests**
|
||||
|
||||
Refactor-safe tests must verify behavior rather than depend on Docker availability:
|
||||
|
||||
@@ -275,7 +275,7 @@ test('API 测试启动器不包含 Docker 子进程路径', async () => {
|
||||
|
||||
Use an OS-assigned loopback port for deterministic tests. The user-facing failure message may state the fixed required Redis endpoint even when the injected test port differs.
|
||||
|
||||
- [ ] **Step 3: Run the launcher RED test**
|
||||
- [x] **Step 3: Run the launcher RED test**
|
||||
|
||||
Run:
|
||||
|
||||
@@ -285,7 +285,7 @@ node --test server/tools/run-test-api.test.mjs
|
||||
|
||||
Expected: FAIL because `checkLocalRedis` and guarded direct-execution behavior do not yet exist.
|
||||
|
||||
- [ ] **Step 4: Refactor the launcher without infrastructure fallback**
|
||||
- [x] **Step 4: Refactor the launcher without infrastructure fallback**
|
||||
|
||||
Remove `execFileSync`, container naming, dynamic Redis port publication, ownership flags, and cleanup. Export and use:
|
||||
|
||||
@@ -305,7 +305,7 @@ export async function runTestApi() {
|
||||
|
||||
Guard execution with the existing `process.argv[1]` and `fileURLToPath(import.meta.url)` pattern so tests can import the functions without starting API. Keep `REDIS_PORT: '6379'`; never derive or override it from a container.
|
||||
|
||||
- [ ] **Step 5: Include the new test in the Server test command**
|
||||
- [x] **Step 5: Include the new test in the Server test command**
|
||||
|
||||
Change the Server test script to run both Vitest and the Node launcher test:
|
||||
|
||||
@@ -313,7 +313,7 @@ Change the Server test script to run both Vitest and the Node launcher test:
|
||||
"test": "vitest run && node --test tools/run-test-api.test.mjs"
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Run GREEN and real local Redis checks**
|
||||
- [x] **Step 6: Run GREEN and real local Redis checks**
|
||||
|
||||
Run:
|
||||
|
||||
@@ -326,7 +326,7 @@ pnpm verify:e2e
|
||||
|
||||
Expected: unit tests pass, Redis prints `PONG`, and both Playwright viewports pass using the already-running local Redis. If Redis is unavailable, stop with the new explicit error; do not start or install it.
|
||||
|
||||
- [ ] **Step 7: Detect scope, commit, and push the launcher change**
|
||||
- [x] **Step 7: Detect scope, commit, and push the launcher change**
|
||||
|
||||
Run GitNexus `detect_changes(scope: "all")`, confirm the impact is limited to Playwright/API startup, then run:
|
||||
|
||||
@@ -364,7 +364,7 @@ git push origin "$(git branch --show-current)"
|
||||
- Consumes: the confirmed `source-only-deployment-design.md` decision and actual Task 2/3 behavior.
|
||||
- Produces: one unambiguous current deployment policy with intact historical evidence and a traceable GOV-009 record.
|
||||
|
||||
- [ ] **Step 1: Update current public docs and architecture**
|
||||
- [x] **Step 1: Update current public docs and architecture**
|
||||
|
||||
Make these statements exact and consistent:
|
||||
|
||||
@@ -377,7 +377,7 @@ Make these statements exact and consistent:
|
||||
|
||||
Remove the active Docker deployment link from `README.md` and `docs/index.md`.
|
||||
|
||||
- [ ] **Step 2: Update mandatory engineering and workflow rules**
|
||||
- [x] **Step 2: Update mandatory engineering and workflow rules**
|
||||
|
||||
In code standards, replace the dual-deployment variable rule with:
|
||||
|
||||
@@ -387,7 +387,7 @@ In code standards, replace the dual-deployment variable rule with:
|
||||
|
||||
Replace `开发、测试、Docker 和生产环境` with `开发、测试和生产环境`. In workflow rules, require env/systemd/Nginx synchronization and immutable release-directory rollback; remove Compose/image language. State that `verify:release` is the source-release gate and that unavailable external infrastructure is a failed prerequisite, never a container fallback.
|
||||
|
||||
- [ ] **Step 3: Update GOV-009 current records without falsifying history**
|
||||
- [x] **Step 3: Update GOV-009 current records without falsifying history**
|
||||
|
||||
Revise PRD scope, R7, design configuration/deployment sections, automated test plan, current release notes, rollback, and architecture review to match actual source-only implementation. Add `source_only_deployment_implementation_plan` to `manifest.yaml`. Keep `status: reviewing`, `release: unreleased`, and the architecture confirmation completion gate.
|
||||
|
||||
@@ -395,11 +395,11 @@ In `qa/test-results.md`, preserve dated Docker validation as historical fact and
|
||||
|
||||
If GOV-006's manifest presents its Docker approach as current, add only a dated `superseded_by` pointer to the GOV-009 source-only decision; do not rewrite its original PRD/design/test evidence.
|
||||
|
||||
- [ ] **Step 4: Add the unreleased changelog decision**
|
||||
- [x] **Step 4: Add the unreleased changelog decision**
|
||||
|
||||
At the top current section, record that the project removed Docker/Compose/image validation and now supports only Ubuntu source deployment with external infrastructure. Leave older entries about when Docker was added unchanged below it.
|
||||
|
||||
- [ ] **Step 5: Run active-document policy tests and scan for contradictions**
|
||||
- [x] **Step 5: Run active-document policy tests and scan for contradictions**
|
||||
|
||||
Run:
|
||||
|
||||
@@ -410,7 +410,7 @@ rg -n '双部署|同时支持 Docker|Compose 只|Docker Compose 生产|verify:do
|
||||
|
||||
Expected: tests pass. Search results may remain only in explicitly dated historical results or supersession explanations; no current instruction may expose a Docker command or claim Docker support.
|
||||
|
||||
- [ ] **Step 6: Detect scope, commit, and push documentation alignment**
|
||||
- [x] **Step 6: Detect scope, commit, and push documentation alignment**
|
||||
|
||||
Run GitNexus `detect_changes(scope: "all")`, then:
|
||||
|
||||
@@ -437,7 +437,7 @@ git push origin "$(git branch --show-current)"
|
||||
- Consumes: the completed implementation, root verification scripts, GitNexus graph, and Review standards.
|
||||
- Produces: final evidence for the deployment-policy adjustment while GOV-009 remains `reviewing/unreleased` pending user architecture confirmation.
|
||||
|
||||
- [ ] **Step 1: Run focused tests and full source release verification**
|
||||
- [x] **Step 1: Run focused tests and full source release verification**
|
||||
|
||||
Run without Docker:
|
||||
|
||||
@@ -450,11 +450,11 @@ pnpm verify:release
|
||||
|
||||
Expected: all pass. `verify:release` must execute the full root verification, desktop/mobile Playwright checks, builds, and `verify:source`; it must not invoke Docker.
|
||||
|
||||
- [ ] **Step 2: Perform visual verification at both configured viewports**
|
||||
- [x] **Step 2: Perform visual verification at both configured viewports**
|
||||
|
||||
Use Playwright/browser screenshots at 1440x900 and 390x844. Confirm the page is nonblank, API health data renders, no content overlaps, and browser console/network contains no blocking error. Save screenshots under the existing ignored/output convention and record results, not binary artifacts, in `qa/test-results.md`.
|
||||
|
||||
- [ ] **Step 3: Refresh GitNexus and record before/after evidence**
|
||||
- [x] **Step 3: Refresh GitNexus and record before/after evidence**
|
||||
|
||||
Run:
|
||||
|
||||
@@ -466,7 +466,7 @@ npm run governance:finish -- GOV-009 application-scaffold-baseline
|
||||
|
||||
Then use GitNexus `detect_changes(scope: "compare", base_ref: "cfcd7f13d9a6a35173d01bd8ca1458911190e70f")`. Record node/edge/flow counts, removed Docker verifier symbols, added source verifier symbols, and affected processes in the three GitNexus records. Do not commit `.gitnexus/`.
|
||||
|
||||
- [ ] **Step 4: Conduct code Review**
|
||||
- [x] **Step 4: Conduct code Review**
|
||||
|
||||
Review for functional regressions, release-gate bypasses, unsafe process spawning, Redis failure semantics, missing build artifacts, and test gaps. Resolve every blocking finding, rerun affected checks, and finish `review/code-review.md` with the exact line:
|
||||
|
||||
@@ -474,7 +474,7 @@ Review for functional regressions, release-gate bypasses, unsafe process spawnin
|
||||
最终结论:passed
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Conduct development-standards Review**
|
||||
- [x] **Step 5: Conduct development-standards Review**
|
||||
|
||||
Review source-only policy consistency, Chinese comments for non-obvious logic, file responsibility, no secrets, MySQL 5.7 constraints, no production access, historical traceability, Chinese commits, Gitea push state, and the absence of a `v0.0.8` tag. Finish `review/standards-review.md` with the exact line:
|
||||
|
||||
@@ -482,7 +482,7 @@ Review source-only policy consistency, Chinese comments for non-obvious logic, f
|
||||
最终结论:passed
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Re-run final verification after Review edits**
|
||||
- [x] **Step 6: Re-run final verification after Review edits**
|
||||
|
||||
Run:
|
||||
|
||||
@@ -494,7 +494,7 @@ git status --short
|
||||
|
||||
Expected: formatting and release verification pass. Only intended Review/evidence files remain uncommitted.
|
||||
|
||||
- [ ] **Step 7: Detect final scope, commit, and push evidence**
|
||||
- [x] **Step 7: Detect final scope, commit, and push evidence**
|
||||
|
||||
Run GitNexus `detect_changes(scope: "all")`, verify no unexpected application flow changed, then:
|
||||
|
||||
@@ -504,7 +504,7 @@ git commit -m "docs(GOV-009): 封存仅源码部署复核证据"
|
||||
git push origin "$(git branch --show-current)"
|
||||
```
|
||||
|
||||
- [ ] **Step 8: Confirm remote consistency without releasing**
|
||||
- [x] **Step 8: Confirm remote consistency without releasing**
|
||||
|
||||
Run:
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { access, readFile } from 'node:fs/promises';
|
||||
import { access, readFile, readdir } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
@@ -32,6 +32,16 @@ const serverProcesses = Object.freeze([
|
||||
['worker', 'Worker'],
|
||||
]);
|
||||
|
||||
const ignoredScanDirectories = new Set([
|
||||
'.git',
|
||||
'.gitnexus',
|
||||
'.local',
|
||||
'dist',
|
||||
'node_modules',
|
||||
'playwright-report',
|
||||
'test-results',
|
||||
]);
|
||||
|
||||
function resolveRoot(repositoryRoot) {
|
||||
return repositoryRoot instanceof URL
|
||||
? fileURLToPath(repositoryRoot)
|
||||
@@ -54,6 +64,34 @@ async function assertDockerArtifactsAbsent(repositoryRoot) {
|
||||
throw new Error(`禁止存在 Docker 活动文件:${relativePath}`);
|
||||
}
|
||||
}
|
||||
|
||||
const pendingDirectories = [repositoryRoot];
|
||||
while (pendingDirectories.length > 0) {
|
||||
const currentDirectory = pendingDirectories.pop();
|
||||
const entries = await readdir(currentDirectory, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory() && ignoredScanDirectories.has(entry.name)) continue;
|
||||
const absolutePath = path.join(currentDirectory, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
pendingDirectories.push(absolutePath);
|
||||
continue;
|
||||
}
|
||||
if (!entry.isFile()) continue;
|
||||
|
||||
const relativePath = path.relative(repositoryRoot, absolutePath).split(path.sep).join('/');
|
||||
const segments = relativePath.split('/');
|
||||
const fileName = segments.at(-1);
|
||||
const isDockerfile = /^Dockerfile(?:\..+)?$/i.test(fileName);
|
||||
const isDockerIgnore = fileName === '.dockerignore';
|
||||
const isDockerCompose = /^docker-compose.*\.ya?ml$/i.test(fileName);
|
||||
const isComposeYaml = segments.includes('compose') && /\.ya?ml$/i.test(fileName);
|
||||
|
||||
if (isDockerfile || isDockerIgnore || isDockerCompose || isComposeYaml) {
|
||||
throw new Error(`禁止存在 Docker 活动文件:${relativePath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function assertBuildOutputsPresent(repositoryRoot) {
|
||||
|
||||
@@ -81,6 +81,20 @@ test('任一 Docker 活动文件会阻断源码发布', async () => {
|
||||
await assert.rejects(() => verifySourceDeployment(root), /禁止存在 Docker 活动文件.*Dockerfile/);
|
||||
});
|
||||
|
||||
test('未预先列举的 Dockerfile 和 Compose 文件仍会阻断源码发布', async () => {
|
||||
for (const relativePath of ['ops/Dockerfile', 'deploy/compose/extra.yml']) {
|
||||
const root = await createSourceReleaseFixture();
|
||||
const absolutePath = path.join(root, relativePath);
|
||||
await mkdir(path.dirname(absolutePath), { recursive: true });
|
||||
await writeFile(absolutePath, 'services: {}\n');
|
||||
|
||||
await assert.rejects(
|
||||
() => verifySourceDeployment(root),
|
||||
new RegExp(`禁止存在 Docker 活动文件.*${relativePath.replace('/', '\\/')}`),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('Server 构建入口缺失会阻断源码发布', async () => {
|
||||
const root = await createSourceReleaseFixture({ omit: 'server/dist/apps/worker/main.js' });
|
||||
|
||||
|
||||
@@ -169,6 +169,16 @@ test('部署文档要求本机外部 Redis 和唯一 Ubuntu 源码生产路径',
|
||||
assert.match(source, /pnpm verify:release/);
|
||||
assert.match(source, /\/opt\/a-share-analysis\/releases\//);
|
||||
assert.match(source, /\/opt\/a-share-analysis\/current/);
|
||||
for (const processName of ['api', 'scheduler', 'worker']) {
|
||||
assert.match(
|
||||
source,
|
||||
new RegExp(
|
||||
`install -m 0644 deploy/systemd/a-share-${processName}\\.service\\.example /etc/systemd/system/a-share-${processName}\\.service`,
|
||||
),
|
||||
);
|
||||
assert.match(source, new RegExp(`systemctl restart a-share-${processName}\\.service`));
|
||||
}
|
||||
assert.doesNotMatch(source, /systemctl (?:restart|status) a-share-\w+\.service\.example/);
|
||||
assert.match(source, /不负责安装/);
|
||||
for (const document of [local, source]) {
|
||||
assert.match(document, /MySQL 5\.7\.42/);
|
||||
|
||||
Reference in New Issue
Block a user