ai-project-manage-cli 1.0.17 → 1.0.19

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.
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmCzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyC3D"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkIzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiD3D"}
@@ -6,10 +6,88 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.registerInitCommands = registerInitCommands;
7
7
  const promises_1 = require("node:fs/promises");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
+ const DEPLOY_README_STUB = `# 测试环境部署说明
10
+
11
+ 请在本文件中编写:前置条件、构建命令、部署命令、验证方式等。Agent / \`apm\` 将按本文档执行测试环境部署。
12
+
13
+ ## 前置条件
14
+
15
+ (可选)
16
+
17
+ ## 部署步骤
18
+
19
+ 1.
20
+
21
+ ## 验证
22
+
23
+ (可选)
24
+ `;
25
+ const PRODUCT_CAPABILITY_README_STUB = `# 产品能力清单
26
+
27
+ 本目录用于维护产品能力条目(CAP)。详见 [使用说明书.md](./使用说明书.md)。
28
+
29
+ ## 子系统列表
30
+
31
+ | 目录 | 说明 |
32
+ |------|------|
33
+ | (待补充) | 在各子目录下维护 \`index.md\` 与 \`CAP-*.md\` |
34
+ `;
9
35
  function resolveSkillSourceDir() {
10
36
  // dist/cli/commands/init.js -> ../../../templates/skills
11
37
  return node_path_1.default.resolve(__dirname, "../../../templates/skills");
12
38
  }
39
+ async function pathExists(p) {
40
+ try {
41
+ await (0, promises_1.stat)(p);
42
+ return true;
43
+ }
44
+ catch {
45
+ return false;
46
+ }
47
+ }
48
+ /** \`.cursor/skills\` 所在仓库根目录 */
49
+ function resolveProjectRootFromCursorSkillsDir(cursorSkillsDir) {
50
+ return node_path_1.default.resolve(cursorSkillsDir, "..", "..");
51
+ }
52
+ /**
53
+ * 创建标准 \`.apm\` 目录结构(与仓库内参考 \`.apm\` 一致):
54
+ * - workitems
55
+ * - deploy(含占位 README,已存在则不覆盖)
56
+ * - product-capability-inventory(含总览 README;从模板复制使用说明书,已存在则不覆盖)
57
+ */
58
+ async function ensureApmStandardLayout(projectRoot, skillsTemplateDir) {
59
+ const apmRoot = node_path_1.default.join(projectRoot, ".apm");
60
+ const created = [];
61
+ const warnings = [];
62
+ await (0, promises_1.mkdir)(node_path_1.default.join(apmRoot, "workitems"), { recursive: true });
63
+ created.push(".apm/workitems");
64
+ await (0, promises_1.mkdir)(node_path_1.default.join(apmRoot, "deploy"), { recursive: true });
65
+ created.push(".apm/deploy");
66
+ await (0, promises_1.mkdir)(node_path_1.default.join(apmRoot, "product-capability-inventory"), { recursive: true });
67
+ created.push(".apm/product-capability-inventory");
68
+ const deployReadme = node_path_1.default.join(apmRoot, "deploy", "README.md");
69
+ if (!(await pathExists(deployReadme))) {
70
+ await (0, promises_1.writeFile)(deployReadme, DEPLOY_README_STUB, "utf8");
71
+ created.push(".apm/deploy/README.md");
72
+ }
73
+ const manualSrc = node_path_1.default.join(skillsTemplateDir, "product-capability-inventory", "使用说明书.md");
74
+ const manualDst = node_path_1.default.join(apmRoot, "product-capability-inventory", "使用说明书.md");
75
+ if (!(await pathExists(manualDst))) {
76
+ if (await pathExists(manualSrc)) {
77
+ await (0, promises_1.cp)(manualSrc, manualDst);
78
+ created.push(".apm/product-capability-inventory/使用说明书.md");
79
+ }
80
+ else {
81
+ warnings.push(`模板缺失,未复制使用说明书: ${manualSrc}`);
82
+ }
83
+ }
84
+ const capReadme = node_path_1.default.join(apmRoot, "product-capability-inventory", "README.md");
85
+ if (!(await pathExists(capReadme))) {
86
+ await (0, promises_1.writeFile)(capReadme, PRODUCT_CAPABILITY_README_STUB, "utf8");
87
+ created.push(".apm/product-capability-inventory/README.md");
88
+ }
89
+ return { apmRoot, created, warnings };
90
+ }
13
91
  async function resolveCursorSkillsDir() {
14
92
  // 从当前工作目录向上查找最近的 `.cursor/skills`
15
93
  let cur = process.cwd();
@@ -39,10 +117,12 @@ async function resolveCursorSkillsDir() {
39
117
  function registerInitCommands(program) {
40
118
  program
41
119
  .command("init")
42
- .description("安装内置 Cursor skills 到当前项目的 .cursor/skills(须已存在该目录)")
120
+ .description("安装内置 Cursor skills 到当前项目的 .cursor/skills(须已存在该目录),并初始化标准 .apm 目录结构")
43
121
  .action(async () => {
44
122
  const srcDir = resolveSkillSourceDir();
45
123
  const dstDir = await resolveCursorSkillsDir();
124
+ const projectRoot = resolveProjectRootFromCursorSkillsDir(dstDir);
125
+ const apmResult = await ensureApmStandardLayout(projectRoot, srcDir);
46
126
  await (0, promises_1.mkdir)(dstDir, { recursive: true });
47
127
  // 读取模板下的技能子目录名,用于在目标目录中做“删除后重装”
48
128
  const entries = await (0, promises_1.readdir)(srcDir, { withFileTypes: true });
@@ -64,6 +144,11 @@ function registerInitCommands(program) {
64
144
  ok: true,
65
145
  installedFrom: srcDir,
66
146
  installedTo: dstDir,
147
+ apm: {
148
+ root: apmResult.apmRoot,
149
+ created: apmResult.created,
150
+ warnings: apmResult.warnings,
151
+ },
67
152
  }, null, 2));
68
153
  });
69
154
  }
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":";;;;;AAqCA,oDAyCC;AA9ED,+CAAgE;AAChE,0DAA6B;AAG7B,SAAS,qBAAqB;IAC5B,yDAAyD;IACzD,OAAO,mBAAI,CAAC,OAAO,CAAC,SAAS,EAAE,2BAA2B,CAAC,CAAC;AAC9D,CAAC;AAED,KAAK,UAAU,sBAAsB;IACnC,kCAAkC;IAClC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACxB,qBAAqB;IACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,mBAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACtD,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,IAAA,eAAI,EAAC,SAAS,CAAC,CAAC;YAChC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBACpB,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;QACD,MAAM,MAAM,GAAG,mBAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM;QACrC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IAED,gCAAgC;IAChC,sCAAsC;IACtC,sCAAsC;IACtC,OAAO,CAAC,KAAK,CACX,iEAAiE,CAClE,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,SAAgB,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CACV,mDAAmD,CACpD;SACA,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAE9C,MAAM,IAAA,gBAAK,EAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEzC,gCAAgC;QAChC,MAAM,OAAO,GAAG,MAAM,IAAA,kBAAO,EAAC,MAAM,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAE5E,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,mBAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACzC,IAAI,CAAC;gBACH,MAAM,IAAA,aAAE,EAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACvD,CAAC;YAAC,MAAM,CAAC;gBACP,mCAAmC;YACrC,CAAC;QACH,CAAC;QACD,MAAM,IAAA,aAAE,EAAC,MAAM,EAAE,MAAM,EAAE;YACvB,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ;YACE,EAAE,EAAE,IAAI;YACR,aAAa,EAAE,MAAM;YACrB,WAAW,EAAE,MAAM;SACpB,EACD,IAAI,EACJ,CAAC,CACF,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "private": false,
5
5
  "description": "CLI / SDK for AI项目管理",
6
6
  "main": "./dist/index.js",
@@ -5,7 +5,7 @@ description: 按分支 ID、分支名、基准分支、需求 ID、版本序号
5
5
 
6
6
  # APM 全自动开发(编排技能)
7
7
 
8
- **角色**:主 Agent 只做参数传递、**串行**启动子 Agent、校验上一步产物、失败则停止并汇总;**禁止**在同一对话里自己执行完整 propose+apply 长流程而不用子 Agent。
8
+ **角色**:主 Agent 只做参数传递、**串行**启动子 Agent、校验上一步产物、失败则停止并汇总(**例外见步骤 8/9**);**禁止**在同一对话里自己执行完整 propose+apply 长流程而不用子 Agent。
9
9
 
10
10
  **输入(必填)**
11
11
 
@@ -21,7 +21,7 @@ description: 按分支 ID、分支名、基准分支、需求 ID、版本序号
21
21
 
22
22
  ## 子 Agent 强制隔离
23
23
 
24
- - 下列步骤 **1~8** 各对应一次 **Task 子 Agent**(或等价:独立子会话),**严格串行**:仅当上一步子 Agent **明确结束**且主 Agent **已校验产物**后,再启动下一步。
24
+ - 下列步骤 **1~9** 各对应一次 **Task 子 Agent**(或等价:独立子会话),**严格串行**:仅当上一步子 Agent **明确结束**且主 Agent **已校验产物**后,再启动下一步(**步骤 8 发布失败时仍须启动步骤 9**,见步骤 8 说明)。
25
25
  - **禁止**并行启动多个子 Agent 执行本流程中的步骤。
26
26
  - 子 Agent 需执行完毕:读 SKILL、跑命令、写文件、回报结构化结果(路径、变更名、成功/失败)。
27
27
 
@@ -52,7 +52,7 @@ apm requirement version content --requirement-id <ID> --version-seq <SEQ>
52
52
  ```
53
53
 
54
54
  2. 解析 **stdout** JSON:取版本对象中的 **`content`** 字段(字符串)作为 PRD 正文。
55
- 3. 由正文推导目录名 `<name>`(**kebab-case**):优先取第一行 Markdown 标题(去 `#`)、否则取首行摘要;小写、空格与下划线改为 `-`,移除非 URL/路径安全字符;过长则截断至约 48 字符。若 `.apm/workitems/<name>` 已存在则加后缀 `-2`、`-3`… 直至不冲突。
55
+ 3. 由正文推导目录名 `<name>`(**kebab-case**):优先取第一行 Markdown 标题(去 `#`)、否则取首行摘要;小写、空格与下划线改为 `-`,移除非 URL/路径安全字符;过长则截断至约 48 字符。若 `.apm/workitems/<name>/prd.md` **已存在**,才加后缀 `-2`、`-3`… 直至找到一个 `prd.md` 不存在的目录;若仅目录存在但 `prd.md` 不存在,则直接使用该目录。
56
56
  4. 创建目录并**覆盖写入**:
57
57
 
58
58
  `.apm/workitems/<name>/prd.md`
@@ -69,7 +69,7 @@ apm requirement version content --requirement-id <ID> --version-seq <SEQ>
69
69
  2. 调用 CLI 更新分支状态为“开发中”,命令形如:
70
70
 
71
71
  ```bash
72
- apm requirement branch set-status --branch-id <BRANCH_ID> --status 开发中
72
+ apm requirement branch set-status --branch-id <BRANCH_ID> --status IN_DEVELOPMENT
73
73
  ```
74
74
 
75
75
  3. 子 Agent 需检查命令退出码,非 0 时读取 stderr,返回失败原因并终止全流程(不要静默继续后续步骤)。
@@ -91,7 +91,7 @@ apm requirement branch set-status --branch-id <BRANCH_ID> --status 开发中
91
91
  ## 步骤 5 — 子 Agent:openspec-apply-change
92
92
 
93
93
  1. 读取并遵循:`.cursor/skills/openspec-apply-change/SKILL.md`。
94
- 2. **输入(必须)**:上一步回报的变更目录路径或 **`<change-name>`**(与 openspec-propose 产出一致);主 Agent 必须将步骤 3 的结构化结果传入本子 Agent。
94
+ 2. **输入(必须)**:上一步回报的变更目录路径或 **`<change-name>`**(与 openspec-propose 产出一致);主 Agent 必须将步骤 4 的结构化结果传入本子 Agent。
95
95
  3. 按该 SKILL 执行任务直至完成或**硬阻塞**(硬阻塞时停止全流程,汇总原因)。
96
96
 
97
97
  **完成判定**:该 SKILL 定义的完成/暂停语义达成;代码与任务勾选与仓库状态一致。
@@ -120,13 +120,29 @@ apm requirement branch set-status --branch-id <BRANCH_ID> --status 开发中
120
120
 
121
121
  ---
122
122
 
123
- ## 步骤 8 — 子 Agent:调用 `frontend-test-env-release` 发布前端测试环境
123
+ ## 步骤 8 — 子 Agent:调用 `test-env-release` 部署测试环境
124
124
 
125
125
  1. 本步骤必须在“全部代码提交完成”后执行(即步骤 7 完成后)。
126
- 2. 调用技能 `frontend-test-env-release`,执行前端测试环境发布(构建 + 上传产物)。
127
- 3. 若发布失败,输出失败原因并将全流程标记为失败,不得宣称完成。
126
+ 2. 调用技能 `test-env-release`,按项目根目录 `.apm/deploy/README.md` 部署测试环境。
127
+ 3. **若部署失败**:必须输出失败原因并记录;**不得因此跳过或终止步骤 9**(仍须继续执行「待测试」状态更新)。
128
128
 
129
- **完成判定**:`frontend-test-env-release` 执行成功,前端测试环境发布完成。
129
+ **完成判定(本步骤自身)**:部署成功为理想结果;部署失败亦视为本步骤已结束(带失败信息),并进入步骤 9。
130
+
131
+ ---
132
+
133
+ ## 步骤 9 — 子 Agent:更新需求分支状态为待测试
134
+
135
+ 1. 在步骤 7 完成后执行;**与步骤 8 的成败无关**(步骤 8 即使失败也必须执行本步)。
136
+ 2. 在仓库根目录或任意目录执行(只依赖 apm 配置,不依赖当前 cwd):确保已通过 `apm login`,并已配置 `base-url`。
137
+ 3. 使用**必填输入**中的 `--branch-id`(`<BRANCH_ID>`),调用 CLI 将分支状态更新为「待测试」:
138
+
139
+ ```bash
140
+ apm requirement branch set-status --branch-id <BRANCH_ID> --status PENDING_TEST
141
+ ```
142
+
143
+ 4. 子 Agent 需检查命令退出码,非 0 时读取 stderr,返回失败原因并终止全流程(不要静默继续后续汇总)。
144
+
145
+ **完成判定**:命令成功返回(退出码 0),且无错误输出。
130
146
 
131
147
  ---
132
148
 
@@ -136,6 +152,8 @@ apm requirement branch set-status --branch-id <BRANCH_ID> --status 开发中
136
152
 
137
153
  - 分支名、`.apm/workitems/<name>/` 路径、`openspec/changes/<change-name>/`
138
154
  - 各子步骤成功/失败
155
+ - 步骤 8 测试环境部署结果(成功或失败原因;失败不阻断步骤 9)
156
+ - 步骤 9 分支是否已置为「待测试」
139
157
  - 最终 commit SHA(若有)、远程推送结果
140
158
  - 若有 stash:提醒用户在其他分支上 `git stash pop` 时注意冲突
141
159
 
@@ -143,6 +161,6 @@ apm requirement branch set-status --branch-id <BRANCH_ID> --status 开发中
143
161
 
144
162
  ## 护栏
145
163
 
146
- - 任一步子 Agent 失败:**不要**静默跳过;停止后续步骤,输出失败步骤与可复现命令。
164
+ - 任一步子 Agent 失败:**不要**静默跳过;停止后续步骤,输出失败步骤与可复现命令(**例外**:步骤 8 发布失败**不**停止步骤 9)。
147
165
  - 全程**不向用户追问**澄清需求;歧义按 openspec / apply 技能中的「合理假设、不反问」处理。
148
- - 步骤 8 未完成前,不得宣称全流程完成。
166
+ - **全流程交付完成**以步骤 9(分支已置为待测试)成功为准;步骤 8 发布失败仅作为告警项写入汇总,**不**单独阻断「交付完成」判定(但若步骤 9 失败,仍不得宣称全流程完成)。
@@ -128,13 +128,13 @@ apm requirement defect set-status --defect-id <defectId> --status RESOLVED
128
128
 
129
129
  **完成判定**:未提供 `defectId` 时本步骤被正确跳过;提供 `defectId` 时 CLI 返回成功且缺陷状态为 `RESOLVED`。
130
130
 
131
- ### 步骤 8 — 子 Agent:调用 `frontend-test-env-release` 发布前端测试环境
131
+ ### 步骤 8 — 子 Agent:调用 `test-env-release` 部署测试环境
132
132
 
133
133
  1. 本步骤必须在“全部代码提交完成”后执行(至少已完成步骤 4;若有推送要求则需先完成步骤 6)。
134
- 2. 调用技能 `frontend-test-env-release`,执行前端测试环境发布流程(构建 + 上传产物)。
135
- 3. 若发布失败,输出失败原因并将流程标记为失败,不得宣称 bug-fix 全流程完成。
134
+ 2. 调用技能 `test-env-release`,按项目根目录 `.apm/deploy/README.md` 部署测试环境。
135
+ 3. 若部署失败,输出失败原因并将流程标记为失败,不得宣称 bug-fix 全流程完成。
136
136
 
137
- **完成判定**:`frontend-test-env-release` 执行成功,前端测试环境发布完成。
137
+ **完成判定**:`test-env-release` 执行成功,测试环境部署完成。
138
138
 
139
139
  ## 约束
140
140
 
@@ -39,6 +39,7 @@ description: 依据用户提供的补充信息(如对评审的回复、澄清
39
39
  4. **消除重复**:同一议题在原文与补充信息中多处出现时,合并为**一处**表述。
40
40
  5. **可追溯(轻量)**:可选「修订说明」概括相对原文的变化,且**只写补充信息实际带来的变化**,不罗列未采纳的评审。
41
41
  6. **与仓库一致**:对照 `AGENTS.md`、`.apm/product-capability-inventory` 等,避免修订稿与用户已确认表述冲突;**禁止**用代码路径当需求论据。
42
+ 7. **图片引用保持原样**:若原文含图片(如 `<img ...>`),在修订稿中直接保留对应 `img` 标签原文;不要改写成“图片见原始文档”等占位说明。
42
43
 
43
44
  ## 输出
44
45
 
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: test-env-release
3
+ description: 部署测试环境。必须先阅读项目根目录下的 `.apm/deploy/README.md` 并按文档执行(文档不存在则终止,不猜测命令)。Use when 用户提到「部署测试环境」「测试环境部署」「发布测试环境」等与测试环境部署相关诉求。
4
+ ---
5
+
6
+ # 部署测试环境
7
+
8
+ ## 目标
9
+
10
+ 在目标项目根目录完成一次**可复现**的测试环境部署。所有具体命令、前置条件、校验方式**以项目内文档为准**,本技能不替代该文档。
11
+
12
+ ## 唯一权威:`.apm/deploy/README.md`
13
+
14
+ 1. **执行任何部署命令之前**,必须先使用 Read 工具阅读**项目根目录**下的:
15
+
16
+ `.apm/deploy/README.md`
17
+
18
+ 2. **若该文件不存在或无法读取**:立即终止,明确告知用户需在项目根目录补充 `.apm/deploy/README.md` 部署说明;**不要**用 README、package.json 或其它文件猜测部署方式。
19
+
20
+ 3. **严格按文档步骤执行**:文档中写明的命令、目录、环境变量、顺序即为执行依据;文档未提及的操作不要自行发明。
21
+
22
+ 4. 若文档要求先构建再发布/上传等:仅在文档允许的前提下,再参考文档中指向的其它路径(例如某子目录 README);仍**不得**绕过 `.apm/deploy/README.md` 中已写明的流程。
23
+
24
+ ## 失败处理
25
+
26
+ - 文档缺失或步骤无法执行:终止并说明缺少什么或哪一步失败。
27
+ - 某一步命令非 0 退出:按文档是否有「失败时」说明处理;若无,则终止并输出错误信息,不静默重试无关命令。
28
+
29
+ ## 成功判定
30
+
31
+ 以 `.apm/deploy/README.md` 中定义的「完成」或「验证」为准(例如健康检查、访问地址、接口返回等)。文档未写成功条件时,以文档列出的最后一步无错误执行完毕为准。
@@ -1,75 +0,0 @@
1
- ---
2
- name: frontend-test-env-release
3
- description: 执行客户端前端产物发布:先构建并在失败时立即终止,再自动识别分支名与产物目录并调用 apm publish 上传。Use when 用户提到“上传产物/发布前端产物/minio 上传/一键发布客户端前端”。
4
- ---
5
-
6
- # 发布测试环境
7
-
8
- ## 目标
9
-
10
- 在客户端机器执行一次可中断、可复现的发布流程:
11
-
12
- 1. `npm run build`(失败立即终止)
13
- 2. 自动识别分支名和产物目录后上传到服务端
14
-
15
- ## 输入
16
-
17
- - 项目根目录(默认当前目录)
18
- - 可选:用户手动指定产物目录(若提供则优先使用)
19
-
20
- ## 执行流程
21
-
22
- ### 1) 构建(失败即终止)
23
-
24
- 1. 在目标项目根目录执行:
25
-
26
- ```bash
27
- npm run build
28
- ```
29
-
30
- 2. 若退出码非 0:立即终止,不执行上传步骤,并输出失败原因。
31
-
32
- ### 2) 自动识别并上传
33
-
34
- #### 2.1 识别分支名
35
-
36
- 1. 获取当前分支:
37
-
38
- ```bash
39
- git rev-parse --abbrev-ref HEAD
40
- ```
41
-
42
- 2. 取最后一段作为上传分支名:
43
- - `feat/login` -> `login`
44
- - `feature/a/b` -> `b`
45
-
46
- #### 2.2 识别产物目录名
47
-
48
- 按以下优先级选择目录(命中即停止):
49
-
50
- 1. 用户显式提供的目录(如 `dist`)
51
- 2. 当前项目根目录下已存在且非空的:`dist`
52
- 3. 当前项目根目录下已存在且非空的:`build`
53
- 4. 当前项目根目录下已存在且非空的:`out`
54
- 5. 若以上均不存在:终止并报错“未找到构建产物目录”
55
-
56
- #### 2.3 上传
57
-
58
- 使用识别结果执行:
59
-
60
- ```bash
61
- apm publish --branch-name "<branchLastSegment>" --dir "<artifactDir>"
62
- ```
63
-
64
- ## 成功判定
65
-
66
- - `npm run build` 成功
67
- - `apm publish` 成功返回 `ok: true`
68
- - MinIO 目录满足:`<branchLastSegment>/<artifactDir>/...`
69
-
70
- ## 失败处理
71
-
72
- - 构建失败:直接结束,不进入上传
73
- - 分支识别失败:直接结束并提示检查 git 仓库状态
74
- - 目录识别失败:直接结束并提示显式传入目录
75
- - 上传失败:输出接口错误并结束