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 重写为单源开发流程。
This commit is contained in:
吴让宇
2026-09-11 00:40:15 +08:00
parent e786742bcb
commit c5905a5b1e
104 changed files with 20744 additions and 10 deletions
+215
View File
@@ -0,0 +1,215 @@
---
title: ADT 架构与通信原理
created: 2026-05-18
tags:
- SAP
- ADT
- architecture
- REST
parent: "[[sap-cli/README|SAP ADT 学习笔记总览]]"
---
# ADT 架构与通信原理
> [!abstract] 核心洞察
> ADT 本质上是一个 **REST API 客户端**。SAP 通过在 ABAP 服务器上构建一套完整的 REST 层(`/sap/bc/adt/*`),然后开发 Eclipse 插件来消费这些 API,实现了前后端的完全解耦。
## 1. 三层架构模型
ADT 采用经典的 **客户端/服务器** 分层架构:
```
┌───────────────────────────────────────────────────────────┐
│ Layer 1: IDE 客户端层 (Eclipse / VS Code / 自定义客户端) │
│ │
│ • Eclipse ADT 插件(Java 实现) │
│ • VS Code 扩展(2026年起支持,复用 Eclipse 代码库) │
│ • 任何 HTTP 客户端(Python requests / JS fetch / AI Agent
│ • 客户端 UI 无关代码:2.9 百万行! │
└────────────────────────┬──────────────────────────────────┘
│ HTTP(S) + Basic Auth
┌───────────────────────────────────────────────────────────┐
│ Layer 2: REST 通信层 (/sap/bc/adt/*) │
│ │
│ • 基于 HTTP 协议的 RESTful API │
│ • 请求格式: XML / ATOM Feed / JSON │
│ • CSRF Token 机制(写操作必须先获取 Token) │
│ • 状态会话管理(Stateful HTTP Session
│ • 服务发现端点: /sap/bc/adt/discovery │
└────────────────────────┬──────────────────────────────────┘
│ ICF Handler 路由
┌───────────────────────────────────────────────────────────┐
│ Layer 3: SAP ABAP 后端 │
│ │
│ • ICF (Internet Communication Framework) 处理请求路由 │
│ • ADT REST Framework (增强点 SADT_REST_RFC_APPLICATION) │
│ • ABAP Runtime(语法检查、编译、激活) │
│ • Repository(仓库对象存储) │
│ • CTS(传输管理系统) │
│ • ATC(代码质量检查引擎) │
└───────────────────────────────────────────────────────────┘
```
## 2. REST 通信层详解
### 2.1 端点结构
所有 ADT 操作通过 `/sap/bc/adt/` 前缀的端点进行通信:
| 端点路径 | 功能 | 最低版本要求 |
|----------|------|-------------|
| `/sap/bc/adt/discovery` | 服务发现(Atom Feed | NW 7.31 SP04 |
| `/sap/bc/adt/repository` | 仓库对象搜索与浏览 | NW 7.31 SP04 |
| `/sap/bc/adt/oo` | 类与接口管理 | NW 7.31 SP04 |
| `/sap/bc/adt/programs` | 程序与 Include | NW 7.31 SP04 |
| `/sap/bc/adt/functions` | 函数组与函数模块 | NW 7.31 SP04 |
| `/sap/bc/adt/ddic` | ABAP Dictionary 访问 | NW 7.40 SP02 |
| `/sap/bc/adt/datapreview` | 表数据预览(SE16N 替代) | NW 7.40 SP05 |
| `/sap/bc/adt/cts` | 传输请求管理 | NW 7.40 SP02 |
| `/sap/bc/adt/activation` | 对象激活 | NW 7.31 SP04 |
| `/sap/bc/adt/atc` | ABAP Test Cockpit | NW 7.50+ |
### 2.2 通信协议特征
> [!important] 关键协议特征
**认证方式:**
- **Basic Authentication**(最常用)— 通过 HTTPS 发送用户名/密码
- **X.509 证书认证** — 生产环境推荐
- **SAP OAuth 2.0** — 高级场景
**CSRF Token 机制:**
```
1. 客户端发送 GET 请求,Header: x-csrf-token = "Fetch"
2. 服务器返回响应,Header 中包含 CSRF Token
3. 后续所有写操作(POST/PUT/DELETE)必须携带此 Token
4. Token 过期时(HTTP 403),重新获取并重试
```
**会话管理:**
- ADT 使用 **有状态的 HTTP 会话**Stateful Session
- 通过 Cookie 维持会话,用于对象锁定等操作
- `sap-client` Header 指定 SAP 客户端编号
**数据格式:**
- 请求/响应主要使用 **XML** 格式
- 部分端点支持 `text/plain`(源代码读写)
- 服务发现使用 **ATOM Feed** 格式
## 3. 服务发现机制
> [!tip] 核心概念
> ADT 采用 **服务发现** 模式,而非硬编码 URL。客户端可以通过 `/sap/bc/adt/discovery` 端点动态获取所有可用的服务及其 URI。
### 发现流程
```
1. 客户端请求 GET /sap/bc/adt/discovery
→ 返回 Atom Feed,列出所有已注册的服务集合
2. 每个服务集合包含:
- href: 服务的 URI 路径
- title: 服务的描述名称
- category: 服务的分类(scheme + term
3. 客户端根据 category scheme/term 查找需要的具体服务 URI
→ 避免硬编码,支持不同系统版本的兼容性
```
### 发现端点示例响应结构
```xml
<app:collection href="/sap/bc/adt/oo/classes">
<atom:title>Classes</atom:title>
<category scheme="http://www.sap.com/adt/..." term="classes"/>
</app:collection>
```
## 4. 后端扩展机制
### ADT REST Framework 的扩展点
SAP 提供了 **增强点 (Enhancement Spot)** 来扩展 ADT
| BAdI | 用途 |
|------|------|
| `BADI_ADT_DISCOVERY_PROVIDER` | 实现自定义发现提供者,注册新的 URI |
| `SADT_REST_RFC_APPLICATION` | 实现自定义 REST 资源处理 |
### 扩展架构
```
客户端请求
RFC HandlerADT REST Framework 核心)
├── 根据 URI 路径匹配对应的 BAdI 实现
├── 调用 Discovery Controller(发现控制器)
│ └── 提供 URI schema(如 /ztransportutils
└── 调用 Resource Controller(资源控制器)
└── 处理具体的 GET/POST/PUT/DELETE 操作
```
### 创建自定义 ADT 资源的步骤
1. **创建 Discovery Controller** — 继承 `CL_ADT_RES_APP_BASE`,定义 URI 路径
2. **注册 BAdI `BADI_ADT_REST_RFC_APPLICATION`** — 链接到 Discovery Controller
3. **创建 Resource Application** — 继承 `CL_ADT_DISC_RES_APP_BASE`
4. **创建 Resource Controller** — 继承 `CL_ADT_REST_RESOURCE`,实现 GET/POST 方法
5. **注册 BAdI `BADI_ADT_DISCOVERY_PROVIDER`** — 使资源可被发现
## 5. 架构演进:从 Eclipse 到 VS Code
> [!success] 架构演进策略(2025年 SAP 官方博客)
SAP 面临的核心挑战:
- **290万行** 客户端 UI 无关代码
- **88个** 独特的对象类型编辑器(仅 SAP BTP ABAP 环境)
### 解决方案 1Language Server 复用
借鉴 Java VS Code 扩展的思路 — 将 Eclipse ADT 插件 "包装" 为 Language Server
```
VS Code ←→ Language Server Protocol (LSP) ←→ Eclipse ADT 代码库 (2.9M 行)
```
- 无需从头重写客户端代码
- Eclipse 和 VS Code 共享同一代码库
- 连接任何 Eclipse 支持的 ABAP 服务器版本
### 解决方案 2Server-Driven Development
从 2020 年起,新对象类型采用 **服务器驱动开发** 模式:
- UI 逻辑完全在 ABAP 端定义(类似 Dynpro / Fiori Elements
- 客户端只需 **两个渲染引擎**
- **表单渲染器** — 用于表单类对象
- **源码渲染器** — 用于源码类对象
- 不再需要为每个 IDE 实现 88 个独立编辑器
## 6. 权限控制
| 权限对象 | 控制范围 |
|----------|---------|
| `S_ADT_RES` | 所有 ADT API 访问(端点级别) |
| `S_DEVELOP` | 对象读写操作 |
| `S_CTS_ADMI` | 传输管理 |
| `S_TRANSPRT` | 传输发布 |
## 🔗 相关笔记
- [[sap-cli/02.查询代码-原理|02.查询代码 - 原理]]
- [[sap-cli/03.修改代码-原理|03.修改代码 - 原理]]
- [[sap-cli/04.检查代码-原理|04.检查代码 - 原理]]
- [[sap-cli/05.提交与传输-原理|05.提交与传输 - 原理]]
## 📚 参考来源
- [Behind the Design: How We Transformed the ABAP Development Tools](https://community.sap.com/t5/technology-blog-posts-by-sap/behind-the-design-how-we-transformed-the-abap-development-tools/ba-p/14258121)
- [Creating an ABAP in Eclipse Plug-in Using the ADT SDK](https://community.sap.com/t5/application-development-and-automation-blog-posts/creating-a-abap-in-eclipse-plug-in-using-the-adt-sdk-part-2/ba-p/13093582)
- [End-to-End SAP Automation with ADT REST Services](https://medium.com/@onuryz.itu/end-to-end-sap-automation-with-adt-rest-services-and-ai-a-modern-alternative-to-gui-scripting-343ea86064ea)