Backstage v1.10.0-next.0 版本解读:Catalog 服务端排序、Scaffolder 实体过滤与搜索索引稳定性增强
2026/9/12 10:01:46 网站建设 项目流程

Backstage v1.10.0-next.0 版本解读:Catalog 服务端排序、Scaffolder 实体过滤与搜索索引稳定性增强

【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage

本指南基于 docs/releases/v1.10.0-next.0-changelog.md 整理,并结合本仓库源码(packages/catalog-clientplugins/catalog-backendplugins/scaffolderplugins/search-backend-module-elasticsearch等)对三项核心变更进行纵深剖析。读者读完可以掌握:如何利用getEntitiesorder参数与 Catalog 服务端排序 API 落地稳定、可预期的实体列表顺序;如何用catalogFilter取代已废弃的allowedKinds精确控制 Scaffolder 选择器候选实体;以及如何理解 Elasticsearch 索引吞吐与进程稳定性修复背后的实现细节。文中给出的 API 参数格式、请求示例与配置代码均来自当前仓库实际代码,可直接用于v1.10.0系列的升级与排障。

版本概览:一次围绕 Catalog 与 Scaffolder 的 minor 升级

v1.10.0-next.0是 Backstage 1.10 系列的第一个预发布(next)版本,采用 Backstage 常规的按包版本化发布节奏:各@backstage/*包独立版本号,并在本次迭代中集中升级。本仓库docs/releases/目录下保存了完整的版本变更记录,本文对应的 v1.10.0-next.0-changelog.md 全文约 1900 行,覆盖了包括@backstage/cli@backstage/core-components@backstage/create-app@backstage/repo-tools以及数十个前端插件在内的依赖更新。

其中真正带来行为变化的核心亮点集中在三处(均以Minor Changes标记):

变更涉及包类型
getEntities支持order指令,entities 端点实现服务端排序@backstage/catalog-client@1.3.0-next.0@backstage/plugin-catalog-backend@1.7.0-next.0Minor
OwnerPicker/EntityPicker新增catalogFilter字段,allowedKinds废弃@backstage/plugin-scaffolder@1.10.0-next.0及多个 scaffolder-backend 模块Minor
Catalog 内部引用残留修复(d136793ff0@backstage/plugin-catalog-backend@1.7.0-next.0Patch
Elasticsearch 索引吞吐与进程稳定性修复@backstage/plugin-search-backend-module-elasticsearch@1.1.1-next.0Patch

此外plugin-search-backend@1.2.1-next.0允许配置搜索结果的最大分页限制,plugin-catalog-react@1.2.4-next.0修复了EntityTagPicker对已选 kind 过滤不可用标签的问题,@backstage/cli@0.22.1-next.0则带来若干与 Yarn 工作区相关的修复(详见后文)。

Catalog 服务端排序:从客户端排序到order指令

变更内容与动机

v1.10.0-next.0之前,getEntities返回的实体顺序在服务端并不保证稳定,依赖列表排序的调用方需要自行处理。本次通过提交f75bf76330在 packages/catalog-client/src/types/api.ts 中新增了EntityOrderQuery类型,并把它挂到GetEntitiesRequest.order上,同时在 packages/catalog-client/src/CatalogClient.ts 中把该指令编码进 HTTP 请求参数。与之对应,plugins/catalog-backend在 entities 端点实现了真正的服务端排序。

EntityOrderQuery的定义如下:

export type EntityOrderQuery = | { field: string; order: 'asc' | 'desc'; } | Array<{ field: string; order: 'asc' | 'desc'; }>;

该类型在注释中明确了以下语义(见 types/api.ts):

  • field是实体内以点分隔的字段路径,例如kindmetadata.namespec.type
  • order只能是asc(升序,字典序)或desc(降序,逆字典序),排序大小写不敏感;
  • 传入数组时按顺序构成多级排序:靠前的指令优先级更高,仅当高优先级字段值相等时才使用后面的指令(例如先按kind升序、再在同 kind 内按metadata.name降序);
  • 当某个字段在结果集中部分实体上不存在时,缺失该字段的实体在该排序步骤中始终排在最后,无论期望是升序还是降序

客户端如何编码order

在 CatalogClient.ts 中,getEntitiesorder序列化为asc:<field>/desc:<field>形式的查询参数:

if (order) { for (const directive of [order].flat()) { encodedOrder.push(`${directive.order}:${directive.field}`); } // ... params.order = encodedOrder; }

{ field: 'metadata.name', order: 'desc' }会被编码为order=desc:metadata.name。多个指令可以重复order参数(例如order=asc:kind&order=desc:metadata.name)。

服务端解析:格式校验与归一化

服务端在 plugins/catalog-backend/src/service/request/parseEntityOrderParams.ts 中用正则^(asc|desc):(.+)$校验每个order参数,非法格式会抛出InputError

Invalid order parameter "<value>", expected "<asc or desc>:<field name>"

解析得到的EntityOrder[]会进入查询流水线(parseEntityQuery.ts 还统一校验order值必须为asc/desc,否则抛出Invalid order field order, must be asc or desc),最终在数据库层转换为排序条件。相关测试覆盖了单字段、多字段、缺省顺序以及非法顺序(如metadata.uid,invalid)等场景,可参考 parseEntityOrderParams.test.ts 与 parseEntityQuery.test.ts。

客户端调用示例

import { catalogApiRef, useApi } from '@backstage/core-plugin-api'; const catalogApi = useApi(catalogApiRef); // 单级排序:按 name 降序 const result = await catalogApi.getEntities({ order: { field: 'metadata.name', order: 'desc' }, }); // 多级排序:先按 kind 升序,再按 name 降序 const multi = await catalogApi.getEntities({ order: [ { field: 'kind', order: 'asc' }, { field: 'metadata.name', order: 'desc' }, ], });

顺带的变化:orderFields走向统一

值得留意的是,同一版本的 CatalogClient.ts 中queryEntitiesorderFields参数也被保留并编码为orderField=<field>,<order>形式(例如orderField=metadata.name,desc),服务端解析见 parseEntityOrderFieldParams.ts。两套排序入口在语义上保持对齐,createQueryCatalogEntitiesAction也支持在模板 Action 中使用orderFields(单条或数组),见 createQueryCatalogEntitiesAction.ts。

Scaffolder 选择器:用catalogFilter取代allowedKinds

变更内容

@backstage/plugin-scaffolder@1.10.0-next.0(以及plugin-scaffolder-backendscaffolder-backend-module-cookiecutter/rails/yeoman)通过提交e4c0240445OwnerPickerEntityPicker新增catalogFilter字段,用于按实体的任意字段过滤候选选项。同时:

TheallowedKindsfield has been deprecated. UsecatalogFilterinstead.

allowedKinds被标记为废弃。在前端字段 Schema 中可以看到明确的废弃标注:

allowedKinds: z .array(z.string()) .optional() .describe('DEPRECATED: Use `catalogFilter` instead. ...'),

见 plugins/scaffolder/src/components/fields/EntityPicker/schema.ts。catalogFilter的取值类型为“单条过滤表达式或过滤表达式数组”(t.or(t.array())),每个表达式是键值对记录,见 schema.ts。

底层映射:uiSchemaEntityFilterQuery

在 EntityPicker.tsx 中,catalogFilter会被构造成查询条件并通过getEntities流式请求拉取候选:

const catalogFilter = buildCatalogFilter(uiSchema); const streamRequest = catalogFilter ? { query: {}, filter: catalogFilter, fields } : // ... 原有查询路径

buildCatalogFilter(EntityPicker.tsx)负责把ui:options.catalogFilter中的表达式转换为EntityFilterQuery:数组输入被逐条convertSchemaFiltersToQuery,单个对象输入则直接转换。也就是说,模板中写的过滤条件最终会透传给 CatalogClient,与getEntitiesfilter参数同构。

模板中的完整用法(原 changelog 示例)

  • 获取所有kind: Group的实体作为 Owner 候选:
owner: title: Owner type: string description: Owner of the component ui:field: OwnerPicker ui:options: catalogFilter: - kind: Group
  • 同时限定kind: Groupspec.type: team
owner: title: Owner type: string description: Owner of the component ui:field: OwnerPicker ui:options: catalogFilter: - kind: Group spec.type: team

对比旧写法ui:options: { allowedKinds: ['Group'] }catalogFilter的表达能力从“只按 kind”扩展为“任意字段(含spec.*)的任意组合”,并且支持传入数组表达“或”关系的多组过滤条件。同版本OwnerPickerMultiEntityPicker也一并支持该字段,相关测试可参考 EntityPicker.test.tsx、MultiEntityPicker.test.tsx 与 OwnerPicker.test.tsx。

升级提示

  • 存量模板如果使用allowedKinds,功能仍然可用(仅废弃,未移除),但建议在升级到v1.10.0系列时迁移为等价的catalogFilterallowedKinds: ['Group']对应catalogFilter: [{ kind: 'Group' }]
  • 由于该字段作用于ui:options,属于前端表单 Schema 与后端执行共用的描述,scaffolder-backend各模块同样接收该配置(见 changelog 中三个 backend 模块的同步更新),因此前后端版本需同步升级。

版本中的其他值得关注的变化

Scaffolder 表单体验:Stepper与校验器回退

  • 223e2c5f03:为Stepper组件新增onChange处理器,便于在多步表单切换时感知状态变化;
  • 3c112f6967:将@rjsf/validator-ajv8回退为@rjsf/validator-v6。这是一次兼容性回退,说明 ajv8 校验器在当前 rjsf 版本组合下存在兼容问题,升级时应保持该依赖组合不变。

Elasticsearch 搜索索引的稳定性与吞吐优化

@backstage/plugin-search-backend-module-elasticsearch@1.1.1-next.0本次包含三个 Patch 修复(见 v1.10.0-next.0-changelog.md):

  • 1e1a9fe979:修复索引流程可能静默失败、超时并积累陈旧索引(stale indices)的问题;
  • 56633804dd:修复索引过程中遇到客户端错误时可能导致 Backstage 后端意外终止的问题;
  • aa33a06894:通过优化批量客户端可获取文档的时机与数量来提升索引吞吐。

这三项修复共同提升了大规模实体入库场景下 Elasticsearch 索引任务的健壮性,对部署了 Elasticsearch 搜索后端的用户尤其重要。此外@backstage/plugin-search-backend@1.2.1-next.0bfd66b0478)允许配置搜索结果的最大分页限制,搜索 API 的分页行为因此可被显式约束。

Catalog 引用残留修复

d136793ff0plugin-catalog-backendPatch):修复了 catalog 内部引用存留时间超过预期的问题——该问题此前会导致实体无法按预期被删除或孤儿化(orphaned)。该修复保证引用关系的清理时机与实体生命周期一致,对使用 orphan cleanup 机制(参见 contrib/scripts/orphan-clean-up)的部署有直接影响。

CLI 与依赖治理

@backstage/cli@0.22.1-next.0的 Patch 变更集中在依赖一致性上:

  • 47c10706df:修复 Yarn 3 下yarn.lock同时存在 workspace 与非 workspace 版本的同名包时 CLI 失效的问题;
  • a62a1f9dcafrontend serve任务的包检查现在与versions:bumpversions:check一致地过滤允许的重复包;
  • 7c8a974515repo test/repo lint/repo build在基于--since <ref>寻找变更包时会分析yarn.lock的依赖变更,从而在存在 lockfile 变更时也能正确限定范围;
  • e1b71e142e:版本命令不再将 workspace 范围视为非法。

这些改进降低了大型 monorepo 中并发升级依赖时的摩擦。

升级与验证建议

  1. 同步升级前后端:本次catalog-clientplugin-catalog-backendplugin-scaffolder之间存在依赖联动(见 changelog 中各自的 “Updated dependencies”),建议整体升级到v1.10.0-next.0对应版本,避免新旧客户端与服务端对order参数理解不一致。
  2. 验证排序行为:升级后使用getEntities({ order: [...] })做一次冒烟测试,重点验证多级排序的优先级与“缺失字段排最后”的语义是否符合预期(可用 parseEntityOrderParams.test.ts 中的用例作为行为基准)。
  3. 迁移allowedKinds:搜索仓库内模板对allowedKinds的使用,逐一替换为catalogFilter,并在 Scaffolder 表单中实际选择一次以验证过滤结果。
  4. 留意 Elasticsearch 配置:若使用 ES 搜索后端,升级后观察索引任务日志,确认陈旧索引清理与批量吞吐优化生效;如需限制搜索分页上限,可参考plugin-search-backend的新增配置项。

小结

v1.10.0-next.0是围绕 Catalog 数据访问能力的一次实质性增强:getEntitiesorder指令与服务端排序让实体列表顺序变得可预期,catalogFilter让 Scaffolder 的实体选择器获得与 Catalog 查询同构的过滤能力,而 Elasticsearch 索引修复与 CLI 依赖治理则为生产环境的稳定性提供了保障。结合本文给出的源码路径与测试用例,读者可以在升级过程中快速定位行为差异并进行验证。

【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询