@wdyy/skills 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.well-known/skills/index.json +2 -2
- package/.well-known/skills/wdyy-deployment-standard/SKILL.md +30 -55
- package/.well-known/skills/wdyy-deployment-standard/agents/openai.yaml +2 -2
- package/.well-known/skills/wdyy-deployment-standard/reference/docker-delivery-rules.md +103 -0
- package/.well-known/skills/wdyy-deployment-standard/scripts/generate-deployment-files.mjs +140 -153
- package/.well-known/skills/wdyy-deployment-standard/scripts/generate-deployment-files.test.mjs +97 -85
- package/.well-known/skills/wdyy-deployment-standard/scripts/validate-deployment-package.mjs +102 -174
- package/.well-known/skills/wdyy-deployment-standard/scripts/validate-deployment-package.test.mjs +203 -455
- package/.well-known/skills/wdyy-deployment-standard/templates/{Dockerfile.template → backend.Dockerfile.template} +5 -9
- package/.well-known/skills/wdyy-deployment-standard/templates/deploy.sh.template +207 -647
- package/.well-known/skills/wdyy-deployment-standard/templates/docker-compose.yml +33 -0
- package/.well-known/skills/wdyy-deployment-standard/templates/dockerignore.template +1 -1
- package/.well-known/skills/wdyy-deployment-standard/templates/env.example.template +0 -24
- package/.well-known/skills/wdyy-deployment-standard/templates/frontend-container.conf.template +2 -8
- package/.well-known/skills/wdyy-deployment-standard/templates/frontend.Dockerfile.template +9 -4
- package/.well-known/skills/wdyy-logging-standard/SKILL.md +2 -2
- package/.well-known/skills/wdyy-logging-standard/agents/openai.yaml +1 -1
- package/.well-known/skills/wdyy-logging-standard/reference/logging-rules.md +2 -2
- package/.well-known/skills/wdyy-logging-standard/scripts/validate-log-entry.test.mjs +1 -1
- package/README.md +4 -2
- package/lib/wdyy-cli.js +4 -2
- package/package.json +1 -1
- package/.well-known/skills/wdyy-deployment-standard/reference/linux-deployment-rules.md +0 -127
- package/.well-known/skills/wdyy-deployment-standard/templates/docker-compose.blue-green.yml +0 -70
- package/.well-known/skills/wdyy-deployment-standard/templates/nginx-upstream.template.conf +0 -25
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
services:
|
|
2
|
+
frontend:
|
|
3
|
+
image: "${PROJECT_NAME:?PROJECT_NAME is required}_frontend:latest"
|
|
4
|
+
env_file: ./.env
|
|
5
|
+
environment:
|
|
6
|
+
NGINX_ENVSUBST_FILTER: "^(FRONTEND_URL|FRONTEND_PORT)$"
|
|
7
|
+
ports:
|
|
8
|
+
- "${DOCKER_BIND_IP}:${FRONTEND_PORT}:${FRONTEND_PORT}"
|
|
9
|
+
volumes:
|
|
10
|
+
- ./logs:/app/logs
|
|
11
|
+
restart: unless-stopped
|
|
12
|
+
healthcheck:
|
|
13
|
+
test: ["CMD", "nginx", "-t"]
|
|
14
|
+
interval: 10s
|
|
15
|
+
timeout: 3s
|
|
16
|
+
retries: 6
|
|
17
|
+
|
|
18
|
+
backend:
|
|
19
|
+
image: "${PROJECT_NAME:?PROJECT_NAME is required}_backend:latest"
|
|
20
|
+
env_file: ./.env
|
|
21
|
+
environment:
|
|
22
|
+
HOST: "${BACKEND_URL}"
|
|
23
|
+
PORT: "${BACKEND_PORT}"
|
|
24
|
+
ports:
|
|
25
|
+
- "${DOCKER_BIND_IP}:${BACKEND_PORT}:${BACKEND_PORT}"
|
|
26
|
+
volumes:
|
|
27
|
+
- ./logs:/app/logs
|
|
28
|
+
restart: unless-stopped
|
|
29
|
+
healthcheck:
|
|
30
|
+
test: ["CMD-SHELL", "node -e \"const http=require('http');const r=http.get({host:'127.0.0.1',port:process.env.BACKEND_PORT,path:'/health'},x=>process.exit(x.statusCode===200?0:1));r.on('error',()=>process.exit(1));r.setTimeout(2500,()=>{r.destroy();process.exit(1)})\""]
|
|
31
|
+
interval: 10s
|
|
32
|
+
timeout: 3s
|
|
33
|
+
retries: 6
|
|
@@ -1,28 +1,4 @@
|
|
|
1
|
-
# 前端
|
|
2
|
-
FRONTEND_URL=0.0.0.0
|
|
3
|
-
FRONTEND_PORT=5173
|
|
4
|
-
|
|
5
|
-
# 后端
|
|
6
|
-
BACKEND_URL=0.0.0.0
|
|
7
|
-
BACKEND_PORT=3000
|
|
8
|
-
|
|
9
|
-
# 数据库
|
|
10
|
-
DB_URL=
|
|
11
|
-
DB_PORT=5432
|
|
12
|
-
DB_USER=
|
|
13
|
-
DB_PASSWORD=
|
|
14
|
-
DB_NAME=
|
|
15
|
-
DB_SCHEMA=
|
|
16
|
-
|
|
17
|
-
# API
|
|
18
|
-
|
|
19
|
-
# 部署
|
|
20
1
|
PROJECT_NAME=
|
|
21
|
-
PROJECT_HTTP_PORT=
|
|
22
2
|
DOCKER_BIND_IP=
|
|
23
|
-
FRONTEND_BLUE_PORT=
|
|
24
|
-
FRONTEND_GREEN_PORT=
|
|
25
|
-
BACKEND_BLUE_PORT=
|
|
26
|
-
BACKEND_GREEN_PORT=
|
|
27
3
|
FRONTEND_BASE_IMAGE=nginx:stable
|
|
28
4
|
BACKEND_BASE_IMAGE=node:24-alpine3.24
|
package/.well-known/skills/wdyy-deployment-standard/templates/frontend-container.conf.template
CHANGED
|
@@ -3,8 +3,8 @@ server {
|
|
|
3
3
|
server_name _;
|
|
4
4
|
root /usr/share/nginx/html;
|
|
5
5
|
index index.html;
|
|
6
|
-
access_log /app/logs/frontend
|
|
7
|
-
error_log /app/logs/frontend
|
|
6
|
+
access_log /app/logs/frontend-access.log;
|
|
7
|
+
error_log /app/logs/frontend-error.log warn;
|
|
8
8
|
|
|
9
9
|
location = /health {
|
|
10
10
|
access_log off;
|
|
@@ -12,12 +12,6 @@ server {
|
|
|
12
12
|
return 200 'ok';
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
location = /version {
|
|
16
|
-
access_log off;
|
|
17
|
-
default_type text/plain;
|
|
18
|
-
return 200 '${RELEASE_VERSION}';
|
|
19
|
-
}
|
|
20
|
-
|
|
21
15
|
location / {
|
|
22
16
|
try_files $uri $uri/ /index.html;
|
|
23
17
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
ARG BACKEND_BASE_IMAGE
|
|
1
2
|
ARG FRONTEND_BASE_IMAGE
|
|
3
|
+
FROM ${BACKEND_BASE_IMAGE} AS build
|
|
4
|
+
WORKDIR /app
|
|
5
|
+
COPY . .
|
|
6
|
+
RUN corepack enable && pnpm install --frozen-lockfile
|
|
7
|
+
RUN pnpm --dir src/frontend build
|
|
8
|
+
|
|
2
9
|
FROM ${FRONTEND_BASE_IMAGE}
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
LABEL org.opencontainers.image.version=${RELEASE_VERSION}
|
|
6
|
-
COPY src/frontend/dist/ /usr/share/nginx/html/
|
|
10
|
+
LABEL org.opencontainers.image.title="wdyy-frontend"
|
|
11
|
+
COPY --from=build /app/src/frontend/dist/ /usr/share/nginx/html/
|
|
7
12
|
COPY scripts/deployment/frontend-container.conf.template /etc/nginx/templates/default.conf.template
|
|
@@ -19,7 +19,7 @@ description: 为 NestJS 和 Vue 项目实现仅写入项目根目录 ./logs 的
|
|
|
19
19
|
|
|
20
20
|
## 输入与输出
|
|
21
21
|
|
|
22
|
-
-
|
|
22
|
+
- 输入:服务名、进程实例标识、环境和请求上下文;应用从项目根目录启动。
|
|
23
23
|
- 输出:统一 logger、前端异常上报客户端、HTTP 日志中间件、日志文件命名规则和日志验证结果。
|
|
24
24
|
- 使用 [日志规则](reference/logging-rules.md) 和 [logger 模板](templates/logger.template.ts)。
|
|
25
25
|
|
|
@@ -37,7 +37,7 @@ description: 为 NestJS 和 Vue 项目实现仅写入项目根目录 ./logs 的
|
|
|
37
37
|
|
|
38
38
|
- 不得将 `message` 仅限制为 `success` 或 `error`。
|
|
39
39
|
- 不得用 console 输出替代业务日志。
|
|
40
|
-
- 不得将日志写入项目根目录 `./logs`
|
|
40
|
+
- 不得将日志写入项目根目录 `./logs` 之外,或按服务、实例、日期等维度创建日志子目录。
|
|
41
41
|
|
|
42
42
|
## Red Flags
|
|
43
43
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
|
-
display_name: "
|
|
2
|
+
display_name: "wdyy-logging-standard"
|
|
3
3
|
short_description: "Write full-context logs only to project-root ./logs"
|
|
4
4
|
default_prompt: "Use $wdyy-logging-standard to implement full-context structured logs that write only to project-root ./logs."
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
- 日志为一行 JSON,最小字段见 `logger.template.ts`。
|
|
4
4
|
- `logger.template.ts` 必须可在未安装 `@types/node` 的项目中独立类型检查;读取环境变量时通过 `globalThis` 声明最小运行时形状,不直接依赖 Node.js 全局类型。
|
|
5
5
|
- `timestamp` 使用服务器本地时间 `YYYY-MM-DD HH:mm:ss`,精确到秒;不得包含毫秒、`T` 或 `Z`。
|
|
6
|
-
- 应用必须从项目根目录启动,只允许创建项目根目录 `./logs`,并将文件直接写入该目录;不得读取 `LOG_DIR`、`HOST_LOG_DIR`
|
|
6
|
+
- 应用必须从项目根目录启动,只允许创建项目根目录 `./logs`,并将文件直接写入该目录;不得读取 `LOG_DIR`、`HOST_LOG_DIR` 或其他目录配置,不得创建服务、实例、日期或其他日志子目录。
|
|
7
7
|
- 文件名使用服务器本地时间 `yyyy-mm-dd_hh24-mm-ss.log`。使用排他创建;同一秒内文件名冲突时依次尝试 `yyyy-mm-dd_hh24-mm-ss_1.log`、`yyyy-mm-dd_hh24-mm-ss_2.log`,不得先检查后覆盖写入。最新日志文件大于 2MB 时在同一 `./logs` 中创建新文件,既有日志文件不得移动、重命名或覆盖。
|
|
8
8
|
- 日志仅记录关键业务事件、请求和异常;`params`、`query`、`body` 和 `response` 均保留完整原始值,不执行脱敏、数组截断或大对象裁剪。授权请求可记录实际用户、模式、表和权限等入参。
|
|
9
9
|
- HTTP 日志必须保留 `statusCode`。服务端成功返回时 `result` 为 `success`;失败返回时 `result` 为 `failure`,并在 `response` 中保留完整失败内容。100–399 为成功,400–599 为失败。
|
|
10
10
|
- HTTP 入口和内部服务调用必须透传 traceId。
|
|
11
|
-
- 每条日志必须包含 `instanceId
|
|
11
|
+
- 每条日志必须包含 `instanceId`;所有进程共享同一 `./logs`,通过排他创建和同秒递增后缀避免覆盖。
|
|
12
12
|
- Vue 未处理异常和 Promise 拒绝必须上报后端;后端校验请求身份后写入统一日志。
|
|
13
13
|
- 容器必须将宿主机项目根目录 `./logs` 挂载到应用根目录 `/app/logs`,替换容器不得删除历史日志。
|
|
@@ -83,7 +83,7 @@ test('2MB 轮转阈值使用同一 logs 目录的下一个候选路径', () => {
|
|
|
83
83
|
assert.equal(createLogFilePath(date, 3), './logs/2026-07-28_09-05-03_3.log');
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
test('
|
|
86
|
+
test('多进程日志必须包含 instanceId', async () => {
|
|
87
87
|
const result = await validate({
|
|
88
88
|
timestamp: '2026-07-09 08:00:00',
|
|
89
89
|
level: 'info',
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ OpenSpec 单项变更的需求、设计、任务、实
|
|
|
18
18
|
| `wdyy-api-standard` | 根据“获取XX数据”“使用XX接口”等需求定位接口 reference,并按已确认契约写入调用方式。 |
|
|
19
19
|
| `wdyy-bug-record` | 手动汇总当前任务已解决的问题,并按模板追加至 `docs/bug_record.md`。 |
|
|
20
20
|
| `wdyy-logging-standard` | 结构化日志、敏感字段移除、traceId、前端异常上报与日志轮转。 |
|
|
21
|
-
| `wdyy-deployment-standard` |
|
|
21
|
+
| `wdyy-deployment-standard` | 使用本地基础镜像构建前后端独立镜像,分别导出并统一压缩交付,远程数据库直连,服务器一键部署整个项目栈。 |
|
|
22
22
|
|
|
23
23
|
## 使用方式
|
|
24
24
|
|
|
@@ -43,7 +43,9 @@ wdyy update-skill --all
|
|
|
43
43
|
|
|
44
44
|
`wdyy update-skill <skill-name>` 只接受 5 个受管理的 `wdyy-*` Skill,且仅替换系统用户目录 `.agents/skills/` 中的指定目录;`--all` 替换全部 5 个受管理 Skill。两种方式都不会写入调用项目的 `AGENTS.md`、`AGENTS_new.md`、`docs/bug_record.md` 或 `.agents/skills/`,也不会执行 `openspec init`。首次初始化或需要重新生成项目规则时,使用 `wdyy init`。
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
部署 Skill 生成的标准流程为:在本地项目根目录执行 `./deploy.sh build`,只使用本地已有的 Node、Nginx 基础镜像构建 `<项目名>_frontend:latest` 与 `<项目名>_backend:latest`,分别导出两个镜像 tar,并统一封装为 `deploy/<项目名>-docker.tar.gz`。工程师人工上传并解压该压缩包,服务器无参数执行 `./deploy.sh` 即校验、加载并整体部署前后端;另可执行 `./deploy.sh stop` 和 `./deploy.sh status`。数据库通过 `.env` 直连远程 PostgreSQL,不生成数据库容器;前后端直接暴露 `.env` 中的宿主机端口,日志直接保存在服务器部署根 `logs/`。
|
|
47
|
+
|
|
48
|
+
中大型变更先使用 `/opsx:explore` 或 `/opsx:propose <change-name>`,在方案确认后使用 `/opsx:apply`;完成验证后使用 `/opsx:archive`。涉及数据库、内部 API、日志、部署时,按 `AGENTS.md` 的路由加载相应企业 Skill。所有 URL、端口和 IP 地址从 `.env` 读取,不得硬编码;所有项目管理的日志直接写入项目根目录 `logs/`;生产部署不使用蓝绿发布。不得提交秘密或生产环境 `.env`。项目完成后创建 `README.md`,说明技术栈、目录结构和安装部署。
|
|
47
49
|
|
|
48
50
|
## 固定技术栈
|
|
49
51
|
|
package/lib/wdyy-cli.js
CHANGED
|
@@ -81,14 +81,16 @@ const generatedAgentsContent = `# 企业开发规则
|
|
|
81
81
|
| PostgreSQL 表、DDL、迁移、数据兼容性 | \`wdyy-database-standard\` |
|
|
82
82
|
| 获取已登记接口数据、使用已登记接口 | \`wdyy-api-standard\` |
|
|
83
83
|
| 汇总当前任务已解决的 BUG、漏洞或运行异常 | 手动调用 \`wdyy-bug-record\`,追加写入 \`docs/bug_record.md\` |
|
|
84
|
-
| 结构化日志、traceId
|
|
85
|
-
|
|
|
84
|
+
| 结构化日志、traceId、完整原始入参、前端异常上报 | \`wdyy-logging-standard\` |
|
|
85
|
+
| 统一 Docker 交付、本地双镜像、远程数据库与整栈一键部署 | \`wdyy-deployment-standard\` |
|
|
86
86
|
|
|
87
87
|
## 通用边界
|
|
88
88
|
|
|
89
89
|
- 项目根目录应提供真实可执行的 \`pnpm dev\`、\`pnpm build\`、\`pnpm test\`、\`pnpm lint\` 命令;\`pnpm dev\` 只负责前后端的启动,不得启动或管理数据库。
|
|
90
90
|
- 代码、配置、迁移、测试与部署文件必须以实际实现为准;不得用模板虚构已实现能力。
|
|
91
91
|
- 所有需求(如数据库变更、流程变更、功能变更、从零开发项目等),必须先使用\`openspec-explore\`技能确认需求,再根据实际情况,使用\`openspec\`的其它技能。
|
|
92
|
+
- 所有项目管理的日志必须直接写入项目根目录 \`logs/\`,不得通过环境变量改写目录或创建服务、实例、日期等日志子目录。
|
|
93
|
+
- 生产部署必须使用 \`wdyy-deployment-standard\`:本地只使用已有基础镜像构建前后端两个独立镜像,分别导出后封装为一个压缩包;数据库直连远程实例且不得使用数据库容器;服务器解压后无参数执行 \`./deploy.sh\`,一次性部署整个前后端项目栈。禁止自动拉取镜像、交互菜单和单独操作一个服务。
|
|
92
94
|
- 不得静默吞错、跳过验证、以兜底逻辑掩盖未决问题。
|
|
93
95
|
`;
|
|
94
96
|
|
package/package.json
CHANGED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
# Linux 部署规则
|
|
2
|
-
|
|
3
|
-
## 目录和受控源文件
|
|
4
|
-
|
|
5
|
-
目标项目必须维护:
|
|
6
|
-
|
|
7
|
-
```text
|
|
8
|
-
deploy.sh
|
|
9
|
-
.dockerignore
|
|
10
|
-
src/frontend/Dockerfile
|
|
11
|
-
src/backend/Dockerfile
|
|
12
|
-
scripts/deployment/docker-compose.blue-green.yml
|
|
13
|
-
scripts/deployment/frontend-container.conf.template
|
|
14
|
-
scripts/deployment/nginx-site.conf
|
|
15
|
-
.env.example
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
这些文件必须由 `scripts/generate-deployment-files.mjs --target <project-root> --write` 按固定映射原子生成,templates 是唯一源。既有差异默认失败,不得静默覆盖;工程师审查并确认后才允许 `--force`。生成后执行 `--check`。build 必须原样复制 deploy.sh、Compose 和 Nginx 模板,不得根据运行顺序产生随机内容;相同输入连续构建时这些配置的 SHA-256 必须一致。
|
|
19
|
-
|
|
20
|
-
## 根 .env
|
|
21
|
-
|
|
22
|
-
根 `.env` 是本地 build、上传包和服务器 Compose 的唯一配置文件。`.env` 与 `.env.example` 固定按“前端、后端、数据库、API、部署”排列;部署生成器保留前四段与已有值,只向两个文件的部署段追加同名空键。`.env.example` 必须直接采用 `templates/env.example.template` 的键、顺序与非敏感默认值。脚本必须按数据解析,不得 `source` 或 `eval`。部署前根 `.env` 至少要求:
|
|
23
|
-
|
|
24
|
-
```dotenv
|
|
25
|
-
FRONTEND_URL=0.0.0.0
|
|
26
|
-
FRONTEND_PORT=5173
|
|
27
|
-
BACKEND_URL=0.0.0.0
|
|
28
|
-
BACKEND_PORT=3000
|
|
29
|
-
DB_URL=
|
|
30
|
-
DB_PORT=5432
|
|
31
|
-
DB_USER=
|
|
32
|
-
DB_PASSWORD=
|
|
33
|
-
DB_NAME=
|
|
34
|
-
DB_SCHEMA=
|
|
35
|
-
PROJECT_NAME=example_project
|
|
36
|
-
PROJECT_HTTP_PORT=9099
|
|
37
|
-
DOCKER_BIND_IP=127.0.0.1
|
|
38
|
-
FRONTEND_BLUE_PORT=19091
|
|
39
|
-
FRONTEND_GREEN_PORT=19092
|
|
40
|
-
BACKEND_BLUE_PORT=19093
|
|
41
|
-
BACKEND_GREEN_PORT=19094
|
|
42
|
-
FRONTEND_BASE_IMAGE=nginx:stable
|
|
43
|
-
BACKEND_BASE_IMAGE=node:24-alpine3.24
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
`FRONTEND_URL`、`FRONTEND_PORT`、`BACKEND_URL`、`BACKEND_PORT` 是应用监听的唯一来源;容器、蓝绿和项目入口的健康/版本 URL 必须由对应主机、端口与固定路径确定性构造。不得增加 `FRONTEND_CONTAINER_PORT`、`BACKEND_CONTAINER_PORT`、`BACKEND_LISTEN_HOST`、`*_HEALTH_URL` 或 `*_VERSION_URL`。通配监听地址 `0.0.0.0` 仅在主动本机探测时转换为 `127.0.0.1`。
|
|
47
|
-
|
|
48
|
-
部署示例值只说明字段,生成目标项目后必须由工程师确认 `.env` 实际值,不得保留占位符或示例部署端口。`PROJECT_NAME` 只允许 `^[a-z][a-z0-9_]*$`。所有宿主机端口必须互不相同且在 1–65535;两个基础镜像必须是非空 Docker 镜像引用,可使用本地带标签镜像。相同标签在不同时间重新构建时可能解析为不同基础镜像内容;成功构建后导出的项目成品镜像仍用于服务器端确定部署。数据库连接键允许为空,但项目使用数据库时必须填写真实值。
|
|
49
|
-
|
|
50
|
-
`.env` 权限必须为 `0600` 或只读的 `0400`。部署脚本只把明确的部署键载入自身环境;数据库密码、JWT 等其他应用键保留在文件中供 Compose 注入容器,不得改变脚本的 `PATH`、Shell 选项或命令行为。
|
|
51
|
-
|
|
52
|
-
可选路径键为 `FRONTEND_DOCKERFILE`、`BACKEND_DOCKERFILE`、`DEPLOY_CONFIG_DIR`;未设置时只能使用与目标项目真实结构一致且已验证的标准路径。
|
|
53
|
-
|
|
54
|
-
## Docker 与日志
|
|
55
|
-
|
|
56
|
-
- 前端镜像:`${PROJECT_NAME}_frontend:${RELEASE_VERSION}`。
|
|
57
|
-
- 后端镜像:`${PROJECT_NAME}_backend:${RELEASE_VERSION}`。
|
|
58
|
-
- 四个服务由同一个 `docker compose --project-name "$PROJECT_NAME"` 管理,不设置 `container_name`。
|
|
59
|
-
- 四个服务都使用 `../../.env`,复用 `FRONTEND_PORT`、`BACKEND_PORT`、`FRONTEND_URL`、`BACKEND_URL`,并且只有 `../../logs:/app/logs` 一个日志挂载。
|
|
60
|
-
- 前端 Nginx 容器的 access/error 文件直接写入 `/app/logs/frontend-<color>-*.log`;不得创建子目录。
|
|
61
|
-
- 后端必须把自身日志直接写入 `/app/logs`,不得依赖容器可写层保存持久日志。
|
|
62
|
-
- `.dockerignore` 必须排除 `.env`、`.env.*`、密钥、凭据、deploy、logs、Git、依赖缓存和虚拟环境。
|
|
63
|
-
|
|
64
|
-
## 发布账本与本地包
|
|
65
|
-
|
|
66
|
-
`AGENTS.md` 只允许一个固定两列表:
|
|
67
|
-
|
|
68
|
-
```markdown
|
|
69
|
-
## 发布记录
|
|
70
|
-
|
|
71
|
-
| 版本号 | 构建时间 |
|
|
72
|
-
|---|---|
|
|
73
|
-
| 20260808-001 | 2026-08-08 09:30:00 +08:00 |
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
build 使用项目级原子锁,严格验证账本后生成当天下一序号。全部门禁、双镜像、包结构和确定性校验通过后才写账本。失败必须保留原 deploy 和原账本。
|
|
77
|
-
|
|
78
|
-
```text
|
|
79
|
-
deploy/
|
|
80
|
-
├── .env
|
|
81
|
-
├── deploy.sh
|
|
82
|
-
├── release.env
|
|
83
|
-
└── YYYYMMDD-NNN/
|
|
84
|
-
├── frontend-image.tar
|
|
85
|
-
├── backend-image.tar
|
|
86
|
-
├── manifest.sha256
|
|
87
|
-
├── docker/docker-compose.blue-green.yml
|
|
88
|
-
├── nginx/site.conf
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
`release.env` 只包含当前版本。manifest 覆盖版本目录内除自身外的全部普通文件,禁止符号链接、硬链接秘密、绝对路径和 `..`。根 `.env` 可上传,但版本目录与镜像不得包含它。
|
|
92
|
-
|
|
93
|
-
## 服务器部署和 Nginx
|
|
94
|
-
|
|
95
|
-
上传目标由工程师确定;脚本通过自身物理路径确定部署根,不依赖调用者当前目录。
|
|
96
|
-
|
|
97
|
-
共享 Nginx 主配置由运维预先 include `/xxzx/home/*/nginx/site.conf`。项目脚本不得写 `/etc/nginx` 或其他项目,只维护:
|
|
98
|
-
|
|
99
|
-
```text
|
|
100
|
-
<project-root>/nginx/site.conf
|
|
101
|
-
<project-root>/nginx/active-upstreams.conf
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
site 监听 `PROJECT_HTTP_PORT`,并带项目名、外部端口及四个 Docker 宿主机端口标记。首次部署和端口变更必须在共享锁内检查展开的 Nginx 配置、其他标准项目 site 以及运行中容器的实际发布端口;任一外部端口或 blue/green 宿主机端口重复、其他项目缺少端口标记或不能证明唯一时失败。候选 site 与前后端 upstream 一起安装,`nginx -t` 或 reload 失败时恢复旧文件。
|
|
105
|
-
|
|
106
|
-
## 命令
|
|
107
|
-
|
|
108
|
-
- `./deploy.sh start`:只允许无活动状态的首次 blue 部署。
|
|
109
|
-
- `./deploy.sh replace`:只允许已有活动状态且 release.env 指向不同新版本。
|
|
110
|
-
- `./deploy.sh restart`:重新创建并验证当前颜色的两个容器,不改变流量颜色和版本。
|
|
111
|
-
- `./deploy.sh stop`:停止当前颜色的两个容器,保留所有文件和状态。
|
|
112
|
-
- `./deploy.sh remove`:删除 Compose project 下四个容器及网络,并删除两个精确项目镜像仓库的全部标签;保留日志、包、状态和 Nginx 文件。
|
|
113
|
-
- `./deploy.sh status`:报告 active/previous 和四服务状态。
|
|
114
|
-
- `./deploy.sh rollback <version>`:只允许 previous 中已保留且健康的成对容器。
|
|
115
|
-
|
|
116
|
-
除 rollback 的版本外,命令不得接受额外参数。
|
|
117
|
-
|
|
118
|
-
## 数据库
|
|
119
|
-
|
|
120
|
-
部署 Skill 不接受数据库迁移参数,也不打包、校验、提示或执行迁移文件。
|
|
121
|
-
|
|
122
|
-
## 失败边界
|
|
123
|
-
|
|
124
|
-
- 新颜色前后端全部健康且后端版本正确前,不得修改 Nginx 或活动状态。
|
|
125
|
-
- Nginx candidate、全局校验、reload 或状态提交失败时,必须恢复本项目旧配置和旧状态。
|
|
126
|
-
- 不得停止旧颜色掩盖新颜色失败;不得修改、停止或删除其他项目任何资源。
|
|
127
|
-
- `remove` 不得删除 logs、上传版本目录、release.env、状态文件或 Nginx 配置。
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
services:
|
|
2
|
-
frontend-blue:
|
|
3
|
-
image: ${FRONTEND_IMAGE:?FRONTEND_IMAGE is required}
|
|
4
|
-
env_file: ../../.env
|
|
5
|
-
environment:
|
|
6
|
-
INSTANCE_ID: blue
|
|
7
|
-
NGINX_ENVSUBST_FILTER: "^(INSTANCE_ID|FRONTEND_URL|FRONTEND_PORT|RELEASE_VERSION)$"
|
|
8
|
-
ports:
|
|
9
|
-
- "${DOCKER_BIND_IP}:${FRONTEND_BLUE_PORT}:${FRONTEND_PORT}"
|
|
10
|
-
volumes:
|
|
11
|
-
- ../../logs:/app/logs
|
|
12
|
-
restart: unless-stopped
|
|
13
|
-
healthcheck:
|
|
14
|
-
test: ["CMD-SHELL", "probe_host=$${FRONTEND_URL}; [ \"$${probe_host}\" != 0.0.0.0 ] || probe_host=127.0.0.1; wget -qO- \"http://$${probe_host}:$${FRONTEND_PORT}/health\""]
|
|
15
|
-
interval: 10s
|
|
16
|
-
timeout: 3s
|
|
17
|
-
retries: 6
|
|
18
|
-
|
|
19
|
-
backend-blue:
|
|
20
|
-
image: ${BACKEND_IMAGE:?BACKEND_IMAGE is required}
|
|
21
|
-
env_file: ../../.env
|
|
22
|
-
environment:
|
|
23
|
-
INSTANCE_ID: blue
|
|
24
|
-
HOST: ${BACKEND_URL}
|
|
25
|
-
PORT: ${BACKEND_PORT}
|
|
26
|
-
ports:
|
|
27
|
-
- "${DOCKER_BIND_IP}:${BACKEND_BLUE_PORT}:${BACKEND_PORT}"
|
|
28
|
-
volumes:
|
|
29
|
-
- ../../logs:/app/logs
|
|
30
|
-
restart: unless-stopped
|
|
31
|
-
healthcheck:
|
|
32
|
-
test: ["CMD-SHELL", "probe_host=$${BACKEND_URL}; [ \"$${probe_host}\" != 0.0.0.0 ] || probe_host=127.0.0.1; wget -qO- \"http://$${probe_host}:$${BACKEND_PORT}/health\""]
|
|
33
|
-
interval: 10s
|
|
34
|
-
timeout: 3s
|
|
35
|
-
retries: 6
|
|
36
|
-
|
|
37
|
-
frontend-green:
|
|
38
|
-
image: ${FRONTEND_IMAGE:?FRONTEND_IMAGE is required}
|
|
39
|
-
env_file: ../../.env
|
|
40
|
-
environment:
|
|
41
|
-
INSTANCE_ID: green
|
|
42
|
-
NGINX_ENVSUBST_FILTER: "^(INSTANCE_ID|FRONTEND_URL|FRONTEND_PORT|RELEASE_VERSION)$"
|
|
43
|
-
ports:
|
|
44
|
-
- "${DOCKER_BIND_IP}:${FRONTEND_GREEN_PORT}:${FRONTEND_PORT}"
|
|
45
|
-
volumes:
|
|
46
|
-
- ../../logs:/app/logs
|
|
47
|
-
restart: unless-stopped
|
|
48
|
-
healthcheck:
|
|
49
|
-
test: ["CMD-SHELL", "probe_host=$${FRONTEND_URL}; [ \"$${probe_host}\" != 0.0.0.0 ] || probe_host=127.0.0.1; wget -qO- \"http://$${probe_host}:$${FRONTEND_PORT}/health\""]
|
|
50
|
-
interval: 10s
|
|
51
|
-
timeout: 3s
|
|
52
|
-
retries: 6
|
|
53
|
-
|
|
54
|
-
backend-green:
|
|
55
|
-
image: ${BACKEND_IMAGE:?BACKEND_IMAGE is required}
|
|
56
|
-
env_file: ../../.env
|
|
57
|
-
environment:
|
|
58
|
-
INSTANCE_ID: green
|
|
59
|
-
HOST: ${BACKEND_URL}
|
|
60
|
-
PORT: ${BACKEND_PORT}
|
|
61
|
-
ports:
|
|
62
|
-
- "${DOCKER_BIND_IP}:${BACKEND_GREEN_PORT}:${BACKEND_PORT}"
|
|
63
|
-
volumes:
|
|
64
|
-
- ../../logs:/app/logs
|
|
65
|
-
restart: unless-stopped
|
|
66
|
-
healthcheck:
|
|
67
|
-
test: ["CMD-SHELL", "probe_host=$${BACKEND_URL}; [ \"$${probe_host}\" != 0.0.0.0 ] || probe_host=127.0.0.1; wget -qO- \"http://$${probe_host}:$${BACKEND_PORT}/health\""]
|
|
68
|
-
interval: 10s
|
|
69
|
-
timeout: 3s
|
|
70
|
-
retries: 6
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# wdyy-project: __PROJECT_NAME__
|
|
2
|
-
# wdyy-port: __PROJECT_HTTP_PORT__
|
|
3
|
-
include "__DEPLOY_ROOT__/nginx/active-upstreams.conf";
|
|
4
|
-
|
|
5
|
-
server {
|
|
6
|
-
listen __PROJECT_HTTP_PORT__;
|
|
7
|
-
server_name _;
|
|
8
|
-
|
|
9
|
-
location /api/ {
|
|
10
|
-
proxy_pass http://__BACKEND_UPSTREAM_NAME__;
|
|
11
|
-
proxy_set_header Host $host;
|
|
12
|
-
proxy_set_header X-Real-IP $remote_addr;
|
|
13
|
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
14
|
-
proxy_set_header X-Forwarded-Proto $scheme;
|
|
15
|
-
proxy_set_header X-Trace-Id $request_id;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
location / {
|
|
19
|
-
proxy_pass http://__FRONTEND_UPSTREAM_NAME__;
|
|
20
|
-
proxy_set_header Host $host;
|
|
21
|
-
proxy_set_header X-Real-IP $remote_addr;
|
|
22
|
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
23
|
-
proxy_set_header X-Forwarded-Proto $scheme;
|
|
24
|
-
}
|
|
25
|
-
}
|