Files
sap-cli-skill/SKILL.md
T

254 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: sap-cli
description: "SAP ABAP ADT CLI for AI agents. Trigger when: operating ABAP objects, syncing code to/from SAP, managing transports, querying DDIC, running ABAP programs, reading SAP tables, or any SAP development task via terminal."
version: "2.3.0"
author: WuRangyu
license: MIT
triggers:
- "ABAP development"
- "sync to SAP"
- "download from SAP"
- "SAP transport request"
- "DDIC/SE11/SE16N/SE38/SE80"
- "SAP ADT REST API"
---
# sap-cli — SAP ABAP Development Object Management
Python CLI wrapping the SAP ADT REST API. Manages the full lifecycle of ABAP development objects from the terminal. Core loop: **download → local edit → sync back to SAP**.
## Quick Start
```bash
# 1. Single object: download → edit → sync
python main.py download --name ZMY_CLASS --type class --path ./src
# edit ./src/zmy_class.abap
python main.py sync --name ZMY_CLASS --type class --path ./src/zmy_class.abap --corr_nr DEVK901XXX
# 2. Batch project sync (auto dependency-ordered)
python main.py init --path ./my_project # add objects under src/
python main.py sync --all --path ./my_project --corr_nr DEVK901XXX
# 3. Table query: structure (SE11) + data (SE16N)
python main.py show-table --name ZMY_TABLE
python main.py read-table --name ZMY_TABLE --fields "F1,F2" --where "F1 = 'X'" --max-rows 50
```
## Command Reference
Global params (before command): `--profile <name>`, `--verify-ssl`. Optional params in `[ ]`.
| Category | Command | Key Parameters |
|----------|---------|----------------|
| CRUD | `create` | `--name --type [--description --source <.abap> --definition <.json> --package <$TMP> --corr_nr]` |
| CRUD | `info` | `--name --type` [^1] |
| CRUD | `download` | `--name --type --path` |
| CRUD | `sync` | `--name --type --path --corr_nr` **(REQUIRED)** |
| CRUD | `delete` | `--name --type` |
| CRUD | `activate` | `--name --type --corr_nr` (built-in NW 7.40 double-activate) |
| CRUD | `upload` | `--name --type --path --corr_nr` (lock→write→unlock only; no check/activate) |
| CRUD | `syntax-check` | `--name --type` (remote object; no upload/activate) |
| Batch | `init` | `--path` |
| Batch | `refresh` | `--path` |
| Batch | `sync --all` | `--path --corr_nr [--dry-run]` |
| Batch | `analyze` | `--path` (dependency analysis) |
| Query | `show-table` | `--name` (SE11 structure) |
| Query | `read-table` | `--name [--fields --where --max-rows]` (SE16N data) |
| Query | `list` | `--type [--package --prefix]` |
| Query | `whereused` | `--name --type` |
| Query | `search` | `--query` |
| Query | `diff` | `--name --type --path` (local vs SAP) |
| Transport | `transport list` | — |
| Transport | `transport info` | `--corr_nr` |
| Transport | `transport release` | `--corr_nr` |
| Transport | `transport objects` | `--corr_nr` |
| Config | `config show` | — |
| Config | `config list-profiles` | — |
| Config | `config set` | `<key> <val>` |
| Config | `auth login` / `auth status` | password stored in keyring |
| Other | `run-program` | `--name` (SA38) |
| Other | `check` | `--name --type` (ATC) |
| Other | `format` | `--name --type` (Pretty Printer) |
| Other | `package create` | `--name` |
| Other | `cds download` | `--name --path` |
| Other | `scaffold` | `--name --template <t>` — alv-report, bapi-wrapper, interface-class, data-model |
[^1]: ⚠️ `info` 不返回 `package`/`packageRef` 字段。需通过 ADT API 查询:`GET /sap/bc/adt/programs/programs/<name>` 返回 XML 中含 `<adtcore:packageRef>`。也可用 `list --package <pkg>` 反向查找。
Batch sync dependency order: `domain(10) → dataelement(20) → table(30) → tabletype(40) → interface(50) → class(60) → function(70) → report(80)`.
Step-wise sync for lock-heavy automation — split the atomic `sync` when lock conflicts are frequent; upload now, verify, activate later:
```bash
python main.py upload --name ZMY_CLASS --type class --path ./src/zmy_class.abap --corr_nr DEVK901XXX # lock→write→unlock only
python main.py syntax-check --name ZDEPENDENT_REPORT --type report # verify dependents (no upload)
python main.py activate --name ZMY_CLASS --type class --corr_nr DEVK901XXX # activate once clean
```
### Supported Object Types (16)
| Category | Types | Has source |
|----------|-------|------------|
| Programs | `report`, `include` | ✅ |
| OOP | `class`, `interface` | ✅ |
| Functions | `function` | ✅ |
| DDIC base | `domain`, `dataelement`, `table`, `structure` | ✅ |
| DDIC ext | `cdsview`, `view` | ✅ |
| DDIC no-source | `tabletype`, `messageclass`, `searchhelp`, `lockobject` | ❌ |
| Groups | `functiongroup` | ❌ |
**Function naming**: must use `group/module`, e.g. `ZMY_FGROUP/Z_MY_FUNC`.
## ⚠️ Constraints (HARD RULES — DO NOT VIOLATE)
Full rules: `references/sap-tool-constraints.md`. Violations are intercepted by hooks.
质检标准: `references/abap-coding-rules.md`(38条规则,6大类:安全/性能/可维护性/错误处理/NW740兼容/风格。其中 E04/E05 强制:CALL FUNCTION 前必须核实被调对象存在、参数结构与真实签名一致,ADT 语法检查不覆盖被调对象,核实记录纳入交付物)。质检员在代码审计时以此文档为唯一标准,判定体系:✅合规 / ❌违反(必须修复) / ⚠️建议(推荐修复)。
1. **Only `python main.py <cmd>` touches SAP** — no `requests`/`urllib`, no curl to ADT/SOAP/RFC, no `python -c` inline, no importing `ADTClient` internals, no hand-built ADT XML. Exceptions: `run-program` custom reports, explicit user request, or developing sap-cli itself.
2. **Never modify SAP standard objects** (`CL_*`, `CX_*`, `IF_*`, `SAPL*`, or any non-user original system) — read-only only: download/info/list/search/whereused/show-table/read-table/diff. When unsure, ask the user.
3. **Never write system tables** (TADIR, E071, SEOCLASS, REPOSRC, D010SINF, T000, TDEVC, TSTC) — read-only SELECT is fine; any write needs explicit authorization.
4. **`sync` must carry `--corr_nr`** — otherwise it triggers an interactive transport-request prompt.
5. **Non-interactive `delete` needs piped confirm**`echo "yes" | python main.py delete ...` (else EOFError).
6. **DDIC `sync` failure on NW 7.40 (HTTP 406) is a system limit** — do not retry; report to the user for SE09.
## 🔄 Standard WorkflowSAP 对象操作标准流程)
> 所有 SAP 对象修改操作必须按此顺序执行,不得跳过或调整步骤顺序。
```
步骤1 info — 确认程序存在、已激活、关联请求号
├─ 有请求号 → 记录
└─ 无请求号 → transport list 找老板的请求号推荐
→ 无合适的则帮老板新建(含请求描述)
步骤2 download — 源码下载到本地
步骤3 五角色流水线:研究员 → 创作者 → 质检 → 老板批准
步骤4 建 Gitee 仓库(ADT 层级:src/包/类型/对象/)+ 同步确认请求号
└─ 请求号写入 doc 文档
步骤5 工程师改代码(本地,不 commit)
步骤6 请求号绑定对象(如 SE09 未自动绑定)
步骤7 sync --corr_nr → 语法检查 → 迭代修复 → 激活成功
└─ 全程带请求号,不要到编译阶段才关联
步骤8 激活成功 → git commit + tag → push
└─ git = 细粒度变更追溯 / 请求号 = 系统大版本管理
```
**核心原则:**
- info 同时查请求号,不单独处理
- 建 Gitee 仓库同时确认请求号,不滞后
- sync 全程带 `--corr_nr`,不等编译阶段补
- 只有激活成功才 git commit,不是每次本地改就提交
- git 管变更细节,请求号管系统大版本
## 📦 Gitee仓库规范
### 目录结构(ADT 层级)
每个 SAP 项目的 Gitee 仓库按 ADT 层级组织源码:
```
sap-<project-name>/
├── src/
│ └── <package>/ # SAP 包名(如 $ZIDTR
│ ├── report/ # 程序类型目录
│ │ └── ZXXX.abap # ABAP 源码(.abap 扩展名)
│ ├── class/
│ │ └── ZCL_XXX.abap
│ ├── interface/
│ │ └── ZIF_XXX.abap
│ ├── function/
│ │ └── ZGROUP_ZFUNC.abap
│ ├── domain/
│ ├── dataelement/
│ ├── table/
│ └── ...
├── doc/ # 文档(请求号记录、设计说明)
│ └── transport-<corr_nr>.md # 每次传输的请求号记录
├── references/ # 参照文档
└── log/ # 错误知识库
```
### 请求号同步确认
1. **创建仓库时**:确认传输请求号(`transport list``transport info --corr_nr DEVK9XXXXX`),写入 `doc/transport-<corr_nr>.md`
2. **每次 sync 前**:确认请求号仍有效(未释放、未满),检查 `transport objects --corr_nr DEVK9XXXXX` 确保对象已绑定
3. **激活成功后**:更新 `doc/` 记录本次变更摘要
4. **仓库命名建议**`sap-<package-name>`,小写、hyphen 分隔,如 `sap-zidtradmin`
### Git 提交时机
- **只有 `sync` 激活成功后才 git commit**,不是每次本地修改就提交
- commit message 包含:对象名 + 请求号 + 变更摘要
- tag 使用请求号命名:`DEVK9XXXXX`
- git 管变更细节追溯,请求号管系统大版本管理
## Error Handling (Quick Reference)
错误知识库: `log/` 目录(LLM-WIKI 格式),每个错误独立一页。**先查 log/,再查 `references/error-handling.md`**。新错误按 `log/SCHEMA.md` 规范入库。
Full flow: `references/error-handling.md`.
| Error Pattern | Action |
|---|---|
| HTTP 406 (DDIC Lock) | System limit — report to user → SE09 manual DDIC sync |
| HTTP 403 (Locked) | Residual enqueue lock — try `run-program` clear-locks report, then SM12 |
| HTTP 400 (SaveFailure) | Class DEFINITION mismatch — diff local vs SAP source |
| HTTP 404 (DDIC download/sync) | NW 7.40 has no `/source/main` endpoint (7.50+) — DDIC objects only create/info/delete |
| HTTP 423 (Transport lock) | Object bound to transport — report to user → SE09 |
| HTTP 500 (set_source) | Lock 成功但写入 500,传输请求中无对象 → SE09 手动添加对象到请求 → `log/adt-set-source-500.md` |
| Activate fails, still inactive | double-activate built-in; still fails → report → SE09 |
| Open SQL @ 转义不一致 | 语法检查 2 错误——一处用 `@` 则全局必须一致(`WHERE field = @lv_var``INTO TABLE @lt_data``log/adt-nw740-open-sql-consistency.md` |
| `WITH EMPTY KEY` dump | NW 7.40 unsupported — use `WITH NON-UNIQUE KEY` / `WITH DEFAULT KEY` |
| Function name error | Missing `/` separator — use `ZGROUP/Z_FUNC` |
| EOFError on delete | Non-interactive — prepend `echo "yes" \|` |
| Syntax: "此处不允许逗号" | NW 7.40 逗号陷阱(9种) → `log/adt-nw740-comma-traps.md` |
General flow: **diagnose** (params / file / transport / network / object existence) → **usage error**: fix & retry → **sap-cli limit**: report, never bypass → **SAP limit**: exhaust automation below → **confirmed un-automatable**: request SAP GUI op.
Automation fallbacks — exhaust in order before requesting any SAP GUI action:
1. **Adjust params** — different `--corr_nr`, or `--dry-run` to preview a batch before committing.
2. **`run-program` workaround** — sync + run a helper report (e.g. `ZSAPILOT_CLEAR_LOCKS`) to clear residual enqueue locks.
3. **`delete` + recreate** — only if the object needs a full rewrite; `delete` may fail with HTTP 423 (transport-bound) → then it is SE09.
4. **`activate` retry** — double-activate is built in; if it still fails, stop retrying and report — do not chase other activation strategies.
- **Never bypass sap-cli** (no requests / curl / ADTClient) — report the failure and its cause.
- **Give the complete change checklist at once** — do the full comparison first (`show-table` vs code field refs); never surface issues incrementally.
- **System-table writes** — 4-step authorization: explain *** → list exact statements → state risks & alternatives → await explicit approval.
## NW 7.40 Compatibility (E2E verified — v2.3.0)
Full matrix: `docs/NW740-COMPATIBILITY.md`.
| Availability | Types |
|---|---|
| Full (download → edit → sync closed loop) | `report`, `class`, `interface`, `function`, `functiongroup`, `include` |
| CRUD only (create/info/delete, no source edit) | `domain`, `dataelement` — DDIC stored as XML at object URI, no `/source/main` endpoint (7.50+ feature) |
| Endpoint missing (404/415) | `table`, `structure`, `tabletype`, `view`, `messageclass`, `searchhelp`, `lockobject`, `cdsview` |
NW 7.40 specifics:
- **DDIC Lock** — `delete` fixed (dedicated Accept header); `sync` still 406.
- **Activation false-negative** — first activate may report failure but actually succeed; double-activate is built in.
- **ABAP syntax limits** — no string templates `\|...\|`, no inline `DATA(...)`, no `WITH EMPTY KEY`.
- **Open SQL @ 转义一致性** — NW 7.40 要求一处用 `@` 则全 SQL 必须一致(`WHERE field = @lv_var``INTO TABLE @lt_data`),混用导致语法检查 2 错误。详见 `log/adt-nw740-open-sql-consistency.md`
- **set_source HTTP 500(传输请求无对象)** — Lock 成功但写入 500,根因:Lock API 创建锁句柄但未绑定对象到传输请求。NW 7.40 需 SE09 手动添加对象。详见 `log/adt-set-source-500.md`
- **CSRF token** — all writes require it; sap-cli handles automatically.
### DDIC 结构/表类型落地方案(NW 7.40 无 ADT 端点时)
`create --type structure|tabletype` 在 NW 7.40 报 404/415(端点缺失)。可用落地路径:自研落地报表 + `run-program`
1. `upload` 一个工具报表到 `$TMP`,内部调 `DDIF_TABL_PUT`(结构)/ `DDIF_TTYP_PUT`(表类型)写 DDIC,再调 `DDIF_TABL_ACTIVATE` / `DDIF_TTYP_ACTIVATE` 激活
2. `run-program --name <工具报表>`
3. `read-table DD02L`(结构)/ `DD40L`(表类型)实查确认 `AS4LOCAL = 'A'`
踩坑(S4T 实测):
- **`DD_OBJ_ACTIVATOR` 会转储** — 必须用 `DDIF_TABL_ACTIVATE` / `DDIF_TTYP_ACTIVATE`
- **`run-program` 端点不稳定** — 一次性批量生成全部结构的工具会反复 500/转储;**逐个落**才稳态
- **结构不写 TADIR** — 落地后的结构在 DD02L/DD40L 可见但 TADIR 查不到,清点必须查字典表,不能用 TADIR 代替
- **清理脚手架用 `delete`** — 需 `echo "yes" \|` 管道确认(见约束 5);删完用 TADIR/DD02L 独立复核,不采信 delete 回显