@wdyy/skills 0.1.6 → 0.1.8
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 +66 -10
- 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
|
|
|
@@ -60,7 +60,51 @@ wdyy update-skill --all
|
|
|
60
60
|
|
|
61
61
|
## 发布到 npm
|
|
62
62
|
|
|
63
|
-
发布包名为 `@wdyy/skills`,命令行入口为 `wdyy
|
|
63
|
+
发布包名为 `@wdyy/skills`,命令行入口为 `wdyy`。以下流程适用于首次发布和后续发版;同一包名与版本只能发布一次。
|
|
64
|
+
|
|
65
|
+
### 使用发布脚本
|
|
66
|
+
|
|
67
|
+
推荐从项目根目录手动运行 `release_npm.sh`。脚本会检查工作区、组织权限和全部质量校验,自动执行 `npm version <patch|minor|major>`、`npm publish --access public`,并核验 registry 版本。它不会执行登录、浏览器认证或处理认证凭据。
|
|
68
|
+
|
|
69
|
+
首次运行或登录失效时,先手工登录;脚本检测到未登录也会提示并退出:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npm login
|
|
73
|
+
./release_npm.sh patch
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
可按变更范围选择版本级别:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
./release_npm.sh patch # 修复或小幅调整
|
|
80
|
+
./release_npm.sh minor # 向后兼容的新功能
|
|
81
|
+
./release_npm.sh major # 不兼容变更
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
脚本在 `npm publish` 成功前不会推送 Git 提交或标签;若 `npm version` 已完成而后续发布失败,工程师必须根据 npm 与 Git 的实际状态处理,不得重复发布相同版本。
|
|
85
|
+
|
|
86
|
+
### 手工执行的发布流程
|
|
87
|
+
|
|
88
|
+
当需要排查发布问题时,可按以下步骤手工执行。发布前确认当前工作区只包含准备发布的内容,并查看将要发布的版本:
|
|
89
|
+
|
|
90
|
+
### 1. 准备发布内容
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git status --short
|
|
94
|
+
node -p "require('./package.json').version"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
后续发版先选择符合变更范围的版本级别。`npm version` 会更新 `package.json`,并在 Git 工作区满足其要求时创建提交和标签:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm version patch # 修复或小幅调整
|
|
101
|
+
# npm version minor # 向后兼容的新功能
|
|
102
|
+
# npm version major # 不兼容变更
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 2. 执行发布前校验
|
|
106
|
+
|
|
107
|
+
版本确定后,必须完整执行以下校验,不得跳过:
|
|
64
108
|
|
|
65
109
|
```bash
|
|
66
110
|
npm test
|
|
@@ -69,27 +113,31 @@ node --test $(find .well-known/skills -path '*/scripts/*.test.mjs' -print)
|
|
|
69
113
|
npm pack --dry-run
|
|
70
114
|
```
|
|
71
115
|
|
|
72
|
-
|
|
116
|
+
其中 `npm pack --dry-run` 用于确认包内容;应包含 `bin`、`lib`、`.well-known/skills` 与 `README.md`,且不应包含本地环境文件或其他无关文件。
|
|
73
117
|
|
|
74
|
-
|
|
118
|
+
### 3. 登录并核对组织权限
|
|
119
|
+
|
|
120
|
+
首次发布前,在 npm 账户设置中配置安全密钥 2FA(WebAuthn,例如 macOS Touch ID 或硬件安全密钥)。npm 已不支持通过 CLI 新增 TOTP 认证器。使用拥有 `wdyy` 组织 Owner 或发布权限的账号登录,并核对身份和组织成员资格:
|
|
75
121
|
|
|
76
122
|
```bash
|
|
77
123
|
npm login
|
|
78
124
|
npm whoami
|
|
79
125
|
npm org ls wdyy
|
|
80
|
-
npm publish --access public
|
|
81
126
|
```
|
|
82
127
|
|
|
83
|
-
|
|
128
|
+
不得在仓库、终端历史或文档中记录 access token、验证码或恢复码。
|
|
84
129
|
|
|
85
|
-
|
|
130
|
+
### 4. 发布公开包
|
|
131
|
+
|
|
132
|
+
完成校验且确认登录态、组织权限和版本号无误后,执行:
|
|
86
133
|
|
|
87
134
|
```bash
|
|
88
|
-
npm version patch
|
|
89
135
|
npm publish --access public
|
|
90
136
|
```
|
|
91
137
|
|
|
92
|
-
|
|
138
|
+
### 5. 发布后验收
|
|
139
|
+
|
|
140
|
+
核对 registry 已出现目标版本;然后在干净的目标项目中安装并验证初始化:
|
|
93
141
|
|
|
94
142
|
```bash
|
|
95
143
|
npm view @wdyy/skills version
|
|
@@ -97,6 +145,14 @@ npm install -g @wdyy/skills
|
|
|
97
145
|
wdyy init
|
|
98
146
|
```
|
|
99
147
|
|
|
148
|
+
### 常见问题
|
|
149
|
+
|
|
150
|
+
- `npm whoami` 返回 `E401`:当前 CLI 没有有效登录态,重新执行 `npm login` 后再继续。
|
|
151
|
+
- 已成功登录但 `npm publish --access public` 返回 `E404`:通常是当前账号没有 `@wdyy` 组织的包创建或发布权限;请组织 Owner 授权后重试。
|
|
152
|
+
- 发布提示版本已存在:版本不可覆盖,先通过 `npm version patch`、`minor` 或 `major` 生成新版本,再从“执行发布前校验”重新开始。
|
|
153
|
+
|
|
154
|
+
不得通过在命令行中传入 access token、验证码或恢复码来规避认证或权限问题。
|
|
155
|
+
|
|
100
156
|
## 验证
|
|
101
157
|
|
|
102
158
|
```bash
|
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
|
}
|