@deepstorm/cli 0.8.0 → 0.9.0
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.
|
@@ -71,13 +71,17 @@ bash packages/reef/hooks/reef-scope-split.sh
|
|
|
71
71
|
|
|
72
72
|
## 配置文件
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
安装后配置写入 `.deepstorm/settings.json` 的 `reef.scope` 字段:
|
|
75
75
|
|
|
76
76
|
```json
|
|
77
77
|
{
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
"reef": {
|
|
79
|
+
"scope": {
|
|
80
|
+
"enabled": true,
|
|
81
|
+
"ciEnabled": true,
|
|
82
|
+
"domains": []
|
|
83
|
+
}
|
|
84
|
+
}
|
|
81
85
|
}
|
|
82
86
|
```
|
|
83
87
|
|
|
@@ -85,6 +89,8 @@ bash packages/reef/hooks/reef-scope-split.sh
|
|
|
85
89
|
- `ciEnabled`: CI 门禁开关(独立控制)
|
|
86
90
|
- `domains`: 项目业务领域列表(空 = AI 自由分类,非空 = AI 对齐到这些领域)
|
|
87
91
|
|
|
92
|
+
> **注意:** 旧版 `.deepstorm/scope-config.json` 已不再使用。如果存在该文件,运行 `deepstorm scope setup` 会自动迁移到 `settings.json`。
|
|
93
|
+
|
|
88
94
|
## 使用流程
|
|
89
95
|
|
|
90
96
|
1. **安装**: 运行一次 `reef-scope-setup.sh install`
|
|
@@ -8,7 +8,7 @@ deepstorm:
|
|
|
8
8
|
|
|
9
9
|
# Sweep Setup — E2E 测试项目初始化
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
初始化当前目录(或指定子目录)为 Sweep E2E 测试项目。根据 DeepStorm setup 阶段选择的 E2E 框架(如 Playwright),创建对应的项目骨架。
|
|
12
12
|
|
|
13
13
|
> **注意:** setup 是 flow-create 和 flow-run 的硬性前置条件。如果当前目录未初始化,其他 skill 会报错引导执行 `/sweep-init`。
|
|
14
14
|
|
|
@@ -41,27 +41,79 @@ cat .deepstorm/settings.json 2>/dev/null | grep -o '"e2eFramework"[^,]*' | head
|
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
+
### 步骤 0A:选择生成位置
|
|
45
|
+
|
|
46
|
+
在执行初始化前,先询问用户的 E2E 测试项目类型,确定文件生成的目标目录。
|
|
47
|
+
|
|
48
|
+
> **注意:** TARGET_DIR 是后续所有文件操作的前缀,在整个初始化流程中使用。
|
|
49
|
+
|
|
50
|
+
#### 0A.1 询问项目类型
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
📂 请问你的 E2E 测试是哪种类型?
|
|
54
|
+
|
|
55
|
+
a) 独立项目 → 生成在当前目录
|
|
56
|
+
b) 与其他项目混放 → 生成到子目录
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**如果选择 a(独立项目):**
|
|
60
|
+
- 设置 TARGET_DIR 为当前目录(`.`)
|
|
61
|
+
- 继续到步骤 1
|
|
62
|
+
|
|
63
|
+
**如果选择 b(混放项目):**
|
|
64
|
+
- 进一步询问子目录选择:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
请选择目标子目录:
|
|
68
|
+
1) e2e/ 👈 推荐
|
|
69
|
+
2) tests/e2e/
|
|
70
|
+
3) 自定义路径
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- 如果选择 3(自定义),AI 询问用户输入路径
|
|
74
|
+
- 验证用户输入的路径:不能为空、不能是绝对路径、不能包含 `..`
|
|
75
|
+
- 设置 TARGET_DIR 为所选路径(如 `"e2e"`、`"tests/e2e"` 等)
|
|
76
|
+
- 如果子目录已存在且非空,输出警告并询问用户是否确认继续
|
|
77
|
+
|
|
78
|
+
#### 0A.2 记录 TARGET_DIR
|
|
79
|
+
|
|
80
|
+
`TARGET_DIR` 变量在后续所有步骤中使用。写入 `.deepstorm/settings.json` 中的 `sweep.e2eProjectPath` 字段将在步骤 8 中完成。
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
44
84
|
### 步骤 1:检查初始化状态
|
|
45
85
|
|
|
46
|
-
|
|
86
|
+
检查当前项目是否已初始化为 E2E 测试项目。从 `.deepstorm/settings.json` 读取 `sweep.e2eProjectPath` 判断。
|
|
87
|
+
|
|
88
|
+
#### 1.1 检查 settings.json
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
E2E_PATH=$(cat .deepstorm/settings.json 2>/dev/null | grep -o '"e2eProjectPath"[^,]*' | head -1 | cut -d'"' -f4)
|
|
92
|
+
```
|
|
47
93
|
|
|
48
|
-
#### 1.
|
|
94
|
+
#### 1.2 已初始化 → 退出
|
|
49
95
|
|
|
50
|
-
- **WHEN** `.sweep-init`
|
|
51
|
-
- **THEN** 提示"
|
|
96
|
+
- **WHEN** `sweep.e2eProjectPath` 已设置(或旧 `.sweep-init` 文件存在)
|
|
97
|
+
- **THEN** 提示"当前项目已初始化为 Sweep 测试项目。如需重新初始化,请删除 `sweep.e2eProjectPath` 配置或 `.sweep-init` 文件后重试。"并退出
|
|
52
98
|
|
|
53
|
-
#### 1.
|
|
99
|
+
#### 1.3 向后兼容:旧 .sweep-init 文件检测
|
|
54
100
|
|
|
55
|
-
- **WHEN** `.sweep-init`
|
|
101
|
+
- **WHEN** `settings.json` 中 `sweep.e2eProjectPath` 未设置,但 `.sweep-init` 文件存在
|
|
102
|
+
- **THEN** 提示"ℹ️ 检测到旧版 .sweep-init 标记。建议删除该文件后重新运行 /sweep-init 以使用新版配置。"
|
|
103
|
+
- **THEN** 提示已初始化,退出
|
|
104
|
+
|
|
105
|
+
#### 1.4 未初始化 → 继续
|
|
106
|
+
|
|
107
|
+
- **WHEN** 以上均不满足
|
|
56
108
|
- **THEN** 继续执行初始化流程
|
|
57
109
|
|
|
58
110
|
---
|
|
59
111
|
|
|
60
112
|
### 步骤 2:创建项目目录结构
|
|
61
113
|
|
|
62
|
-
|
|
114
|
+
在 `{TARGET_DIR}` 下创建 E2E 测试项目的目录骨架。
|
|
63
115
|
|
|
64
|
-
####
|
|
116
|
+
#### 目录结构(当 TARGET_DIR 为 `"."` 时)
|
|
65
117
|
|
|
66
118
|
```
|
|
67
119
|
.
|
|
@@ -75,19 +127,27 @@ cat .deepstorm/settings.json 2>/dev/null | grep -o '"e2eFramework"[^,]*' | head
|
|
|
75
127
|
└── tsconfig.json # TypeScript 配置
|
|
76
128
|
```
|
|
77
129
|
|
|
78
|
-
>
|
|
130
|
+
> 如果 TARGET_DIR 为 `"e2e"`,以上所有文件在 `e2e/` 下生成。如果框架为 `playwright`,还会额外生成 `playwright.config.ts`。
|
|
79
131
|
|
|
80
132
|
#### 执行
|
|
81
133
|
|
|
82
134
|
```bash
|
|
83
|
-
|
|
135
|
+
# 计算目标目录:TARGET_DIR 为 "." 时用当前目录,否则用 TARGET_DIR
|
|
136
|
+
if [ "$TARGET_DIR" != "." ]; then
|
|
137
|
+
mkdir -p "$TARGET_DIR"/flows "$TARGET_DIR"/flows/reports "$TARGET_DIR"/scripts
|
|
138
|
+
echo "📂 将在 $TARGET_DIR/ 目录下生成 E2E 测试项目"
|
|
139
|
+
else
|
|
140
|
+
mkdir -p flows flows/reports scripts
|
|
141
|
+
fi
|
|
84
142
|
```
|
|
85
143
|
|
|
86
144
|
---
|
|
87
145
|
|
|
88
146
|
### 步骤 3:生成项目配置文件(框架感知)
|
|
89
147
|
|
|
90
|
-
根据步骤 0
|
|
148
|
+
根据步骤 0 读取的框架配置,在 `{TARGET_DIR}` 下生成对应的配置文件。
|
|
149
|
+
|
|
150
|
+
> 所有文件写入路径以 `{TARGET_DIR}` 为前缀。当 `TARGET_DIR` 为 `"."` 时,路径不变。
|
|
91
151
|
|
|
92
152
|
#### 3.1 package.json
|
|
93
153
|
|
|
@@ -115,7 +175,7 @@ mkdir -p flows flows/reports scripts
|
|
|
115
175
|
|
|
116
176
|
#### 3.2 框架配置文件
|
|
117
177
|
|
|
118
|
-
**当框架为 `playwright` 时**,写入 `playwright.config.ts`,包含多环境 baseURL 设置:
|
|
178
|
+
**当框架为 `playwright` 时**,写入 `{TARGET_DIR}/playwright.config.ts`,包含多环境 baseURL 设置:
|
|
119
179
|
|
|
120
180
|
```ts
|
|
121
181
|
import { defineConfig } from '@playwright/test';
|
|
@@ -164,23 +224,43 @@ export default defineConfig({
|
|
|
164
224
|
3. 生产环境(prod)baseURL
|
|
165
225
|
4. 默认目标环境(test / staging / prod)
|
|
166
226
|
|
|
167
|
-
#### 4.2 写入 .
|
|
227
|
+
#### 4.2 写入 settings.json
|
|
168
228
|
|
|
169
|
-
|
|
229
|
+
将多环境配置写入 `.deepstorm/settings.json` 的 `sweep.environments` 字段。**不再生成 `.env` 文件。**
|
|
230
|
+
|
|
231
|
+
使用 Bash 和 `jq` 合并写入(或 AI 读取-修改-写回):
|
|
170
232
|
|
|
171
233
|
```bash
|
|
172
|
-
# .
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
234
|
+
# 先读取现有 settings.json
|
|
235
|
+
SETTINGS=$(cat .deepstorm/settings.json 2>/dev/null || echo "{}")
|
|
236
|
+
|
|
237
|
+
# 构造 environments 配置并写入
|
|
238
|
+
# (使用 jq 或 AI 逐字段修改)
|
|
177
239
|
```
|
|
178
240
|
|
|
241
|
+
写入后的 settings.json 结构示例:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"sweep": {
|
|
246
|
+
"e2eFramework": "playwright",
|
|
247
|
+
"environments": {
|
|
248
|
+
"test": { "baseUrl": "http://localhost:3000" },
|
|
249
|
+
"staging": { "baseUrl": "https://staging.example.com" },
|
|
250
|
+
"prod": { "baseUrl": "https://prod.example.com" },
|
|
251
|
+
"default": "test"
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
> **注意:** API Key 等敏感信息仍然放在 `.env` 文件(gitignored)中。此处仅迁移多环境 baseURL 配置。
|
|
258
|
+
|
|
179
259
|
---
|
|
180
260
|
|
|
181
261
|
### 步骤 5:创建 topology.yaml 初始模板
|
|
182
262
|
|
|
183
|
-
|
|
263
|
+
写入功能模块拓扑文件基础结构到 `{TARGET_DIR}/flows/topology.yaml`:
|
|
184
264
|
|
|
185
265
|
```yaml
|
|
186
266
|
# flows/topology.yaml
|
|
@@ -202,7 +282,7 @@ modules:
|
|
|
202
282
|
|
|
203
283
|
### 步骤 6:创建 flow-selector.mjs
|
|
204
284
|
|
|
205
|
-
使用 Read 读取本 skill 目录下的 `scripts/flow-selector.mjs` 文件,用 Write 写入目标项目的 `scripts/flow-selector.mjs`。
|
|
285
|
+
使用 Read 读取本 skill 目录下的 `scripts/flow-selector.mjs` 文件,用 Write 写入目标项目的 `{TARGET_DIR}/scripts/flow-selector.mjs`。
|
|
206
286
|
|
|
207
287
|
> **说明:** `flow-selector.mjs` 是基于 `@inquirer/checkbox` 的层级选择工具脚本(供 flow-run skill 调用)。
|
|
208
288
|
> 它与本 SKILL.md 同属一个 skill,作为 skill 的子文件分开维护,避免内联代码块导致的重复。
|
|
@@ -236,16 +316,37 @@ cat .mcp.json 2>/dev/null | grep -c "deepstorm-playwright"
|
|
|
236
316
|
|
|
237
317
|
### 步骤 8:完成初始化
|
|
238
318
|
|
|
239
|
-
#### 8.1
|
|
319
|
+
#### 8.1 写入 e2eProjectPath 到 settings.json
|
|
320
|
+
|
|
321
|
+
将 `sweep.e2eProjectPath` 写入 `.deepstorm/settings.json`。**不再创建 `.sweep-init` 标记文件。**
|
|
240
322
|
|
|
241
323
|
```bash
|
|
242
|
-
|
|
324
|
+
# 值由步骤 0A 确定:
|
|
325
|
+
# 独立项目 → "."
|
|
326
|
+
# 混放项目 → 用户选择的路径(如 "e2e")
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
写入后的 settings.json 结构示例:
|
|
330
|
+
|
|
331
|
+
```json
|
|
332
|
+
{
|
|
333
|
+
"sweep": {
|
|
334
|
+
"e2eFramework": "playwright",
|
|
335
|
+
"e2eProjectPath": "e2e",
|
|
336
|
+
"environments": { ... }
|
|
337
|
+
}
|
|
338
|
+
}
|
|
243
339
|
```
|
|
244
340
|
|
|
245
341
|
#### 8.2 安装依赖
|
|
246
342
|
|
|
247
343
|
```bash
|
|
248
|
-
npm install
|
|
344
|
+
# 在目标目录中执行 npm install
|
|
345
|
+
if [ "$TARGET_DIR" != "." ]; then
|
|
346
|
+
cd "$TARGET_DIR" && npm install
|
|
347
|
+
else
|
|
348
|
+
npm install
|
|
349
|
+
fi
|
|
249
350
|
```
|
|
250
351
|
|
|
251
352
|
#### 8.3 输出完成信息
|
|
@@ -254,15 +355,16 @@ npm install
|
|
|
254
355
|
✅ Sweep E2E 测试项目初始化完成!
|
|
255
356
|
|
|
256
357
|
框架:{所选框架}
|
|
358
|
+
位置:{TARGET_DIR}
|
|
257
359
|
|
|
258
360
|
项目结构:
|
|
259
|
-
flows/ — 测试意图文档目录
|
|
260
|
-
flows/reports/ — 执行报告目录
|
|
261
|
-
scripts/ — 辅助脚本
|
|
262
|
-
(框架配置文件)
|
|
361
|
+
{TARGET_DIR}/flows/ — 测试意图文档目录
|
|
362
|
+
{TARGET_DIR}/flows/reports/ — 执行报告目录
|
|
363
|
+
{TARGET_DIR}/scripts/ — 辅助脚本
|
|
364
|
+
(框架配置文件) — {框架名} 配置文件
|
|
263
365
|
|
|
264
366
|
下一步:
|
|
265
|
-
1. 编辑 flows/topology.yaml 添加你的功能模块
|
|
367
|
+
1. 编辑 {TARGET_DIR}/flows/topology.yaml 添加你的功能模块
|
|
266
368
|
2. 运行 /sweep-plan 创建测试意图文档
|
|
267
369
|
3. 运行 /sweep-run 执行测试流程
|
|
268
370
|
```
|
|
@@ -272,15 +374,16 @@ npm install
|
|
|
272
374
|
## 检查清单
|
|
273
375
|
|
|
274
376
|
- [ ] 已读取框架配置(`deepstorm.sweep.e2eFramework`)
|
|
275
|
-
- [ ]
|
|
276
|
-
- [ ]
|
|
377
|
+
- [ ] 步骤 0A:已选择目标目录(`TARGET_DIR` 已确定)
|
|
378
|
+
- [ ] 步骤 1:检查通过(`e2eProjectPath` 未设置,且 `.sweep-init` 不存在)
|
|
379
|
+
- [ ] 项目目录结构已创建(`{TARGET_DIR}/flows/`、`{TARGET_DIR}/flows/reports/`、`{TARGET_DIR}/scripts/`)
|
|
277
380
|
- [ ] package.json 已写入(含对应框架的依赖)
|
|
278
381
|
- [ ] 框架配置文件已生成(如 playwright.config.ts)
|
|
279
382
|
- [ ] tsconfig.json 已写入
|
|
280
383
|
- [ ] 用户已输入三个环境的 baseURL
|
|
281
|
-
- [ ] .
|
|
384
|
+
- [ ] environments 已写入 `.deepstorm/settings.json` 的 `sweep.environments`
|
|
282
385
|
- [ ] topology.yaml 初始模板已创建
|
|
283
386
|
- [ ] flow-selector.mjs 已写入
|
|
284
387
|
- [ ] 已确认 MCP 配置状态(从 `.mcp.json` 读取)
|
|
285
|
-
- [ ] .
|
|
286
|
-
- [ ] npm install
|
|
388
|
+
- [ ] `sweep.e2eProjectPath` 已写入 `.deepstorm/settings.json`
|
|
389
|
+
- [ ] npm install 已在目标目录执行
|
|
@@ -17,7 +17,7 @@ mcpCapabilities:
|
|
|
17
17
|
|
|
18
18
|
## 前置条件
|
|
19
19
|
|
|
20
|
-
运行 `/sweep-plan`
|
|
20
|
+
运行 `/sweep-plan` 前,请确保项目已通过 `/sweep-init` 初始化(`.deepstorm/settings.json` 中存在 `sweep.e2eProjectPath` 配置)。
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -44,10 +44,67 @@ mcpCapabilities:
|
|
|
44
44
|
|
|
45
45
|
## 工作流
|
|
46
46
|
|
|
47
|
-
### 步骤 1
|
|
47
|
+
### 步骤 1:检查初始化状态与路径导航
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
从 `.deepstorm/settings.json` 读取 `sweep.e2eProjectPath`,确定 E2E 测试项目的位置,如非根目录则自动切换。支持从子目录向上查找以兼容用户在 E2E 项目子目录中执行的情况。
|
|
50
|
+
|
|
51
|
+
#### 1.1 读取配置(支持向上查找)
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# 向上查找 .deepstorm/settings.json
|
|
55
|
+
DEEPSTORM_DIR=""
|
|
56
|
+
CUR="$PWD"
|
|
57
|
+
while [ "$CUR" != "/" ]; do
|
|
58
|
+
if [ -f "$CUR/.deepstorm/settings.json" ]; then
|
|
59
|
+
DEEPSTORM_DIR="$CUR"
|
|
60
|
+
break
|
|
61
|
+
fi
|
|
62
|
+
CUR=$(dirname "$CUR")
|
|
63
|
+
done
|
|
64
|
+
|
|
65
|
+
if [ -n "$DEEPSTORM_DIR" ]; then
|
|
66
|
+
E2E_PATH=$(grep -o '"e2eProjectPath"[^,]*' "$DEEPSTORM_DIR/.deepstorm/settings.json" | head -1 | cut -d'"' -f4)
|
|
67
|
+
else
|
|
68
|
+
E2E_PATH=""
|
|
69
|
+
fi
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### 1.2 配置存在 → 路径导航
|
|
73
|
+
|
|
74
|
+
- **WHEN** `E2E_PATH` 不为空
|
|
75
|
+
- **THEN** 判断路径值。注意 `E2E_PATH` 是基于 `DEEPSTORM_DIR`(settings.json 所在目录)的相对路径,若当前在子目录则需拼接:
|
|
76
|
+
```bash
|
|
77
|
+
if [ "$E2E_PATH" != "." ]; then
|
|
78
|
+
# 若从子目录找到的 settings.json,E2E_PATH 相对于 DEEPSTORM_DIR
|
|
79
|
+
TARGET_DIR="$E2E_PATH"
|
|
80
|
+
if [ -n "$DEEPSTORM_DIR" ] && [ "$DEEPSTORM_DIR" != "$PWD" ]; then
|
|
81
|
+
TARGET_DIR="$DEEPSTORM_DIR/$E2E_PATH"
|
|
82
|
+
fi
|
|
83
|
+
if [ -d "$TARGET_DIR" ]; then
|
|
84
|
+
echo "📂 切换到 E2E 项目目录: $E2E_PATH"
|
|
85
|
+
cd "$TARGET_DIR"
|
|
86
|
+
else
|
|
87
|
+
echo "❌ E2E 项目目录不存在: $E2E_PATH,请重新运行 /sweep-init"
|
|
88
|
+
exit 1
|
|
89
|
+
fi
|
|
90
|
+
fi
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### 1.3 配置不存在 → 向后兼容检查
|
|
94
|
+
|
|
95
|
+
- **WHEN** `E2E_PATH` 为空
|
|
96
|
+
- **THEN** 检查旧 `.sweep-init` 文件是否存在(从当前目录和 DEEPSTORM_DIR 向上查找):
|
|
97
|
+
```bash
|
|
98
|
+
if [ -f ".sweep-init" ]; then
|
|
99
|
+
echo "ℹ️ 检测到旧版 .sweep-init 标记。建议运行 /sweep-init 刷新配置。"
|
|
100
|
+
# 继续执行(兼容旧项目)
|
|
101
|
+
elif [ -n "$DEEPSTORM_DIR" ] && [ -f "$DEEPSTORM_DIR/.sweep-init" ]; then
|
|
102
|
+
echo "ℹ️ 检测到旧版 .sweep-init 标记(项目根: $DEEPSTORM_DIR)。建议运行 /sweep-init 刷新配置。"
|
|
103
|
+
else
|
|
104
|
+
echo "❌ 未检测到 E2E 项目。请先运行 /sweep-init 初始化。"
|
|
105
|
+
exit 1
|
|
106
|
+
fi
|
|
107
|
+
```
|
|
51
108
|
|
|
52
109
|
### 步骤 2:获取测试需求上下文(MCP 动态适配)
|
|
53
110
|
|
|
@@ -303,7 +360,7 @@ node scripts/spec-compiler.mjs flows/user-system/login/login.flow.md
|
|
|
303
360
|
|
|
304
361
|
## 检查清单
|
|
305
362
|
|
|
306
|
-
- [ ]
|
|
363
|
+
- [ ] 项目已初始化(读取 settings.json → sweep.e2eProjectPath)
|
|
307
364
|
- [ ] 获取到测试需求上下文(Issue / PRD / 描述)
|
|
308
365
|
- [ ] 确定放置模块位置(topology.yaml)
|
|
309
366
|
- [ ] 确定文件名
|
|
@@ -58,10 +58,65 @@ node scripts/env-manager.mjs --framework
|
|
|
58
58
|
|
|
59
59
|
---
|
|
60
60
|
|
|
61
|
-
### 步骤 1
|
|
61
|
+
### 步骤 1:检查初始化状态与路径导航
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
从 `.deepstorm/settings.json` 读取 `sweep.e2eProjectPath`,确定 E2E 测试项目的位置,如非根目录则自动切换。支持从子目录向上查找以兼容用户在 E2E 项目子目录中执行的情况。
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# 向上查找 .deepstorm/settings.json
|
|
67
|
+
DEEPSTORM_DIR=""
|
|
68
|
+
CUR="$PWD"
|
|
69
|
+
while [ "$CUR" != "/" ]; do
|
|
70
|
+
if [ -f "$CUR/.deepstorm/settings.json" ]; then
|
|
71
|
+
DEEPSTORM_DIR="$CUR"
|
|
72
|
+
break
|
|
73
|
+
fi
|
|
74
|
+
CUR=$(dirname "$CUR")
|
|
75
|
+
done
|
|
76
|
+
|
|
77
|
+
if [ -n "$DEEPSTORM_DIR" ]; then
|
|
78
|
+
E2E_PATH=$(grep -o '"e2eProjectPath"[^,]*' "$DEEPSTORM_DIR/.deepstorm/settings.json" | head -1 | cut -d'"' -f4)
|
|
79
|
+
else
|
|
80
|
+
E2E_PATH=""
|
|
81
|
+
fi
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### 1.1 配置存在 → 路径导航
|
|
85
|
+
|
|
86
|
+
- **WHEN** `E2E_PATH` 不为空
|
|
87
|
+
- **THEN** 判断路径值。注意 `E2E_PATH` 是基于 `DEEPSTORM_DIR`(settings.json 所在目录)的相对路径,若当前在子目录则需拼接:
|
|
88
|
+
```bash
|
|
89
|
+
if [ "$E2E_PATH" != "." ]; then
|
|
90
|
+
# 若从子目录找到的 settings.json,E2E_PATH 相对于 DEEPSTORM_DIR
|
|
91
|
+
TARGET_DIR="$E2E_PATH"
|
|
92
|
+
if [ -n "$DEEPSTORM_DIR" ] && [ "$DEEPSTORM_DIR" != "$PWD" ]; then
|
|
93
|
+
TARGET_DIR="$DEEPSTORM_DIR/$E2E_PATH"
|
|
94
|
+
fi
|
|
95
|
+
if [ -d "$TARGET_DIR" ]; then
|
|
96
|
+
echo "📂 切换到 E2E 项目目录: $E2E_PATH"
|
|
97
|
+
cd "$TARGET_DIR"
|
|
98
|
+
else
|
|
99
|
+
echo "❌ E2E 项目目录不存在: $E2E_PATH,请重新运行 /sweep-init"
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
fi
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### 1.2 配置不存在 → 向后兼容检查
|
|
106
|
+
|
|
107
|
+
- **WHEN** `E2E_PATH` 为空
|
|
108
|
+
- **THEN** 检查旧 `.sweep-init` 文件是否存在(从当前目录和 DEEPSTORM_DIR 向上查找):
|
|
109
|
+
```bash
|
|
110
|
+
if [ -f ".sweep-init" ]; then
|
|
111
|
+
echo "ℹ️ 检测到旧版 .sweep-init 标记。建议运行 /sweep-init 刷新配置。"
|
|
112
|
+
# 继续执行(兼容旧项目)
|
|
113
|
+
elif [ -n "$DEEPSTORM_DIR" ] && [ -f "$DEEPSTORM_DIR/.sweep-init" ]; then
|
|
114
|
+
echo "ℹ️ 检测到旧版 .sweep-init 标记(项目根: $DEEPSTORM_DIR)。建议运行 /sweep-init 刷新配置。"
|
|
115
|
+
else
|
|
116
|
+
echo "❌ 未检测到 E2E 项目。请先运行 /sweep-init 初始化。"
|
|
117
|
+
exit 1
|
|
118
|
+
fi
|
|
119
|
+
```
|
|
65
120
|
|
|
66
121
|
---
|
|
67
122
|
|
|
@@ -162,9 +217,9 @@ node scripts/env-manager.mjs --env staging
|
|
|
162
217
|
]}
|
|
163
218
|
```
|
|
164
219
|
|
|
165
|
-
- `--env staging` → 从
|
|
166
|
-
- `--env test` → 从
|
|
167
|
-
- 不传参 → 使用 `.env`
|
|
220
|
+
- `--env staging` → 从 `settings.json` 的 `sweep.environments.staging` 读取(回退到 `.env`)
|
|
221
|
+
- `--env test` → 从 `settings.json` 的 `sweep.environments.test` 读取(回退到 `.env`)
|
|
222
|
+
- 不传参 → 使用 `settings.json` 的 `sweep.environments.default`(回退到 `.env` 的 `DEFAULT_ENV`),未设置则默认 `test`
|
|
168
223
|
|
|
169
224
|
#### 4.2 设置环境变量
|
|
170
225
|
|
|
@@ -426,7 +481,7 @@ Flow: L01 - 正常登录成功
|
|
|
426
481
|
## 检查清单
|
|
427
482
|
|
|
428
483
|
- [ ] 前置检查:框架配置已读取(`.deepstorm/settings.json` → `sweep.e2eFramework`)
|
|
429
|
-
- [ ]
|
|
484
|
+
- [ ] 项目已初始化(读取 settings.json → sweep.e2eProjectPath)
|
|
430
485
|
- [ ] 执行范围已确定(--all / --path / 交互选择)
|
|
431
486
|
- [ ] 执行模式已选择(hybrid / native / no-parallel / browser)
|
|
432
487
|
- [ ] MCP 服务按模式正确启动(available → headless / headed / 不启动)
|
|
@@ -27,6 +27,65 @@ function getEnvPath() {
|
|
|
27
27
|
function getMcpPath() {
|
|
28
28
|
return resolve(process.cwd(), '.mcp.json');
|
|
29
29
|
}
|
|
30
|
+
function getDeepstormSettingsPath() {
|
|
31
|
+
return resolve(process.cwd(), '.deepstorm', 'settings.json');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ── settings.json reading ─────────────────────────────────────────
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Read .deepstorm/settings.json and extract environments config.
|
|
38
|
+
* Returns the sweep.environments object or null if not configured.
|
|
39
|
+
*/
|
|
40
|
+
export function readDeepstormEnvironments() {
|
|
41
|
+
const settingsPath = getDeepstormSettingsPath();
|
|
42
|
+
if (!existsSync(settingsPath)) return null;
|
|
43
|
+
try {
|
|
44
|
+
const content = readFileSync(settingsPath, 'utf-8');
|
|
45
|
+
const config = JSON.parse(content);
|
|
46
|
+
return config.sweep?.environments || null;
|
|
47
|
+
} catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Read .deepstorm/settings.json and extract e2eProjectPath.
|
|
54
|
+
* Returns the project path string or null if not configured.
|
|
55
|
+
*/
|
|
56
|
+
export function readE2eProjectPath() {
|
|
57
|
+
const settingsPath = getDeepstormSettingsPath();
|
|
58
|
+
if (!existsSync(settingsPath)) return null;
|
|
59
|
+
try {
|
|
60
|
+
const content = readFileSync(settingsPath, 'utf-8');
|
|
61
|
+
const config = JSON.parse(content);
|
|
62
|
+
return config.sweep?.e2eProjectPath || null;
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Convert settings.json environments format to the same structure
|
|
70
|
+
* that listEnvs() returns from .env, for a unified return format.
|
|
71
|
+
*
|
|
72
|
+
* Input: { test: { baseUrl: "..." }, staging: { baseUrl: "..." }, default: "test" }
|
|
73
|
+
* Output: { envMap: { BASE_URL_TEST: "...", BASE_URL_STAGING: "...", DEFAULT_ENV: "test" },
|
|
74
|
+
* defaultEnv: "test" }
|
|
75
|
+
*/
|
|
76
|
+
function deepstormEnvsToEnvMap(envs) {
|
|
77
|
+
if (!envs) return { envMap: {}, defaultEnv: 'test' };
|
|
78
|
+
const envMap = {};
|
|
79
|
+
const defaultEnv = envs.default || 'test';
|
|
80
|
+
for (const [name, config] of Object.entries(envs)) {
|
|
81
|
+
if (name === 'default') continue;
|
|
82
|
+
if (config && config.baseUrl) {
|
|
83
|
+
envMap[`BASE_URL_${name.toUpperCase()}`] = config.baseUrl;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
envMap.DEFAULT_ENV = defaultEnv;
|
|
87
|
+
return { envMap, defaultEnv };
|
|
88
|
+
}
|
|
30
89
|
|
|
31
90
|
// ── .env parsing ──────────────────────────────────────────────────
|
|
32
91
|
|
|
@@ -68,17 +127,40 @@ export function readDotEnv() {
|
|
|
68
127
|
|
|
69
128
|
/**
|
|
70
129
|
* Get the default environment name.
|
|
130
|
+
* Priority: settings.json > .env
|
|
71
131
|
* Falls back to 'test' if not configured.
|
|
72
132
|
*/
|
|
73
133
|
export function getDefaultEnv(envMap) {
|
|
134
|
+
const dsEnvs = readDeepstormEnvironments();
|
|
135
|
+
if (dsEnvs && dsEnvs.default) {
|
|
136
|
+
return dsEnvs.default;
|
|
137
|
+
}
|
|
74
138
|
return envMap.DEFAULT_ENV || 'test';
|
|
75
139
|
}
|
|
76
140
|
|
|
77
141
|
/**
|
|
78
|
-
* List all available environments
|
|
142
|
+
* List all available environments.
|
|
143
|
+
* Priority: settings.json > .env
|
|
79
144
|
* Detects BASE_URL_{ENV} patterns and returns their names.
|
|
80
145
|
*/
|
|
81
146
|
export function listEnvs(envMap) {
|
|
147
|
+
const dsEnvs = readDeepstormEnvironments();
|
|
148
|
+
if (dsEnvs) {
|
|
149
|
+
const envs = [];
|
|
150
|
+
for (const [name, config] of Object.entries(dsEnvs)) {
|
|
151
|
+
if (name === 'default') continue;
|
|
152
|
+
if (config && config.baseUrl) {
|
|
153
|
+
envs.push({
|
|
154
|
+
name: name.toLowerCase(),
|
|
155
|
+
key: `BASE_URL_${name.toUpperCase()}`,
|
|
156
|
+
url: config.baseUrl,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return envs;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Fallback to .env-based envMap
|
|
82
164
|
const envs = [];
|
|
83
165
|
for (const key of Object.keys(envMap)) {
|
|
84
166
|
const match = key.match(/^BASE_URL_(.+)$/);
|
|
@@ -96,13 +178,27 @@ export function listEnvs(envMap) {
|
|
|
96
178
|
/**
|
|
97
179
|
* Resolve target environment config.
|
|
98
180
|
*
|
|
181
|
+
* Priority: settings.json > .env
|
|
182
|
+
*
|
|
99
183
|
* @param {string} [envName] - Target environment name (e.g. 'staging', 'test')
|
|
100
184
|
* @returns {{ env: string, baseUrl: string|null, availableEnvs: Array<{name:string,url:string}> }}
|
|
101
185
|
*
|
|
102
|
-
* If envName is omitted, uses DEFAULT_ENV
|
|
186
|
+
* If envName is omitted, uses DEFAULT_ENV (or 'test').
|
|
103
187
|
* If the environment is not found, baseUrl is null and availableEnvs lists alternatives.
|
|
104
188
|
*/
|
|
105
189
|
export function resolveEnv(envName) {
|
|
190
|
+
// Try settings.json first
|
|
191
|
+
const dsEnvs = readDeepstormEnvironments();
|
|
192
|
+
if (dsEnvs) {
|
|
193
|
+
const { envMap, defaultEnv } = deepstormEnvsToEnvMap(dsEnvs);
|
|
194
|
+
const name = envName || defaultEnv;
|
|
195
|
+
const availableEnvs = listEnvs(envMap);
|
|
196
|
+
const baseUrlKey = `BASE_URL_${name.toUpperCase()}`;
|
|
197
|
+
const baseUrl = envMap[baseUrlKey] || null;
|
|
198
|
+
return { env: name, baseUrl, availableEnvs };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Fallback to .env
|
|
106
202
|
const envMap = readDotEnv();
|
|
107
203
|
const name = envName || getDefaultEnv(envMap);
|
|
108
204
|
const availableEnvs = listEnvs(envMap);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstorm/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "DeepStorm CLI — 一键配置项目开发环境",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "billkang",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dotenv": "^17.4.2",
|
|
17
17
|
"handlebars": "^4.7.8",
|
|
18
18
|
"js-yaml": "^4.1.0",
|
|
19
|
-
"@deepstorm/pilot": "^0.
|
|
19
|
+
"@deepstorm/pilot": "^0.9.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^22.0.0",
|