@wdyy/skills 0.1.6 → 0.1.7
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 +53 -61
- package/.well-known/skills/wdyy-deployment-standard/agents/openai.yaml +3 -3
- package/.well-known/skills/wdyy-deployment-standard/reference/linux-deployment-rules.md +92 -88
- package/.well-known/skills/wdyy-deployment-standard/scripts/generate-deployment-files.mjs +213 -0
- package/.well-known/skills/wdyy-deployment-standard/scripts/generate-deployment-files.test.mjs +106 -0
- package/.well-known/skills/wdyy-deployment-standard/scripts/validate-deployment-package.mjs +168 -147
- package/.well-known/skills/wdyy-deployment-standard/scripts/validate-deployment-package.test.mjs +485 -526
- package/.well-known/skills/wdyy-deployment-standard/templates/Dockerfile.template +10 -8
- package/.well-known/skills/wdyy-deployment-standard/templates/deploy.sh.template +598 -416
- package/.well-known/skills/wdyy-deployment-standard/templates/docker-compose.blue-green.yml +46 -12
- package/.well-known/skills/wdyy-deployment-standard/templates/dockerignore.template +2 -0
- package/.well-known/skills/wdyy-deployment-standard/templates/env.example.template +30 -0
- package/.well-known/skills/wdyy-deployment-standard/templates/frontend-container.conf.template +24 -0
- package/.well-known/skills/wdyy-deployment-standard/templates/frontend.Dockerfile.template +7 -0
- package/.well-known/skills/wdyy-deployment-standard/templates/nginx-upstream.template.conf +17 -18
- package/README.md +2 -2
- package/lib/wdyy-cli.js +35 -9
- package/package.json +1 -1
|
@@ -1,36 +1,70 @@
|
|
|
1
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
|
+
|
|
2
19
|
backend-blue:
|
|
3
|
-
image: ${
|
|
4
|
-
env_file: ../../.env
|
|
20
|
+
image: ${BACKEND_IMAGE:?BACKEND_IMAGE is required}
|
|
21
|
+
env_file: ../../.env
|
|
5
22
|
environment:
|
|
6
23
|
INSTANCE_ID: blue
|
|
7
|
-
HOST: ${
|
|
8
|
-
PORT: ${
|
|
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)$"
|
|
9
43
|
ports:
|
|
10
|
-
- "${
|
|
44
|
+
- "${DOCKER_BIND_IP}:${FRONTEND_GREEN_PORT}:${FRONTEND_PORT}"
|
|
11
45
|
volumes:
|
|
12
46
|
- ../../logs:/app/logs
|
|
13
47
|
restart: unless-stopped
|
|
14
48
|
healthcheck:
|
|
15
|
-
test: ["CMD", "
|
|
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\""]
|
|
16
50
|
interval: 10s
|
|
17
51
|
timeout: 3s
|
|
18
52
|
retries: 6
|
|
19
53
|
|
|
20
54
|
backend-green:
|
|
21
|
-
image: ${
|
|
22
|
-
env_file: ../../.env
|
|
55
|
+
image: ${BACKEND_IMAGE:?BACKEND_IMAGE is required}
|
|
56
|
+
env_file: ../../.env
|
|
23
57
|
environment:
|
|
24
58
|
INSTANCE_ID: green
|
|
25
|
-
HOST: ${
|
|
26
|
-
PORT: ${
|
|
59
|
+
HOST: ${BACKEND_URL}
|
|
60
|
+
PORT: ${BACKEND_PORT}
|
|
27
61
|
ports:
|
|
28
|
-
- "${
|
|
62
|
+
- "${DOCKER_BIND_IP}:${BACKEND_GREEN_PORT}:${BACKEND_PORT}"
|
|
29
63
|
volumes:
|
|
30
64
|
- ../../logs:/app/logs
|
|
31
65
|
restart: unless-stopped
|
|
32
66
|
healthcheck:
|
|
33
|
-
test: ["CMD", "
|
|
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\""]
|
|
34
68
|
interval: 10s
|
|
35
69
|
timeout: 3s
|
|
36
70
|
retries: 6
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
PROJECT_NAME=
|
|
21
|
+
SERVER_PROJECTS_ROOT=
|
|
22
|
+
PROJECT_HTTP_PORT=
|
|
23
|
+
DOCKER_BIND_IP=
|
|
24
|
+
FRONTEND_BLUE_PORT=
|
|
25
|
+
FRONTEND_GREEN_PORT=
|
|
26
|
+
BACKEND_BLUE_PORT=
|
|
27
|
+
BACKEND_GREEN_PORT=
|
|
28
|
+
FRONTEND_BASE_IMAGE=
|
|
29
|
+
BACKEND_BASE_IMAGE=
|
|
30
|
+
DATABASE_MIGRATION_MODE=
|
package/.well-known/skills/wdyy-deployment-standard/templates/frontend-container.conf.template
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
server {
|
|
2
|
+
listen ${FRONTEND_URL}:${FRONTEND_PORT};
|
|
3
|
+
server_name _;
|
|
4
|
+
root /usr/share/nginx/html;
|
|
5
|
+
index index.html;
|
|
6
|
+
access_log /app/logs/frontend-${INSTANCE_ID}-access.log;
|
|
7
|
+
error_log /app/logs/frontend-${INSTANCE_ID}-error.log warn;
|
|
8
|
+
|
|
9
|
+
location = /health {
|
|
10
|
+
access_log off;
|
|
11
|
+
default_type text/plain;
|
|
12
|
+
return 200 'ok';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
location = /version {
|
|
16
|
+
access_log off;
|
|
17
|
+
default_type text/plain;
|
|
18
|
+
return 200 '${RELEASE_VERSION}';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
location / {
|
|
22
|
+
try_files $uri $uri/ /index.html;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ARG FRONTEND_BASE_IMAGE
|
|
2
|
+
FROM ${FRONTEND_BASE_IMAGE}
|
|
3
|
+
ARG RELEASE_VERSION
|
|
4
|
+
ENV RELEASE_VERSION=${RELEASE_VERSION}
|
|
5
|
+
LABEL org.opencontainers.image.version=${RELEASE_VERSION}
|
|
6
|
+
COPY src/frontend/dist/ /usr/share/nginx/html/
|
|
7
|
+
COPY scripts/deployment/frontend-container.conf.template /etc/nginx/templates/default.conf.template
|
|
@@ -1,27 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
# wdyy-project: __PROJECT_NAME__
|
|
2
|
+
# wdyy-port: __PROJECT_HTTP_PORT__
|
|
3
|
+
# wdyy-docker-ports: __DOCKER_HOST_PORTS__
|
|
4
|
+
include "__DEPLOY_ROOT__/nginx/active-upstreams.conf";
|
|
2
5
|
|
|
3
6
|
server {
|
|
7
|
+
listen __PROJECT_HTTP_PORT__;
|
|
8
|
+
server_name _;
|
|
9
|
+
|
|
4
10
|
location /api/ {
|
|
5
|
-
proxy_pass
|
|
11
|
+
proxy_pass http://__BACKEND_UPSTREAM_NAME__;
|
|
12
|
+
proxy_set_header Host $host;
|
|
13
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
14
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
15
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
6
16
|
proxy_set_header X-Trace-Id $request_id;
|
|
7
17
|
}
|
|
8
18
|
|
|
9
|
-
location /releases/ {
|
|
10
|
-
root "__DEPLOY_ROOT__";
|
|
11
|
-
try_files $uri =404;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
19
|
location / {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
root "__DEPLOY_ROOT__/current";
|
|
21
|
-
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
location ~* ^/releases/.+\.(?:js|css|woff2?|png|jpg|svg)$ {
|
|
25
|
-
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
|
20
|
+
proxy_pass http://__FRONTEND_UPSTREAM_NAME__;
|
|
21
|
+
proxy_set_header Host $host;
|
|
22
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
23
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
24
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
26
25
|
}
|
|
27
26
|
}
|
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` | 扩充标准五段环境配置,生成人工交付、双 Docker 蓝绿发布与回滚文件。 |
|
|
22
22
|
|
|
23
23
|
## 使用方式
|
|
24
24
|
|
|
@@ -29,7 +29,7 @@ npm install -g @wdyy/skills
|
|
|
29
29
|
wdyy init
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
`wdyy init` 会在系统用户目录 `.agents/skills/` 安装或更新 5 个受管理 Skill,不在目标项目创建 `.agents/skills/`。它还会执行 `git init`,创建或补齐 `.gitignore` 的 `.env`、`node_modules/`、`venv/`、`.pnpm-store/`、`logs/`、`dist/`、`.DS_Store`、`*.tar.gz` 规则,创建 `src/frontend`、`src/backend`、`database`、`deploy`、`docs`、`scripts`、`tests`
|
|
32
|
+
`wdyy init` 会在系统用户目录 `.agents/skills/` 安装或更新 5 个受管理 Skill,不在目标项目创建 `.agents/skills/`。它还会执行 `git init`,创建或补齐 `.gitignore` 的 `.env`、`node_modules/`、`venv/`、`.pnpm-store/`、`logs/`、`dist/`、`.DS_Store`、`*.tar.gz` 规则,创建 `src/frontend`、`src/backend`、`database`、`deploy`、`docs`、`scripts`、`tests`,并以相同的“前端、后端、数据库、API、部署”结构创建缺失的 `.env` 与 `.env.example`。默认前端监听 `0.0.0.0:5173`、后端监听 `0.0.0.0:3000`、数据库端口为 `5432`;已有环境文件保持不变。随后命令执行 `openspec init`、创建或追加 `docs/bug_record.md` 模板。若目标项目已有 `AGENTS.md`,原文件保持不变,命令将生成 `AGENTS_new.md`。
|
|
33
33
|
|
|
34
34
|
### 仅更新已安装的 Skill
|
|
35
35
|
|
package/lib/wdyy-cli.js
CHANGED
|
@@ -34,7 +34,28 @@ const requiredGitIgnoreEntries = [
|
|
|
34
34
|
'*.tar.gz'
|
|
35
35
|
];
|
|
36
36
|
|
|
37
|
-
const
|
|
37
|
+
const defaultEnvironmentContent = `# 前端
|
|
38
|
+
FRONTEND_URL=0.0.0.0
|
|
39
|
+
FRONTEND_PORT=5173
|
|
40
|
+
|
|
41
|
+
# 后端
|
|
42
|
+
BACKEND_URL=0.0.0.0
|
|
43
|
+
BACKEND_PORT=3000
|
|
44
|
+
|
|
45
|
+
# 数据库
|
|
46
|
+
DB_URL=
|
|
47
|
+
DB_PORT=5432
|
|
48
|
+
DB_USER=
|
|
49
|
+
DB_PASSWORD=
|
|
50
|
+
DB_NAME=
|
|
51
|
+
DB_SCHEMA=
|
|
52
|
+
|
|
53
|
+
# API
|
|
54
|
+
|
|
55
|
+
# 部署
|
|
56
|
+
`;
|
|
57
|
+
|
|
58
|
+
const defaultProjectLayout = [...defaultProjectDirectories, '.env', '.env.example'];
|
|
38
59
|
|
|
39
60
|
const generatedAgentsContent = `# 企业开发规则
|
|
40
61
|
|
|
@@ -49,7 +70,7 @@ const generatedAgentsContent = `# 企业开发规则
|
|
|
49
70
|
|
|
50
71
|
默认项目目录为 ${defaultProjectLayout.map((path) => `\`${path}\``).join('、')}。
|
|
51
72
|
|
|
52
|
-
所有 URL、端口和 IP
|
|
73
|
+
所有 URL、端口和 IP 地址必须从项目根目录的 \`.env\` 文件读取,禁止在代码中硬编码;不得提交秘密或生产环境 \`.env\`。
|
|
53
74
|
|
|
54
75
|
项目开发完成后必须创建 \`README.md\`,内容包括项目技术栈、目录结构和安装部署说明。
|
|
55
76
|
|
|
@@ -158,13 +179,18 @@ async function createDefaultProjectLayout(targetRoot, writtenPaths) {
|
|
|
158
179
|
if (!existed) writtenPaths.push(destination);
|
|
159
180
|
}
|
|
160
181
|
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
182
|
+
for (const environmentFile of ['.env', '.env.example']) {
|
|
183
|
+
const environmentPath = join(targetRoot, environmentFile);
|
|
184
|
+
try {
|
|
185
|
+
await access(environmentPath);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
if (error.code !== 'ENOENT') throw error;
|
|
188
|
+
await writeFile(environmentPath, defaultEnvironmentContent, {
|
|
189
|
+
encoding: 'utf8',
|
|
190
|
+
mode: environmentFile === '.env' ? 0o600 : 0o644
|
|
191
|
+
});
|
|
192
|
+
writtenPaths.push(environmentPath);
|
|
193
|
+
}
|
|
168
194
|
}
|
|
169
195
|
console.log(`已准备默认项目目录: ${defaultProjectDirectories.join('、')}`);
|
|
170
196
|
}
|