Files
sap-cli-skill/docs/OPERATION_MANUAL.md
吴让宇 c5905a5b1e refactor: 本仓升为唯一源(原 sap-cli 源码仓归档)
方向反转:此前 SKILL.md 是「模板渲染产物」、sap-cli 是源;现 sap-cli 归档,
sap-cli-skill 承接开发与分发,SKILL.md 回归手工维护的正本。

迁移(来自 sap-cli,共 104 文件):
- tests/           692 例测试(15 个文件的内联 sys.path 改指 assets/)
- openspec/        SDD 规格与归档变更(42 文件)
- docs/            开发文档与 ADT 原理(含 dev/CLAUDE.md、AGENTS.md)
- .claude/         rules 副本 + settings.json(供 Claude Code)
- .github/ .hermes/ .pre-commit-config.yaml .editorconfig CLAUDE.md
- scripts/ 保持仅 setup.py(pack_skill.py 已随旧仓归档,不迁)

修复(迁移暴露的真实缺陷):
- assets/pyproject.toml 的 build-backend 写作 `setuptools.backends._legacy:_Backend`,
  该模块在 setuptools 中不存在 → `pip install -e` 从来装不上。改为 build_meta。
  实测:临时 venv 安装成功,sap-cli --help 正常列出 31 个命令
- pyproject readme 指向不存在的 assets/README.md(editable 安装会失败)→ 改内联文本
- pyproject urls 改指 sap-cli-skill

机制调整:
- .github/workflows/ci.yml 适配 assets/ 布局;顶部注明该工作流仅 GitHub 执行,
  本仓在 Gitee 不会自动跑
- pre-commit 增本地测试门禁(Gitee 上真正生效的那道)
- .gitignore 合并旧仓完整规则(保留 log/ 下 md 知识库入库,只忽略运行日志)
- 大文件上限 100KB→1MB(架构图 512KB)

守卫测试 tests/unit/test_repo_guards.py(10 → 18 例):
- SKILL.md 须记录 parser 全部 CLI 命令 / 铁律 1-5 须为真实小节标题 / 示例不得违反铁律 5
- references/ 规则齐备;.claude/rules 与 references 必须一致(实测抓到一次真实漂移)
- VERSION == sapcli.__version__ == README 版本
- 仓内不得再出现 pack_skill.py / skill-src(防废弃流程回潮)

698 tests OK;editable 安装与 CLI 入口经临时 venv 实测通过。
docs/RELEASING.md 重写为单源开发流程。
2026-09-11 00:40:15 +08:00

690 lines
21 KiB
Markdown
Raw Permalink 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.
# sap-cli 操作手册
> 版本 2.3.0 · 最后更新 2026-08-06
---
## 目录
1. [项目概述](#1-项目概述)
2. [项目结构](#2-项目结构)
3. [安装与配置](#3-安装与配置)
4. [日常使用:命令速查](#4-日常使用命令速查)
5. [典型工作流](#5-典型工作流)
6. [测试管理](#6-测试管理)
7. [版本与发布](#7-版本与发布)
8. [开发指南](#8-开发指南)
9. [故障排查](#9-故障排查)
---
## 1. 项目概述
**sap-cli** 是一个基于 SAP ADT REST API 的 ABAP 开发对象管理工具。
**能做什么:**
- 从 SAP 系统下载/上传 ABAP 源代码
- 在本地编辑器编写 ABAP,一键同步到 SAP 并激活
- 批量管理项目(init → sync --all → refresh
- 16 种 SAP 对象类型(report/class/table/CDS View 等)
- 传输请求管理、代码搜索、依赖分析
**基本信息:**
- 仓库地址:https://gitee.com/markwury168/sap-cli
- 本地路径:`D:\Codespace\sap-cli\`
- 运行方式:`python main.py <命令>``sap-cli <命令>`(安装后)
- Python 版本:≥ 3.10
---
## 2. 项目结构
```
D:\Codespace\sap-cli\
├── main.py # 入口文件(python main.py <命令>
├── config.ini # SAP 连接配置(不入库,含密码)
├── config.ini.example # 配置模板
├── pyproject.toml # 项目构建配置 + 版本号
├── requirements.txt # 依赖(备用,首选 pyproject.toml
├── README.md # 项目介绍 + 快速上手
├── FEATURES.md # 功能全景文档
├── CHANGELOG.md # 版本变更记录
├── CONTRIBUTING.md # 协作规范
├── LICENSE # MIT 许可
├── sapcli/ # 源码包(核心代码)
│ ├── __init__.py # 版本号 __version__ = "2.3.0"
│ ├── cli/ # CLI 层(参数解析 + 入口路由)
│ │ ├── parser.py # 228 行 — argparse 命令定义
│ │ ├── app.py # 159 行 — main() 入口 + 命令路由
│ │ └── output.py # 50 行 — 彩色输出工具
│ ├── client/ # API 层(SAP ADT 通信)— Mixin 架构
│ │ ├── _base.py # 88 行 — 连接、认证、通用请求
│ │ ├── _source.py # 354 行 — 源码读写、锁定、激活
│ │ ├── _transport.py # 203 行 — 传输请求管理
│ │ ├── _search.py # 197 行 — 搜索、Where-Used
│ │ ├── _ddic.py # 639 行 — 对象创建/删除/DDIC
│ │ └── __init__.py # 29 行 — ADTClient = 5个Mixin组合
│ ├── commands/ # 命令层(业务逻辑)
│ │ ├── crud.py # 890 行 — download/sync/delete/info/create
│ │ ├── batch.py # 328 行 — init/sync-all/refresh
│ │ ├── search.py # 147 行 — list/whereused/search
│ │ ├── transport.py # 136 行 — 传输请求操作
│ │ ├── cds.py # 186 行 — CDS View 操作
│ │ ├── package_cmd.py # 107 行 — ABAP 包管理
│ │ ├── quality.py # 131 行 — ATC 检查/格式化
│ │ ├── diff_cmd.py # 89 行 — 代码差异对比
│ │ ├── analyze.py # 126 行 — 依赖分析
│ │ ├── scaffold.py # 251 行 — 项目模板
│ │ ├── config_cmd.py # 106 行 — 配置管理
│ │ └── __init__.py # 69 行 — 统一导出
│ ├── config.py # 95 行 — 配置加载
│ ├── auth.py # 124 行 — 密钥管理(keyring
│ ├── password.py # 76 行 — 密码解析(从 auth 拆出)
│ ├── types.py # 243 行 — 16 种对象类型定义
│ ├── manifest.py # 174 行 — 项目清单管理
│ ├── scanner.py # 121 行 — 项目目录扫描
│ ├── sorter.py # 152 行 — 拓扑排序
│ ├── ddic.py # 277 行 — DDIC XML 构建
│ ├── exceptions.py # 77 行 — 异常体系
│ └── utils/ # 工具函数
│ ├── xml_utils.py # 13 行 — XML 转义
│ └── __init__.py
├── tests/ # 测试(412 用例,84% 覆盖率)
│ ├── test_sapcli.py # 68 个 — 基础层测试
│ └── unit/ # 单元测试
│ ├── test_client.py # 82 个 — API 层测试
│ ├── test_commands.py # 45 个 — 命令层测试
│ ├── test_commands_extra.py # 64 个 — 命令边界场景
│ ├── test_cli.py # 41 个 — 参数解析测试
│ ├── test_batch_analyze.py # 40 个 — 批量操作+分析
│ ├── test_modules.py # 58 个 — 散落模块测试
│ └── test_app_config.py # 14 个 — 入口+配置测试
├── docs/ # 文档
│ ├── guide.md # 详细使用指南(24KB)
│ ├── adt/ # 7 篇 ADT 原理文章
│ └── dev/ # 开发文档
│ ├── architecture.md # 架构说明
│ ├── CLAUDE.md # AI 协作规范
│ ├── AGENTS.md # AI Agent 规范
│ ├── test-plan.md # 测试方案
│ └── test-coverage-report.md # 覆盖率报告
├── openspec/ # OpenSpec SDD 规范
│ ├── specs/ # 7 个领域的需求规格
│ └── changes/ # 变更记录(已归档)
├── .github/workflows/ci.yml # CI 自动测试
├── .editorconfig # 编辑器统一配置
├── .pre-commit-config.yaml # Git 提交前自动检查
└── .gitignore # Git 忽略规则
```
### 架构分层
```
用户输入
main.py → cli/app.py → cli/parser.py ← CLI 层:解析参数
commands/*.py ← 命令层:业务逻辑
client/*.py (Mixin) ← API 层:SAP ADT 通信
config.py / types.py / manifest.py / ... ← 基础层:工具与配置
```
---
## 3. 安装与配置
### 3.1 首次安装
```bash
cd D:\Codespace\sap-cli
# 安装项目(开发模式,代码修改立即生效)
pip install -e .
# 安装可选依赖(密码安全存储)
pip install -e ".[keyring]"
# 安装开发依赖(测试工具)
pip install -e ".[dev]"
```
安装后可以直接使用 `sap-cli` 命令(无需 `python main.py`)。
### 3.2 SAP 连接配置
**方式一:配置文件(推荐)**
复制模板并填写你的 SAP 系统信息:
```bash
cp config.ini.example config.ini
```
编辑 `config.ini`
```ini
[SAP]
host = http://your-sap-server:8000
client = 100
user = your_username
password = your_password
; 多系统配置(用 --profile 切换):
[DEV]
host = http://dev-sap:8000
client = 100
user = dev_user
password = dev_password
[QAS]
host = http://qas-sap:8000
client = 200
user = qas_user
password = qas_password
```
> ⚠️ `config.ini` 包含密码,已在 `.gitignore` 中排除,**绝不要提交到 Git**。
**方式二:环境变量**
```bash
set SAP_HOST=http://your-sap:8000
set SAP_CLIENT=100
set SAP_USER=your_username
set SAP_PASSWORD=your_password
```
**方式三:keyring 安全存储**
```bash
python main.py auth login
# 输入 host / client / user / password 后,密码存入系统密钥环
python main.py auth status # 查看状态
python main.py auth logout # 删除密码
```
**密码优先级:** 环境变量 > keyring > config.ini
### 3.3 多系统切换
```bash
# 默认使用 [SAP] 配置
python main.py download --name ZTEST --type report --path ./out
# 切换到 [DEV] 系统
python main.py --profile DEV download --name ZTEST --type report --path ./out
# 切换到 [QAS] 系统
python main.py --profile QAS info --name ZCL_MY --type class
```
### 3.4 SSL 证书
默认关闭 SSL 验证(SAP 开发环境通常使用自签名证书)。如果你的 SAP 系统有正式证书:
```bash
python main.py --verify-ssl download --name ZTEST --type report --path ./out
```
---
## 4. 日常使用:命令速查
### 4.1 全局参数
| 参数 | 说明 | 示例 |
|------|------|------|
| `--config` | 指定配置文件路径 | `--config ./my.ini` |
| `--profile` / `-p` | 切换系统配置 | `--profile DEV` |
| `--verify-ssl` | 启用 SSL 证书验证 | `--verify-ssl` |
### 4.2 支持的 16 种对象类型
```
report class interface function functiongroup
domain dataelement table structure tabletype
include cdsview messageclass view searchhelp lockobject
```
### 4.3 命令一览(20 个)
#### 核心操作
| 命令 | 用途 | 示例 |
|------|------|------|
| **download** | 下载 SAP 对象源码到本地 | `python main.py download --name ZTEST --type report --path ./out` |
| **sync** | 上传本地代码到 SAP 并激活 | `python main.py sync --name ZTEST --type report --path ./ztest.abap` |
| **create** | 在 SAP 创建新对象 | `python main.py create --name ZTEST --type report` |
| **delete** | 从 SAP 删除对象 | `python main.py delete --name ZTEST --type report` |
| **info** | 查询对象元数据 | `python main.py info --name ZCL_MY --type class` |
#### 批量项目管理
| 命令 | 用途 | 示例 |
|------|------|------|
| **init** | 初始化项目清单 | `python main.py init --path ./my_project` |
| **refresh** | 刷新清单中的 SAP 状态 | `python main.py refresh --path ./my_project` |
#### 批量同步模式
```bash
# 批量同步所有对象
python main.py sync --all --path ./my_project
# 预览模式(不实际操作)
python main.py sync --all --path ./my_project --dry-run
# 遇到失败立即停止
python main.py sync --all --path ./my_project --fail-fast
# 指定传输请求号
python main.py sync --name ZTEST --type report --path ./ztest.abap --corr_nr DEVK901362
```
#### 搜索与浏览
| 命令 | 用途 | 示例 |
|------|------|------|
| **list** | 列出 SAP 对象 | `python main.py list --type report --prefix Z*` |
| **whereused** | Where-Used 引用查询 | `python main.py whereused --name ZTEST --type report` |
| **search** | 源代码搜索 | `python main.py search --query "CALL FUNCTION"` |
| **analyze** | 依赖自动分析 | `python main.py analyze --path ./my_project` |
#### 传输管理
```bash
python main.py transport list # 列出可修改的传输请求
python main.py transport info --corr_nr DEVK901362 # 查看传输详情
python main.py transport release --corr_nr DEVK901362 # 释放传输
python main.py transport objects --corr_nr DEVK901362 # 列出传输中的对象
```
#### 代码质量
| 命令 | 用途 | 示例 |
|------|------|------|
| **check** | ATC 代码检查 | `python main.py check --name ZTEST --type report` |
| **format** | ABAP Pretty Printer | `python main.py format --name ZTEST --type report` |
| **diff** | 本地 vs SAP 差异 | `python main.py diff --name ZTEST --type report --path ./ztest.abap` |
#### CDS View
```bash
python main.py cds download --name ZMY_CDS --path ./out # 下载 DDL
python main.py cds sync --name ZMY_CDS --path ./ddl.abap # 同步 DDL
python main.py cds create --name ZMY_CDS # 创建 CDS
```
#### 包管理
```bash
python main.py package create --name ZMY_PKG --description "我的包" # 创建
python main.py package info --name ZMY_PKG # 查看
python main.py package list --name ZMY_PKG # 列出对象
```
#### 项目模板
```bash
# 列出可用模板
python main.py scaffold --name ZTEST
# 使用指定模板
python main.py scaffold --name ZTEST --template alv-report # ALV 报表
python main.py scaffold --name ZTEST --template bapi-wrapper # BAPI 封装
python main.py scaffold --name ZTEST --template interface-class # 接口类
python main.py scaffold --name ZTEST --template data-model # 数据模型
```
#### 配置与认证
```bash
python main.py config show # 显示当前配置
python main.py config list-profiles # 列出所有 profile
python main.py config set host http://new-host:8000 # 修改配置
python main.py auth login # 保存密码到 keyring
python main.py auth logout # 删除密码
python main.py auth status # 查看状态
```
---
## 5. 典型工作流
### 工作流 A:下载 → 编辑 → 同步
```bash
# 1. 下载 SAP 对象源码
python main.py download --name ZMY_REPORT --type report --path ./src
# 2. 用你喜欢的编辑器修改 ./src/zmy_report.abap
# 3. 同步回 SAP 并激活
python main.py sync --name ZMY_REPORT --type report --path ./src/zmy_report.abap
```
### 工作流 B:新建项目 + 批量开发
```bash
# 1. 创建项目目录结构
mkdir my_project
mkdir my_project\reports my_project\classes my_project\functions
# 2. 在各目录下编写 .abap 文件
# 3. 初始化项目清单(扫描目录 → 查询 SAP → 写 manifest.json
python main.py init --path ./my_project
# 4. 批量同步到 SAP
python main.py sync --all --path ./my_project
# 5. 后续修改后再次同步
python main.py sync --all --path ./my_project
# 6. 刷新 SAP 状态
python main.py refresh --path ./my_project
```
### 工作流 C:使用模板快速创建
```bash
# 1. 生成 ALV 报表模板
python main.py scaffold --name ZALV_DEMO --template alv-report --path ./my_project
# 2. 编辑生成的文件
# my_project/reports/zalv_demo.abap
# 3. 初始化 + 同步
python main.py init --path ./my_project
python main.py sync --all --path ./my_project
```
### 工作流 DDDIC 对象管理
```bash
# 创建 DDIC 对象(需要 JSON 定义文件)
python main.py create --name ZMY_DOMAIN --type domain --definition ./domain_def.json
python main.py create --name ZMY_TABLE --type table --definition ./table_def.json
# 创建时指定包和传输请求
python main.py create --name ZMY_CLASS --type class --package ZMY_PKG --corr_nr DEVK901362
```
### 项目目录命名规范
批量模式时,scanner 按目录名识别对象类型:
| 目录名 | 对象类型 |
|--------|---------|
| `reports/` | report |
| `classes/` | class |
| `interfaces/` | interface |
| `functions/` | function(子目录 = 函数组名) |
| `domains/` | domain |
| `dataelements/` | dataelement |
| `tables/` | table |
| `structures/` | structure |
| `tabletypes/` | tabletype |
| `includes/` | include |
| `cdsviews/` | cdsview |
| `messageclasses/` | messageclass |
| `views/` | view |
| `searchhelps/` | searchhelp |
| `lockobjects/` | lockobject |
函数组特殊结构:
```
functions/
└── zmy_group/ ← 函数组名(子目录名)
├── zfunc1.abap ← 函数模块
└── zfunc2.abap
```
---
## 6. 测试管理
### 6.1 运行测试
```bash
cd D:\Codespace\sap-cli
# 运行全部测试(412 用例)
python -m unittest discover -s tests -p "test_*.py"
# 运行单个测试文件
python tests/unit/test_client.py
python tests/test_sapcli.py
# 运行特定测试类
python -m unittest tests.unit.test_cli.TestParserDownload
# 运行特定测试方法
python -m unittest tests.unit.test_client.TestADTClient.test_login_success
```
### 6.2 查看覆盖率
```bash
# 安装 coverage
pip install coverage
# 运行测试并收集覆盖率
coverage run -m unittest discover -s tests -p "test_*.py"
# 查看终端报告
coverage report --include="sapcli/*"
# 生成 HTML 报告(浏览器打开)
coverage html --include="sapcli/*"
# 报告在 tests/coverage_html/index.html
```
### 6.3 测试文件说明
| 文件 | 用例数 | 覆盖内容 |
|------|--------|----------|
| `test_sapcli.py` | 68 | 基础层(types/config/exceptions/manifest |
| `test_client.py` | 82 | API 层(ADTClient 全部方法) |
| `test_commands.py` | 45 | 命令层(各命令 happy path |
| `test_commands_extra.py` | 64 | 命令层(边界场景/错误处理) |
| `test_cli.py` | 41 | 参数解析(全部 20 个命令) |
| `test_batch_analyze.py` | 40 | 批量操作 + 依赖分析 |
| `test_modules.py` | 58 | 散落模块(scanner/sorter/auth/password |
| `test_app_config.py` | 14 | CLI 入口 + 配置命令 |
### 6.4 当前覆盖率(84%
```
100% — parser, manifest, exceptions, utils, commands/__init__
96%+ — batch, sorter, scanner, scaffold, types, config
90%+ — search, transport, client (各 Mixin)
80%+ — app, auth, config_cmd, ddic, quality
60%+ — crud, output
```
---
## 7. 版本与发布
### 7.1 版本号在哪
版本号 **只在一个地方维护**
```
sapcli/__init__.py → __version__ = "2.3.0"
```
`pyproject.toml` 通过动态读取自动同步:
```toml
[tool.setuptools.dynamic]
version = {attr = "sapcli.__version__"}
```
**升级版本只需改 `sapcli/__init__.py` 中的 `__version__`。**
### 7.2 发布流程
```bash
# 1. 修改版本号
# 编辑 sapcli/__init__.py → __version__ = "2.2.0"
# 2. 更新 CHANGELOG.md
# 3. 提交
git add -A && git commit -m "release: v2.2.0"
# 4. 打标签
git tag v2.2.0
# 5. 推送
git push --tags
```
### 7.3 Git 操作常用命令
```bash
# 查看状态
git status
# 查看历史
git log --oneline -10
# 提交代码
git add -A
git commit -m "feat: 新增 xxx 功能"
git push
# 回退未提交的修改
git checkout -- .
# 查看 config.ini 是否被误加入暂存
git ls-files | grep config.ini
```
---
## 8. 开发指南
### 8.1 添加新命令
**步骤:**
1.`sapcli/commands/` 下新建或修改命令文件:
```python
# sapcli/commands/my_cmd.py
import argparse
from sapcli.client import ADTClient
def cmd_my_command(args: argparse.Namespace, client: ADTClient) -> None:
"""我的新命令。"""
print(f"执行 my-command: {args.name}")
```
2. 在 `sapcli/commands/__init__.py` 中导出:
```python
from sapcli.commands.my_cmd import cmd_my_command
```
3. 在 `sapcli/cli/parser.py` 的 `build_parser()` 中添加子命令定义
4. 在 `sapcli/cli/app.py` 的 `command_map` 中注册路由
5. 写测试 → 运行测试
### 8.2 添加新对象类型
在 `sapcli/types.py` 中注册:
```python
_TYPE_REGISTRY["mytype"] = ObjectTypeConfig(
obj_type="mytype",
program_type="MYT",
adt_type="MYT",
adt_uri="mytypes",
# ...
)
```
然后在 `scanner.py` 的 `DIRECTORY_TYPE_MAP` 和 `sorter.py` 的 `TYPE_PRIORITY` 中补充。
### 8.3 代码风格
- Python PEP 8
- `.editorconfig` 已配置:4 空格缩进,UTF-8,LF 换行
- pre-commit hooks 自动检查(安装后运行 `pre-commit install`
### 8.4 新增 API 方法
API 方法在 `sapcli/client/` 目录的 Mixin 模块中:
| 功能域 | 文件 | 示例方法 |
|--------|------|---------|
| 连接/认证 | `_base.py` | login, object_exists |
| 源码读写 | `_source.py` | get_source, set_source, lock, unlock |
| 传输管理 | `_transport.py` | list_transport_requests, transport_release |
| 搜索查询 | `_search.py` | list_objects, where_used, search_code |
| 对象操作 | `_ddic.py` | create_object, delete_object, create_ddic_object |
添加新方法时,放在对应 Mixin 文件中即可。`ADTClient` 类自动继承所有 Mixin。
---
## 9. 故障排查
### 常见问题
| 问题 | 原因 | 解决 |
|------|------|------|
| `✗ 配置文件不存在` | 没有 config.ini | 复制 `config.ini.example` 为 `config.ini` 并填写 |
| `✗ 登录失败` | SAP 地址/密码错误 | 检查 config.ini 中的 host/user/password |
| `✗ 对象不存在` | 名称或类型不对 | 检查大小写,SAP 对象名通常大写 |
| `SSL 证书错误` | SAP 自签名证书 | 默认已关闭验证,检查是否误加 `--verify-ssl` |
| `keyring 不可用` | 未安装 keyring | `pip install keyring` |
| `config.ini 入了 Git` | 误提交 | `git rm --cached config.ini && git commit` |
### 日志文件
运行日志自动写入 `log/adt_tools.log``.gitignore` 已排除)。
### 调试技巧
```bash
# 查看完整错误堆栈
python main.py download --name ZTEST --type report --path ./out 2>&1 | more
# 查看日志
cat log/adt_tools.log | tail -50
# 验证配置是否正确
python main.py config show
# 验证连接是否可用
python main.py list --type report --prefix Z*
```
---
## 附录:版本历史
| 版本 | 日期 | 关键变更 |
|------|------|---------|
| v2.1.0 | 2026-06-09 | 全面重构:20 命令、16 类型、Mixin 架构、412 测试 |
| v2.0.0 | 2026-06-08 | OpenSpec SDD 重构、项目结构整理 |
| v1.0.0 | 2026-05 | 初始版本 |
> 详细变更记录见 `CHANGELOG.md`