Initial commit: add NocoBase collection migration tools
This commit is contained in:
@@ -0,0 +1,405 @@
|
||||
# NocoBase Collection 结构导入导出脚本使用说明
|
||||
|
||||
本文说明如何使用项目中的两个脚本,在 NocoBase 环境之间导出、检查和导入主数据源的 Collection 结构。
|
||||
|
||||
- 导出脚本:`script/export-collection-schema.sh`
|
||||
- 导入脚本:`script/import-collection-schema.sh`
|
||||
|
||||
## 1. 适用范围
|
||||
|
||||
脚本迁移以下内容:
|
||||
|
||||
- 主数据源 `main` 中的 Collection 定义;
|
||||
- Collection 的普通字段和关系字段;
|
||||
- Collection 分类及分类成员关系;
|
||||
- Collection 和字段中可移植的配置属性。
|
||||
|
||||
脚本不迁移以下内容:
|
||||
|
||||
- Collection 中的业务数据记录;
|
||||
- 非主数据源中的 Collection;
|
||||
- 页面、区块和菜单配置;
|
||||
- 角色、权限和用户授权;
|
||||
- 工作流、自动化和通知配置;
|
||||
- 插件配置及环境变量。
|
||||
|
||||
导入脚本只接受由导出脚本生成的、`profile` 为 `portable` 且 `dataSource` 为 `main` 的导出包。
|
||||
|
||||
## 2. 运行前准备
|
||||
|
||||
请从项目根目录执行命令,并确认本机已安装:
|
||||
|
||||
- NocoBase CLI:`nb`
|
||||
- JSON 工具:`jq`
|
||||
|
||||
检查命令:
|
||||
|
||||
```sh
|
||||
command -v nb
|
||||
command -v jq
|
||||
```
|
||||
|
||||
同时需要满足以下条件:
|
||||
|
||||
1. 源环境和目标环境已经配置为可用的 NocoBase CLI 环境;
|
||||
2. 当前 CLI 身份可以读取源环境的数据模型;
|
||||
3. 正式导入时,当前 CLI 身份可以在目标环境创建或更新 Collection、字段和 Collection 分类;
|
||||
4. 目标环境应安装导出结构所依赖的字段接口或插件;
|
||||
5. 关系字段引用的外部 Collection 必须已经存在于目标环境。
|
||||
|
||||
可分别查看两个脚本的内置帮助:
|
||||
|
||||
```sh
|
||||
./script/export-collection-schema.sh --help
|
||||
./script/import-collection-schema.sh --help
|
||||
```
|
||||
|
||||
## 3. 推荐操作流程
|
||||
|
||||
建议始终按以下顺序执行:
|
||||
|
||||
1. 从源环境导出 Collection 结构;
|
||||
2. 检查导出目录中的 `manifest.json` 和 Collection JSON 文件;
|
||||
3. 对目标环境执行导入预演,不加 `--apply`;
|
||||
4. 核对预演输出中的环境、Collection 数量、字段数量、分类和外部关系目标;
|
||||
5. 确认无误后使用 `--apply` 和 `--confirm-env` 正式导入;
|
||||
6. 检查脚本最终输出的 `verified: true`。
|
||||
|
||||
## 4. 导出 Collection 结构
|
||||
|
||||
### 4.1 命令格式
|
||||
|
||||
```sh
|
||||
./script/export-collection-schema.sh \
|
||||
--env <源环境名称> \
|
||||
--output-dir <导出目录> \
|
||||
[--category <Collection 分类名称>] \
|
||||
[--no-overwrite]
|
||||
```
|
||||
|
||||
### 4.2 参数说明
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `--env` | 是 | NocoBase CLI 中已配置的源环境名称。 |
|
||||
| `--output-dir` | 是 | 导出包保存目录。目录不存在时会自动创建。 |
|
||||
| `--category` | 否 | 只导出指定 Collection 分类。必须与 NocoBase 中的分类名称完全一致;不指定时导出全部分类及未分类 Collection。 |
|
||||
| `--no-overwrite` | 否 | 如果输出目录已经存在则终止,不覆盖原目录。 |
|
||||
| `-h`、`--help` | 否 | 显示帮助信息。 |
|
||||
|
||||
数据源无需指定。导出脚本固定读取主数据源 `main`,也不接受 `--data-source` 参数。
|
||||
|
||||
### 4.3 导出全部 Collection
|
||||
|
||||
```sh
|
||||
./script/export-collection-schema.sh \
|
||||
--env master-data-local \
|
||||
--output-dir ./exports/all-collection-schema
|
||||
```
|
||||
|
||||
未指定 `--category` 时:
|
||||
|
||||
- 脚本读取主数据源中的全部 Collection;
|
||||
- 已加入分类的 Collection 按分类写入导出目录;
|
||||
- 未加入任何分类的 Collection 写入伪分类目录 `未分类`;
|
||||
- 同一个 Collection 属于多个分类时,会在多个分类目录中生成相同的结构文件,以保留全部分类关系。
|
||||
|
||||
### 4.4 按分类导出
|
||||
|
||||
```sh
|
||||
./script/export-collection-schema.sh \
|
||||
--env master-data-local \
|
||||
--category 参考数据 \
|
||||
--output-dir ./exports/reference-schema
|
||||
```
|
||||
|
||||
导出未加入分类的 Collection:
|
||||
|
||||
```sh
|
||||
./script/export-collection-schema.sh \
|
||||
--env master-data-local \
|
||||
--category 未分类 \
|
||||
--output-dir ./exports/unclassified-schema
|
||||
```
|
||||
|
||||
如果分类名称不存在,脚本会退出并列出当前可用的分类名称。
|
||||
|
||||
> **分类关系警告:** 使用 `--category` 时,导出包只记录所选分类,不会记录这些 Collection 在其他分类中的成员关系。正式导入会以导出包为准协调本次涉及 Collection 的分类关系,因此可能将它们从目标环境的其他分类中移除。如果需要完整保留全部分类关系,应不指定 `--category`,导出全部 Collection 和分类关系。
|
||||
|
||||
### 4.5 输出目录覆盖规则
|
||||
|
||||
默认情况下,如果输出目录已经存在,脚本会:
|
||||
|
||||
1. 先在同一父目录生成完整的临时导出目录;
|
||||
2. 将旧输出目录临时改名;
|
||||
3. 用新目录替换旧目录;
|
||||
4. 替换成功后删除旧目录;
|
||||
5. 替换失败时尝试恢复旧目录。
|
||||
|
||||
如需禁止覆盖,请添加 `--no-overwrite`:
|
||||
|
||||
```sh
|
||||
./script/export-collection-schema.sh \
|
||||
--env master-data-local \
|
||||
--output-dir ./exports/reference-schema \
|
||||
--no-overwrite
|
||||
```
|
||||
|
||||
### 4.6 导出包结构
|
||||
|
||||
典型目录结构如下:
|
||||
|
||||
```text
|
||||
exports/reference-schema/
|
||||
├── manifest.json
|
||||
└── main/
|
||||
└── 参考数据/
|
||||
├── ref_code_sets.json
|
||||
├── ref_code_set_versions.json
|
||||
└── ref_code_items.json
|
||||
```
|
||||
|
||||
`manifest.json` 记录:
|
||||
|
||||
- 源环境名称;
|
||||
- 固定数据源 `main`;
|
||||
- 导出分类或 `all`;
|
||||
- 导出时间;
|
||||
- 覆盖策略;
|
||||
- 发现和导出的 Collection 数量;
|
||||
- 导出文件数量;
|
||||
- 每个文件对应的分类、Collection 和相对路径。
|
||||
|
||||
每个 Collection JSON 文件保存经过标准化的可移植结构。导出时会排除部分由 NocoBase 自动生成或与当前实例绑定的内容,例如:
|
||||
|
||||
- `id`、创建时间、更新时间、创建人和更新人等系统字段;
|
||||
- 文件 Collection 和树形 Collection 的部分内置字段;
|
||||
- 实例内部使用的 `key`、`collectionName`、`parentKey` 等标识。
|
||||
|
||||
导出完成后,脚本会在标准输出中返回一份不包含文件明细的 JSON 摘要。
|
||||
|
||||
## 5. 导入 Collection 结构
|
||||
|
||||
### 5.1 命令格式
|
||||
|
||||
```sh
|
||||
./script/import-collection-schema.sh \
|
||||
--env <目标环境名称> \
|
||||
--input-dir <导出包目录> \
|
||||
[--apply --confirm-env <同一目标环境名称>]
|
||||
```
|
||||
|
||||
### 5.2 参数说明
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `--env` | 是 | NocoBase CLI 中已配置的目标环境名称。 |
|
||||
| `--input-dir` | 是 | 导出脚本生成的目录,其中必须包含 `manifest.json`。 |
|
||||
| `--apply` | 否 | 正式写入目标环境。不指定时只生成预演计划,不进行任何写入。 |
|
||||
| `--confirm-env` | 正式导入时必填 | 必须与 `--env` 完全一致,用于降低误操作到错误环境的风险。 |
|
||||
| `-h`、`--help` | 否 | 显示帮助信息。 |
|
||||
|
||||
### 5.3 第一步:导入预演
|
||||
|
||||
先执行不带 `--apply` 的命令:
|
||||
|
||||
```sh
|
||||
./script/import-collection-schema.sh \
|
||||
--env mdm-uat \
|
||||
--input-dir ./exports/reference-schema
|
||||
```
|
||||
|
||||
预演模式只读取和校验本地导出包,不写入目标 NocoBase 环境。输出示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"mode": "plan",
|
||||
"writes": false,
|
||||
"targetEnvironment": "mdm-uat",
|
||||
"sourceEnvironment": "master-data-local",
|
||||
"profile": "portable",
|
||||
"dataSource": "main",
|
||||
"collections": 3,
|
||||
"scalarFields": 12,
|
||||
"relationFields": 4,
|
||||
"categories": [
|
||||
"参考数据"
|
||||
],
|
||||
"categoryRelations": 3,
|
||||
"externalRelationTargets": []
|
||||
}
|
||||
```
|
||||
|
||||
正式导入前至少核对:
|
||||
|
||||
- `targetEnvironment` 是否为预期目标环境;
|
||||
- `sourceEnvironment` 是否为预期源环境;
|
||||
- `collections`、`scalarFields` 和 `relationFields` 数量是否合理;
|
||||
- `categories` 是否符合预期;
|
||||
- `unclassifiedCollections` 中是否存在不应取消分类的 Collection;
|
||||
- `externalRelationTargets` 引用的 Collection 是否已在目标环境存在。
|
||||
|
||||
注意:预演不会连接目标环境检查外部关系目标是否实际存在,该检查在正式导入、首次写入之前执行。
|
||||
|
||||
### 5.4 第二步:正式导入
|
||||
|
||||
确认预演结果后执行:
|
||||
|
||||
```sh
|
||||
./script/import-collection-schema.sh \
|
||||
--env mdm-uat \
|
||||
--input-dir ./exports/reference-schema \
|
||||
--apply \
|
||||
--confirm-env mdm-uat
|
||||
```
|
||||
|
||||
`--confirm-env` 的值必须与 `--env` 完全相同。例如,`--env mdm-uat` 必须配合 `--confirm-env mdm-uat`。
|
||||
|
||||
正式导入前,脚本会先完成以下检查:
|
||||
|
||||
- 导出包结构和全部 JSON 文件有效;
|
||||
- manifest 声明的数据源为 `main`;
|
||||
- Collection 名称、字段名称和文件路径合法且无重复冲突;
|
||||
- 目标环境可访问且当前身份已认证;
|
||||
- 目标环境不存在重名的 Collection 分类;
|
||||
- 导出包以外的关系目标已存在于目标环境。
|
||||
|
||||
检查通过后,脚本按四个阶段执行:
|
||||
|
||||
1. 创建或更新 Collection,并应用非关系字段;
|
||||
2. 应用 `m2o`、`o2m`、`m2m`、`o2o` 关系字段;
|
||||
3. 创建缺失分类并协调 Collection 分类成员关系;
|
||||
4. 从服务器回读 Collection、字段和分类关系并校验。
|
||||
|
||||
成功时输出类似:
|
||||
|
||||
```json
|
||||
{
|
||||
"mode": "applied",
|
||||
"writes": true,
|
||||
"verified": true,
|
||||
"targetEnvironment": "mdm-uat",
|
||||
"sourceEnvironment": "master-data-local",
|
||||
"profile": "portable",
|
||||
"dataSource": "main",
|
||||
"collections": 3,
|
||||
"scalarFields": 12,
|
||||
"relationFields": 4,
|
||||
"categoryMembership": "verified"
|
||||
}
|
||||
```
|
||||
|
||||
只有出现 `verified: true`,才表示脚本已完成服务器回读校验。
|
||||
|
||||
## 6. 导入合并与分类处理规则
|
||||
|
||||
### 6.1 Collection 和字段
|
||||
|
||||
- 已存在的 Collection 会被更新;不存在的 Collection 会被创建;
|
||||
- 导入包中的普通字段和关系字段会被创建或更新;
|
||||
- 导入使用 `replaceFields: false`,不会删除目标环境中额外存在的字段;
|
||||
- 脚本不会删除目标环境中额外存在的 Collection;
|
||||
- 如果目标结构无法包含导出包声明的结构,回读校验会失败并输出差异。
|
||||
|
||||
### 6.2 Collection 分类
|
||||
|
||||
- 导出包中存在、目标环境中不存在的分类会被创建;
|
||||
- 对本次导入涉及的 Collection,分类成员关系会调整为导出包声明的状态;
|
||||
- 目标分类中不属于本次导入范围的其他 Collection 会被保留;
|
||||
- `未分类` 是导出使用的伪分类,不会在目标环境创建同名分类;
|
||||
- 被标记为 `未分类` 的 Collection 会从目标环境现有分类中移除。
|
||||
|
||||
因此,导入前应重点检查预演结果中的 `categories` 和 `unclassifiedCollections`。对于按单个分类生成的导出包,还应确认是否允许移除本次 Collection 在目标环境中的其他分类关系。
|
||||
|
||||
## 7. 完整迁移示例
|
||||
|
||||
以下示例将本地环境中的“参考数据”分类迁移到 UAT 环境。
|
||||
|
||||
### 7.1 从源环境导出
|
||||
|
||||
```sh
|
||||
./script/export-collection-schema.sh \
|
||||
--env master-data-local \
|
||||
--category 参考数据 \
|
||||
--output-dir ./exports/reference-schema \
|
||||
--no-overwrite
|
||||
```
|
||||
|
||||
### 7.2 查看导出清单
|
||||
|
||||
```sh
|
||||
jq . ./exports/reference-schema/manifest.json
|
||||
```
|
||||
|
||||
列出导出的 Collection:
|
||||
|
||||
```sh
|
||||
jq -r '.files[].collection' ./exports/reference-schema/manifest.json | sort -u
|
||||
```
|
||||
|
||||
### 7.3 在目标环境执行预演
|
||||
|
||||
```sh
|
||||
./script/import-collection-schema.sh \
|
||||
--env mdm-uat \
|
||||
--input-dir ./exports/reference-schema
|
||||
```
|
||||
|
||||
### 7.4 正式导入并回读验证
|
||||
|
||||
```sh
|
||||
./script/import-collection-schema.sh \
|
||||
--env mdm-uat \
|
||||
--input-dir ./exports/reference-schema \
|
||||
--apply \
|
||||
--confirm-env mdm-uat
|
||||
```
|
||||
|
||||
## 8. 常见错误及处理
|
||||
|
||||
### `nb CLI is required`
|
||||
|
||||
当前终端找不到 `nb`。请安装或配置 NocoBase CLI,并确认 `command -v nb` 能返回可执行文件路径。
|
||||
|
||||
### `jq is required`
|
||||
|
||||
当前终端找不到 `jq`。请先安装 `jq`,并确认 `command -v jq` 能返回可执行文件路径。
|
||||
|
||||
### `Unknown category`
|
||||
|
||||
`--category` 指定的名称与源环境中的 Collection 分类不完全一致。请根据错误信息列出的分类名称重新执行。
|
||||
|
||||
### `Output directory already exists`
|
||||
|
||||
使用了 `--no-overwrite`,但输出目录已经存在。请更换目录、移走旧目录,或确认允许替换后去掉 `--no-overwrite`。
|
||||
|
||||
### `Invalid manifest.json: portable main-data-source export required`
|
||||
|
||||
输入目录不是当前导出脚本生成的主数据源可移植包,或 `manifest.json` 已被修改。请重新导出,不要手工修改 manifest 中的数据源、文件路径和数量字段。
|
||||
|
||||
### `External relation target is unavailable`
|
||||
|
||||
某个关系字段引用了未包含在导出包中的 Collection,而该 Collection 在目标环境不存在。请先在目标环境创建或迁移这个依赖 Collection,再重新导入。
|
||||
|
||||
### `--apply requires --confirm-env to exactly equal --env`
|
||||
|
||||
正式导入缺少环境确认,或者两个环境名称不一致。请检查目标环境后重新传入完全相同的值。
|
||||
|
||||
### `Import read-back verification failed`
|
||||
|
||||
写入完成后的实际结构未包含导出包声明的结构。脚本会输出 Collection、字段或分类关系的预期值与实际值。请根据差异检查:
|
||||
|
||||
- 目标环境的 NocoBase 版本和插件是否支持对应字段接口;
|
||||
- 关系字段的目标 Collection 和反向字段配置是否有效;
|
||||
- 当前身份是否拥有完整的数据模型修改权限;
|
||||
- 目标环境是否存在同名但不兼容的字段或 Collection 配置。
|
||||
|
||||
该错误可能发生在部分写入已经完成之后。修正问题后,应重新执行预演,再执行正式导入并确认最终返回 `verified: true`。
|
||||
|
||||
## 9. 使用注意事项
|
||||
|
||||
- 正式导入前,建议先对目标环境创建可恢复的备份;
|
||||
- 不要跳过预演,也不要仅凭进程退出码判断结构完全一致,应检查最终 JSON 中的 `verified`;
|
||||
- 导出包中的 JSON 文件适合纳入版本管理,以便审阅结构变化;
|
||||
- 不建议手工修改导出包;如确需修改,应同时保证 `manifest.json`、文件路径、Collection 名称及重复分类文件保持一致;
|
||||
- Collection 结构迁移完成后,业务数据、ACL、页面和工作流需要使用各自独立的迁移与验证流程。
|
||||
Reference in New Issue
Block a user