加固既有生产部署流程(07-27-yang-jun-reimbursement-readiness)

这个提交包含在:
2026-08-01 18:25:20 +08:00
父节点 5dac336fbf
当前提交 07de198b51
共修改 15 个文件,包含 375 行新增和 34 行删除
+61 -1
查看文件
@@ -7,7 +7,7 @@ operations require explicit approval and evidence.
## Rules
- Use `SYNC_ENV=0 POSTGRES_DATA_DIR=<absolute> STORAGE_HOST_DIR=<absolute> DEPLOY_DATA_MODE=<existing|initialize> bash deploy/trialrun/deploy.sh` only when deployment is approved; do not overwrite remote `.env`.
- Existing installations use `DEPLOY_SERVER=<ssh-target> bash deploy/trialrun/deploy-existing.sh` only when deployment is approved; the wrapper reads the frozen allowlisted contract and keeps `SYNC_ENV=0`. First initialization or controlled recovery without that unit uses `deploy.sh` with explicit absolute data paths and `DEPLOY_DATA_MODE`; neither path overwrites remote `.env` by default.
- When `server/src/config.js` reads a new environment key, add the same key to
`deploy/trialrun/.env.example` before deployment; `deploy/trialrun/deploy.sh`
runs `node deploy/trialrun/validate-env-contract.js` at step 0 and must fail
@@ -1282,3 +1282,63 @@ bash scripts/qa/run-automatic-backup-contract.sh
<explicit-controlled-paths> \
bash deploy/trialrun/install-offhost-app-health-monitor.sh install
```
## Scenario: Existing Deployment Preflight And Cache Stability
### 1. Scope / Trigger
- Trigger: deploying a new published commit onto an existing single-host trialrun installation.
- Purpose: prevent a wrong repository-root interpretation from reaching `rsync --delete`, and prevent per-commit build identity from invalidating stable dependency layers.
### 2. Signatures
- Existing deployment entry: `DEPLOY_SERVER=<ssh-target> bash deploy/trialrun/deploy-existing.sh`.
- Remote preflight: `deploy/trialrun/preflight-remote.sh` executed over SSH before rsync.
- Canonical parameter source: allowlisted `Environment=` values from `hyb-oa-automatic-backup-daily.service`.
- Stable image stages: `base`, `client_deps`, `client_build`, `server_deps`, `server_build`.
### 3. Contracts
- Never derive `REMOTE_DIR` from Compose `com.docker.compose.project.working_dir`; it may name the Compose-file directory rather than the repository root.
- The existing-deployment wrapper reads only `REMOTE_DIR`, `REMOTE_ENV_FILE`, `COMPOSE_FILE`, `COMPOSE_PROJECT_NAME`, `POSTGRES_DATA_DIR` and `STORAGE_HOST_DIR`; it does not echo their values.
- Before `mkdir` or rsync, existing mode requires repository markers, `PG_VERSION`, storage directory and a regular non-symlink env file when `SYNC_ENV=0`.
- `apk add` and both lockfile `npm ci` steps precede `BUILD_SHA` / `VITE_BUILD_SHA`. Build identity may invalidate application output, never stable dependency installation.
- Seed and smoke output reports readiness, counts and booleans; it does not print full login identifiers, contact values, WeCom identifiers, redirect URI or generated credentials.
### 4. Validation & Error Matrix
- Config directory passed as `REMOTE_DIR` -> preflight fails before rsync.
- Remote env missing or symlinked with `SYNC_ENV=0` -> preflight fails before rsync.
- Existing PGDATA missing `PG_VERSION` or storage missing -> preflight fails before rsync.
- Canonical systemd unit missing an allowlisted value -> wrapper fails without calling `deploy.sh`.
- Lockfile unchanged but a new SHA reruns dependency installation -> Dockerfile contract test fails.
### 5. Good/Base/Bad Cases
- Good: wrapper reads the frozen unit contract, preflight passes, Git archive syncs and unchanged dependency layers are cached.
- Base: first initialization uses reviewed explicit parameters and `DEPLOY_DATA_MODE=initialize`; it does not pretend an existing unit is available.
- Bad: inspect a running container's `working_dir`, append another `deploy/trialrun`, then discover the mistake only after rsync.
### 6. Tests Required
- `bash -n deploy/trialrun/deploy.sh deploy/trialrun/deploy-existing.sh deploy/trialrun/preflight-remote.sh`.
- `node deploy/trialrun/validate-env-contract.js`.
- `cd server && npm test -- tests/unit/scripts/deployment-safety-contract.test.js`.
- Synthetic fixtures must prove wrong root, missing/symlink env and invalid data fail; static ordering must prove preflight precedes rsync and dependency stages precede build args.
### 7. Wrong vs Correct
#### Wrong
```bash
# working_dir may be the Compose config directory, not the repository root.
REMOTE_DIR="$(docker inspect <server> --format '<working_dir-label>')" \
bash deploy/trialrun/deploy.sh
```
#### Correct
```bash
DEPLOY_SERVER=<approved-ssh-target> \
bash deploy/trialrun/deploy-existing.sh
```