--- name: sap-cli description: "Use when you need to operate SAP ABAP development objects — syncing code, querying metadata, managing transports, reading tables, or any task involving SAP ADT REST API. Trigger on: ABAP objects, SAP development, transport requests, DDIC types, SE11/SE16N/SE38/SE80 equivalents, 'sync to SAP', 'download from SAP', 'activate ABAP', 'read SAP table'. NOT for developing sap-cli itself." version: "2.3.0" author: WuRangyu license: MIT --- # sap-cli — SAP ABAP 开发对象管理工具 sap-cli 是一个 Python CLI,封装 SAP ADT REST API,让你在终端完成 ABAP 开发对象的完整生命周期管理。 核心工作流:**download → 本地编辑 → sync 回 SAP** --- ## 首次使用:安装与配置 ### 第 1 步:安装 sap-cli 如果 `python main.py --help` 无法执行,先运行安装脚本: ```bash python /scripts/setup.py install ``` 此脚本会: 1. 安装依赖(`requests`) 2. 将 sap-cli 安装为可编辑的 Python 包 3. 创建配置文件模板 安装完成后验证: ```bash python main.py --help ``` ### 第 2 步:配置 SAP 连接 编辑配置文件 `assets/config.ini`(从 `config.ini.example` 复制): ```ini [SAP] host = http://your-sap-server:8000 client = 100 user = your_username password = your_password ``` 也可通过环境变量配置(优先级高于配置文件): - `SAP_HOST` / `SAP_CLIENT` / `SAP_USER` / `SAP_PASSWORD` ### 第 3 步:验证连接 ```bash python main.py config show python main.py transport list ``` --- ## 调用方式 ```bash cd /assets && python main.py [options] ``` 全局参数(在命令之前): | 参数 | 说明 | |------|------| | `--profile ` | 使用指定配置 profile | | `--verify-ssl` | 启用 SSL 验证(默认关闭) | --- ## 命令速查 ### CRUD(对象生命周期) ```bash # 创建新对象 python main.py create --name ZMY_CLASS --type class --corr_nr DEVK901XXX python main.py create --name ZMY_DOMAIN --type domain --definition domain.json --corr_nr DEVK901XXX # 查询元数据 python main.py info --name ZMY_CLASS --type class # 下载源码 python main.py download --name ZMY_CLASS --type class --path ./src # 同步到 SAP(lock → write → unlock → syntax check → activate) python main.py sync --name ZMY_CLASS --type class --path ./src/zmy_class.abap --corr_nr DEVK901XXX # 删除对象 python main.py delete --name ZMY_CLASS --type class # 单独激活(sap-cli 内置 NW 7.40 double-activate) python main.py activate --name ZMY_CLASS --type class --corr_nr DEVK901XXX # 单独上传(仅锁定→写入→解锁,不检查不激活) python main.py upload --name ZMY_CLASS --type class --path ./src/zmy_class.abap --corr_nr DEVK901XXX # 语法检查(检查远程对象,不上传不激活) python main.py syntax-check --name ZMY_CLASS --type class ``` **create 关键参数**: | 参数 | 说明 | |------|------| | `--description` | 对象描述 | | `--source <.abap>` | 自定义源码文件 | | `--definition <.json>` | DDIC 定义文件(domain/dataelement/table/structure/tabletype) | | `--package ` | SAP 包(默认 `$TMP`) | | `--corr_nr` | 传输请求号 | ### 批量操作 ```bash # 初始化项目结构 python main.py init --path ./my_project # 刷新对象状态 python main.py refresh --path ./my_project # 批量同步(自动按依赖拓扑排序) python main.py sync --all --path ./my_project --corr_nr DEVK901XXX python main.py sync --all --path ./my_project --corr_nr DEVK901XXX --dry-run ``` 依赖排序:`domain(10) → dataelement(20) → table(30) → tabletype(40) → interface(50) → class(60) → function(70) → report(80)` ### 数据查询 ```bash # 表结构(SE11 等价) python main.py show-table --name ZMY_TABLE # 表数据(SE16N 等价) python main.py read-table --name ZMY_TABLE python main.py read-table --name ZMY_TABLE --fields "FIELD1,FIELD2" --where "FIELD1 = 'X'" --max-rows 50 # 列出对象 python main.py list --type class --package ZSAPILOT # Where-Used python main.py whereused --name ZMY_CLASS --type class # 源码搜索 python main.py search --query "CALL FUNCTION 'Z_MY_FUNC'" ``` ### 远程执行 ```bash # 执行 ABAP 程序(SA38 等价) python main.py run-program --name ZSAPILOT_SETUP # 本地 vs SAP 差异 python main.py diff --name ZMY_CLASS --type class --path ./src/zmy_class.abap ``` ### 传输请求 ```bash python main.py transport list python main.py transport info --corr_nr DEVK901XXX python main.py transport release --corr_nr DEVK901XXX python main.py transport objects --corr_nr DEVK901XXX ``` ### 配置与认证 ```bash python main.py config show python main.py config list-profiles python main.py config set host s4h.example.com python main.py auth login # 密码保存到 keyring python main.py auth status ``` ### 其他 ```bash python main.py check --name ZMY_CLASS --type class # ATC 检查 python main.py format --name ZMY_CLASS --type class # Pretty Printer python main.py package create --name ZSAPILOT # 创建包 python main.py cds download --name ZMY_CDS --path ./src # CDS View python main.py analyze --path ./src # 依赖分析 python main.py scaffold --name ZMY_RPT --template alv-report # 项目模板 # 模板: alv-report, bapi-wrapper, interface-class, data-model ``` --- ## 支持的对象类型(16 种) | 分类 | 类型 | 有源码 | |------|------|--------| | 程序 | `report`, `include` | ✅ | | OOP | `class`, `interface` | ✅ | | 函数 | `function` | ✅ | | DDIC 基础 | `domain`, `dataelement`, `table`, `structure` | ✅ | | DDIC 扩展 | `cdsview`, `view` | ✅ | | DDIC 无源码 | `tabletype`, `messageclass`, `searchhelp`, `lockobject` | ❌ | | 程序组 | `functiongroup` | ❌ | **函数命名格式**:必须使用 `组名/模块名` 格式,如 `ZMY_FGROUP/Z_MY_FUNC` --- ## 常用工作流 ### 1. 单对象编辑同步 ```bash python main.py download --name ZMY_CLASS --type class --path ./src # 用编辑器修改 ./src/zmy_class.abap python main.py sync --name ZMY_CLASS --type class --path ./src/zmy_class.abap --corr_nr DEVK901XXX ``` ### 2. 批量项目同步 ```bash python main.py init --path ./my_project # 添加对象到 src/ 目录 python main.py sync --all --path ./my_project --corr_nr DEVK901XXX ``` ### 3. DDIC 对象创建 ```bash # 准备 JSON 定义文件 python main.py create --name ZMY_DOMAIN --type domain --definition domain.json --corr_nr DEVK901XXX ``` ### 4. 数据查询 ```bash python main.py show-table --name ZMY_TABLE # 结构 python main.py read-table --name ZMY_TABLE --max-rows 100 # 数据 ``` ### 5. 远程执行 ABAP 程序 ```bash python main.py run-program --name ZSAPILOT_SETUP ``` ### 6. 分步操作(上传→检查→激活) ```bash # 适合锁定冲突频繁的自动化场景:先安全上传,稍后再激活 python main.py upload --name ZMY_CLASS --type class --path ./src/zmy_class.abap --corr_nr DEVK901XXX # 修改表结构后验证关联程序语法 python main.py syntax-check --name ZDEPENDENT_REPORT --type report # 确认无问题后单独激活 python main.py activate --name ZMY_CLASS --type class --corr_nr DEVK901XXX ``` --- ## ⚠️ 使用约束(必须遵守) > 详细规则见 `references/sap-tool-constraints.md` 和 `references/error-handling.md` 1. **只使用 `python main.py <命令>` 操作 SAP** — 禁止用 requests、curl 直接调 ADT/SOAP 2. **禁止修改 SAP 标准对象**(`CL_*`、`SAPL*` 等)— 只允许只读操作 3. **禁止未授权操作系统表**(TADIR、E071、SEOCLASS 等)— SELECT 诊断可以 4. **sync 必须带 `--corr_nr`** — 否则触发交互提示 5. **非交互 delete 用管道确认** — `echo "yes" | python main.py delete ...`(否则 EOFError) --- ## 常见问题速查 | 问题 | 原因 | 解决 | |------|------|------| | HTTP 406(DDIC sync Lock) | NW 7.40 DDIC sync 路径 lock 仍 406(delete 已修复) | 报告用户 → SE09 手动同步 DDIC | | HTTP 403(Locked) | 残留 enqueue lock | 先试 `run-program` 清锁,不行 → SM12 | | HTTP 400(SaveFailure) | 类 DEFINITION 与 SAP 不一致 | 对比本地 vs SAP 源码 | | HTTP 404(DDIC download/sync) | NW 7.40 无 `/source/main` 端点(7.50+ 特性) | DDIC 对象只能 create/info/delete,不能 download/sync | | HTTP 423(Transport lock) | 对象绑定在传输请求中 | 报告用户 → SE09 | | 激活失败 | NW 7.40 ADT 限制 | sap-cli 内置 double-activate,仍失败 → SE09 | | `WITH EMPTY KEY` dump | NW 7.40 不支持 | 改用 `WITH NON-UNIQUE KEY` | | 函数名格式错误 | 缺少 `/` 分隔符 | 使用 `ZGROUP/Z_FUNC` 格式 | ## NW 7.40 兼容性(真实系统 E2E 验证 — v2.2.1) > 完整矩阵见 `docs/NW740-COMPATIBILITY.md` ### 完整可用(download → 编辑 → sync 全闭环) `report` · `class` · `interface` · `function` · `functiongroup` · `include` ### 仅 CRUD 可用(create/info/delete,无源码编辑) `domain` · `dataelement` — NW 7.40 的 DDIC 对象以 XML 存储于对象 URI,没有独立的 source/main 端点(7.50+ 特性)。即便 Eclipse ADT 在 7.40 上也无法编辑 DDIC 源码。 ### 端点缺失(代码已就位,待更高版本验证) `table` · `structure` · `tabletype` · `view` · `messageclass` · `searchhelp` · `lockobject` · `cdsview` — NW 7.40 ADT 端点层返回 404/415,请求未到达 XML 解析。 ### 其他 NW 7.40 特性 - **DDIC Lock**:delete 已修复(专用 Accept 头),sync 路径仍 406 - **激活误报**:首次激活可能报失败但实际成功,sap-cli 已内置 double-activate - **ABAP 语法限制**:不支持字符串模板 `\|...\|`、inline 声明 `DATA(...)`、`WITH EMPTY KEY` - **CSRF Token**:所有写操作必须携带,sap-cli 自动处理 --- ## 分发与安装(团队成员) ### 方式 1:Hermes Agent ```bash git clone ~/AppData/Local/hermes/skills/productivity/sap-cli python ~/AppData/Local/hermes/skills/productivity/sap-cli/scripts/setup.py all ``` ### 方式 2:Claude Code ```bash git clone ~/.claude/skills/sap-cli python ~/.claude/skills/sap-cli/scripts/setup.py all ``` 安装后验证: ```bash cd /assets && python main.py --help ```