- 修复 SfApexClass、SfApexTrigger、SfMetadataContainer、SfContainerAsyncRequest、SfDeployDetails 类的字段冲突 - 移除与父类冲突的字段,直接使用父类方法 - 优化 DeploymentManager 的 parseCompilationErrors 方法,直接处理 DeployMessage[] - 优化 MetadataContainerManager 的日期处理,直接使用 Calendar 类型 - 添加相关设计文档、提示词、复盘和会话记录
14 KiB
API 文档
元数据
- 需求编号:014-4
- 创建时间:2026-01-27
- 创建人:SSOT 架构师
- 状态:已完成
API 概述
本 API 提供了元数据容器与原子性部署功能,基于 Salesforce Tooling API 的 MetadataContainer 机制,支持元数据容器生命周期管理、容器成员管理、异步部署请求和状态轮询与结果解析。
核心功能
- 元数据容器生命周期管理:创建容器、删除容器、查询容器、获取容器详情
- 容器成员管理:添加成员到容器,支持多种元数据类型
- 异步部署请求:创建部署请求,支持 CheckOnly 模式和测试执行
- 状态轮询与结果解析:查询部署状态、轮询部署状态、获取部署详情、解析编译错误、解析测试结果
技术栈
- Spring Boot 3.5.7
- 若依框架
- Salesforce WSC 0.0.1
基础路径
- 元数据容器管理:
/tooling/metadata-container - 部署管理:
/tooling/deployment
统一响应格式
所有 API 接口均返回统一的响应格式:
{
"code": 200,
"msg": "操作成功",
"data": {}
}
| 字段名 | 类型 | 说明 |
|---|---|---|
| code | Integer | 状态码(200 成功,其他失败) |
| msg | String | 提示信息 |
| data | Object | 返回数据 |
接口列表
1. 创建容器接口
功能描述
创建一个新的元数据容器,用于存放待部署的元数据成员。
请求方式
POST
请求路径
/tooling/metadata-container/create
请求权限
tooling:container:create
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | String | 是 | 容器名称,长度 1-255 字符 |
请求示例
{
"name": "MyContainer"
}
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| id | String | 容器 ID |
| name | String | 容器名称 |
| createdDate | String | 创建时间 |
| lastModifiedDate | String | 最后修改时间 |
成功示例
{
"code": 200,
"msg": "操作成功",
"data": {
"id": "a0B5g000006l7VFEAY",
"name": "MyContainer",
"createdDate": "2026-01-27T10:00:00.000Z",
"lastModifiedDate": "2026-01-27T10:00:00.000Z"
}
}
错误码
- 500:容器名称冲突
- 501:创建容器失败
2. 删除容器接口
功能描述
删除指定的元数据容器及其所有成员。
请求方式
DELETE
请求路径
/tooling/metadata-container/delete/{id}
请求权限
tooling:container:delete
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | String | 是 | 容器 ID(路径参数) |
请求示例
DELETE /tooling/metadata-container/delete/a0B5g000006l7VFEAY
响应参数
无
成功示例
{
"code": 200,
"msg": "操作成功"
}
错误码
- 500:删除容器失败
- 501:容器不存在
3. 获取容器详情接口
功能描述
获取指定容器的详细信息。
请求方式
GET
请求路径
/tooling/metadata-container/get/{id}
请求权限
tooling:container:query
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| id | String | 是 | 容器 ID(路径参数) |
请求示例
GET /tooling/metadata-container/get/a0B5g000006l7VFEAY
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| id | String | 容器 ID |
| name | String | 容器名称 |
| createdDate | String | 创建时间 |
| lastModifiedDate | String | 最后修改时间 |
成功示例
{
"code": 200,
"msg": "操作成功",
"data": {
"id": "a0B5g000006l7VFEAY",
"name": "MyContainer",
"createdDate": "2026-01-27T10:00:00.000Z",
"lastModifiedDate": "2026-01-27T10:00:00.000Z"
}
}
错误码
- 500:查询容器失败
- 501:容器不存在
4. 查询容器列表接口
功能描述
查询符合条件的容器列表。
请求方式
GET
请求路径
/tooling/metadata-container/list
请求权限
tooling:container:query
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | String | 否 | 容器名称(模糊查询) |
请求示例
GET /tooling/metadata-container/list?name=MyContainer
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| id | String | 容器 ID |
| name | String | 容器名称 |
| createdDate | String | 创建时间 |
| lastModifiedDate | String | 最后修改时间 |
成功示例
{
"code": 200,
"msg": "操作成功",
"data": [
{
"id": "a0B5g000006l7VFEAY",
"name": "MyContainer",
"createdDate": "2026-01-27T10:00:00.000Z",
"lastModifiedDate": "2026-01-27T10:00:00.000Z"
}
]
}
错误码
- 500:查询容器列表失败
5. 添加成员接口
功能描述
向指定容器添加一个元数据成员。
请求方式
POST
请求路径
/tooling/deployment/member/add
请求权限
tooling:deployment:addMember
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| containerId | String | 是 | 容器 ID |
| metadataType | String | 是 | 元数据类型(ApexClass、ApexTrigger、ApexPage 等) |
| contentEntityId | String | 否 | 内容实体 ID(可选) |
| body | String | 是 | 代码内容 |
请求示例
{
"containerId": "a0B5g000006l7VFEAY",
"metadataType": "ApexClass",
"body": "public class MyClass {\n public void myMethod() {\n System.debug('Hello World');\n }\n}"
}
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| id | String | 成员 ID |
| containerId | String | 容器 ID |
| metadataType | String | 元数据类型 |
| contentEntityId | String | 内容实体 ID |
| body | String | 代码内容 |
| createdDate | String | 创建时间 |
| lastModifiedDate | String | 最后修改时间 |
成功示例
{
"code": 200,
"msg": "操作成功",
"data": {
"id": "a0C5g000006l7VFEAY",
"containerId": "a0B5g000006l7VFEAY",
"metadataType": "ApexClass",
"contentEntityId": null,
"body": "public class MyClass {\n public void myMethod() {\n System.debug('Hello World');\n }\n}",
"createdDate": "2026-01-27T10:00:00.000Z",
"lastModifiedDate": "2026-01-27T10:00:00.000Z"
}
}
错误码
- 500:添加成员失败
- 501:容器不存在
6. 部署容器接口
功能描述
触发指定容器的部署,支持 CheckOnly 模式和测试执行。
请求方式
POST
请求路径
/tooling/deployment/deploy
请求权限
tooling:deployment:deploy
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| containerId | String | 是 | 容器 ID |
| isCheckOnly | Boolean | 是 | 是否仅检查(true:仅检查不部署,false:实际部署) |
| isRunTests | Boolean | 是 | 是否运行测试(true:运行测试,false:不运行测试) |
请求示例
{
"containerId": "a0B5g000006l7VFEAY",
"isCheckOnly": false,
"isRunTests": true
}
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| id | String | 请求 ID |
| state | String | 部署状态(Queued、InProgress、Completed、Failed) |
| metadataContainerId | String | 容器 ID |
| isCheckOnly | Boolean | 是否仅检查 |
| isRunTests | Boolean | 是否运行测试 |
| createdDate | String | 创建时间 |
| lastModifiedDate | String | 最后修改时间 |
成功示例
{
"code": 200,
"msg": "操作成功",
"data": {
"id": "1DR5g000006l7VFEAY",
"state": "Queued",
"metadataContainerId": "a0B5g000006l7VFEAY",
"isCheckOnly": false,
"isRunTests": true,
"createdDate": "2026-01-27T10:00:00.000Z",
"lastModifiedDate": "2026-01-27T10:00:00.000Z"
}
}
错误码
- 500:部署失败
- 501:容器不存在
- 502:容器为空(没有成员)
- 503:并发部署限制
7. 查询部署状态接口
功能描述
查询指定部署请求的状态。
请求方式
POST
请求路径
/tooling/deployment/status/check
请求权限
tooling:deployment:query
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| requestId | String | 是 | 请求 ID |
请求示例
{
"requestId": "1DR5g000006l7VFEAY"
}
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| requestId | String | 请求 ID |
| state | String | 部署状态(Queued、InProgress、Completed、Failed) |
| metadataContainerId | String | 容器 ID |
| isCheckOnly | Boolean | 是否仅检查 |
| isRunTests | Boolean | 是否运行测试 |
| createdDate | String | 创建时间 |
| lastModifiedDate | String | 最后修改时间 |
成功示例
{
"code": 200,
"msg": "操作成功",
"data": {
"requestId": "1DR5g000006l7VFEAY",
"state": "Completed",
"metadataContainerId": "a0B5g000006l7VFEAY",
"isCheckOnly": false,
"isRunTests": true,
"createdDate": "2026-01-27T10:00:00.000Z",
"lastModifiedDate": "2026-01-27T10:00:00.000Z"
}
}
错误码
- 500:查询状态失败
- 501:请求不存在
8. 轮询部署状态接口
功能描述
轮询指定部署请求的状态,直到完成或超时。
请求方式
POST
请求路径
/tooling/deployment/status/poll
请求权限
tooling:deployment:query
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| requestId | String | 是 | 请求 ID |
| maxRetries | Integer | 否 | 最大重试次数(默认 60) |
| intervalMillis | Long | 否 | 轮询间隔(毫秒,默认 1000) |
请求示例
POST /tooling/deployment/status/poll?requestId=1DR5g000006l7VFEAY&maxRetries=60&intervalMillis=1000
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| requestId | String | 请求 ID |
| state | String | 部署状态(Queued、InProgress、Completed、Failed) |
| metadataContainerId | String | 容器 ID |
| isCheckOnly | Boolean | 是否仅检查 |
| isRunTests | Boolean | 是否运行测试 |
| createdDate | String | 创建时间 |
| lastModifiedDate | String | 最后修改时间 |
成功示例
{
"code": 200,
"msg": "操作成功",
"data": {
"requestId": "1DR5g000006l7VFEAY",
"state": "Completed",
"metadataContainerId": "a0B5g000006l7VFEAY",
"isCheckOnly": false,
"isRunTests": true,
"createdDate": "2026-01-27T10:00:00.000Z",
"lastModifiedDate": "2026-01-27T10:00:00.000Z"
}
}
错误码
- 500:轮询状态失败
- 501:请求不存在
- 502:轮询超时
9. 获取部署详情接口
功能描述
获取指定部署请求的详细信息,包括编译错误和测试结果。
请求方式
POST
请求路径
/tooling/deployment/details/get
请求权限
tooling:deployment:query
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| requestId | String | 是 | 请求 ID |
请求示例
{
"requestId": "1DR5g000006l7VFEAY"
}
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| requestId | String | 请求 ID |
| state | String | 部署状态(Queued、InProgress、Completed、Failed) |
| metadataContainerId | String | 容器 ID |
| isCheckOnly | Boolean | 是否仅检查 |
| isRunTests | Boolean | 是否运行测试 |
| createdDate | String | 创建时间 |
| lastModifiedDate | String | 最后修改时间 |
| componentFailures | Array | 编译错误列表 |
| runTestResult | Object | 测试结果 |
成功示例
{
"code": 200,
"msg": "操作成功",
"data": {
"requestId": "1DR5g000006l7VFEAY",
"state": "Completed",
"metadataContainerId": "a0B5g000006l7VFEAY",
"isCheckOnly": false,
"isRunTests": true,
"createdDate": "2026-01-27T10:00:00.000Z",
"lastModifiedDate": "2026-01-27T10:00:00.000Z",
"componentFailures": [],
"runTestResult": {
"numFailures": 0,
"numTestsRun": 1,
"totalTime": 123
}
}
}
错误码
- 500:获取详情失败
- 501:请求不存在
10. 获取部署结果接口
功能描述
获取指定部署请求的部署结果,包括编译错误和测试结果。
请求方式
GET
请求路径
/tooling/deployment/result/{requestId}
请求权限
tooling:deployment:query
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| requestId | String | 是 | 请求 ID(路径参数) |
请求示例
GET /tooling/deployment/result/1DR5g000006l7VFEAY
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| requestId | String | 请求 ID |
| state | String | 部署状态(Queued、InProgress、Completed、Failed) |
| metadataContainerId | String | 容器 ID |
| isCheckOnly | Boolean | 是否仅检查 |
| isRunTests | Boolean | 是否运行测试 |
| createdDate | String | 创建时间 |
| lastModifiedDate | String | 最后修改时间 |
| componentFailures | Array | 编译错误列表 |
| runTestResult | Object | 测试结果 |
成功示例
{
"code": 200,
"msg": "操作成功",
"data": {
"requestId": "1DR5g000006l7VFEAY",
"state": "Completed",
"metadataContainerId": "a0B5g000006l7VFEAY",
"isCheckOnly": false,
"isRunTests": true,
"createdDate": "2026-01-27T10:00:00.000Z",
"lastModifiedDate": "2026-01-27T10:00:00.000Z",
"componentFailures": [],
"runTestResult": {
"numFailures": 0,
"numTestsRun": 1,
"totalTime": 123
}
}
}
错误码
- 500:获取结果失败
- 501:请求不存在
错误码
通用错误码
| 错误码 | 说明 |
|---|---|
| 200 | 操作成功 |
| 500 | 操作失败 |
| 501 | 资源不存在 |
元数据容器错误码
| 错误码 | 说明 |
|---|---|
| 500 | 创建容器失败 |
| 501 | 容器不存在 |
| 502 | 容器名称冲突 |
部署错误码
| 错误码 | 说明 |
|---|---|
| 500 | 部署失败 |
| 501 | 请求不存在 |
| 502 | 容器为空(没有成员) |
| 503 | 并发部署限制 |
| 504 | 轮询超时 |