# site-deploy — Playbook 驱动的部署管线 `site-deploy/` 是所有站点服务的部署大本营:**一个服务一份 playbook**,脚本读取 playbook 与配置执行 rsync、可选的远程 Docker Compose、健康检查,并可启用 AI 辅助 审查;另含 GitLab 批量克隆工具。 ```{warning} 本工作空间的硬性规则。修改 site-deploy 前**必须先读** `site-deploy/AGENTS.md`: playbook 是事实来源;禁止臆造主机名/路径/凭据;先 dry-run;不提交密钥; 日志 append-only 不可改;一切下载走 `http://172.24.240.1:7897` 代理。 ``` ## 目录布局 ``` site-deploy/ ├── AGENTS.md # 子项目硬性规则(agent 必读) ├── config/ │ ├── hosts.env # SSH 主机 / docker 目标(gitignored,从 .example 复制) │ └── services.yaml # 服务定义(从 .example 复制) ├── playbooks/ # 每服务一份 .md,指令的事实来源 │ ├── _template.md # 新服务从模板派生 │ ├── casdoor.md # Casdoor 生产部署 │ └── auth-proxy.md # sl-entry nginx 反代(手工操作文档) ├── scripts/ │ ├── lib.sh # 共享层:日志、代理、host_var 解析 │ ├── deploy.sh # 部署(rsync + 可选 docker compose + 健康检查) │ ├── validate.sh # 部署前校验(结构检查 + 可选 AI 审查 + dry-run) │ ├── ai.sh # AI 生成/校验辅助 │ └── gitlab.sh # GitLab 批量克隆 repos/ ├── docs/ │ ├── runbook.md # 操作手册(部署、回滚、查日志) │ ├── ai-workflow.md # AI 辅助工作流 │ └── oauth-integration.md# 跨项目 OIDC/PKCE 统一接入指南 └── logs/ # 时间戳部署日志(gitignored,不可改) ``` ## 配置解析约定 - `hosts.env` 变量命名 `HOST__`(脚本用简单文本匹配解析,改名会破坏解析)。 - `services.yaml` 每个服务一个块,常用键:`host`、`source`、`remote`、`docker`、 `healthcheck`、`playbook`(缺省 `.md`)。 - playbook 中 *Deploy steps* / *Post-deploy verification* 里的命令必须**单行、 POSIX sh、可在远程直接执行**——它们会被脚本原样提取运行。 ## 标准工作流 ```bash cp config/hosts.example.env config/hosts.env # 填真实主机 cp config/services.example.yaml config/services.yaml scripts/validate.sh # 1. 校验 scripts/deploy.sh --dry-run # 2. 干跑(默认动作,先看落点) scripts/deploy.sh # 3. 真部署 # 4. 验证:logs/ 下对应日志出现 "deploy complete", # 且 playbook 的 Post-deploy verification 命令通过 ``` 部署步骤(`deploy.sh` 内部):rsync 源目录 → 远端 → 若 `docker: true` 则在远端跑 compose → 执行 playbook 的健康检查 → 可选 AI 审查(`AI_ENABLED=1`,默认 AI 后端 `claude -p`,见 `docs/ai-workflow.md`)。 ## 已知注意事项(历史 bug,已修复,防回退) - `deploy.sh` 的 rsync 实跑与 dry-run 落点必须一致(历史上 `--relative --dirs` 用法不一致)。 - compose v2 没有 `--no-reload` flag,不要加回去。 - `read_yaml_value` 必须剥离值两侧引号,否则 healthcheck 会被当文件名执行。 - `lib.sh` 需尽早 `source` `hosts.env`;变量默认值用 `${VAR-default}`(无冒号), 避免覆盖用户显式设置的空值。