Backstage v1.12.0 版本解析:Catalog 游标分页、Scaffolder Zod 动作定义与后端系统导出重命名
2026/9/12 14:50:07 网站建设 项目流程

Backstage v1.12.0 版本解析:Catalog 游标分页、Scaffolder Zod 动作定义与后端系统导出重命名

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

本篇技术指南围绕 Backstage 开源开发者门户框架的 v1.12.0 版本发布展开,系统梳理该版本引入的核心能力:软件目录(Catalog)基于游标(cursor)的分页查询接口、Scaffolder 模板动作的zod声明式输入输出、新后端系统模块的命名规范重命名,以及两个新插件(Octopus Deploy、StackStorm)的落地方式。读者读完本篇后,能够掌握 v1.12.0 新增 API 的请求/响应结构与配置要点,了解如何利用zod编写类型安全的 Scaffolder 动作,并能在升级时正确迁移被重命名的导出符号。

一、版本概览与升级说明

v1.12.0 是 Backstage 的一个常规增量版本,主体由一批小的功能增强与缺陷修复构成,同时在开发体验上有若干明显改进。本仓库的正式发布说明位于 docs/releases/v1.12.0.md,对应的完整逐包变更记录(changeset)位于 docs/releases/v1.12.0-changelog.md。

  • 安全修复:该版本不包含任何安全修复项。
  • 升级建议:官方推荐将 Backstage 项目持续保持到最新版本,具体升级指引可参考 keeping-backstage-updated。
  • 版本配套:本次发布伴随多个核心包的主/次版本号更新,例如@backstage/backend-plugin-api升至 0.5.0、@backstage/backend-tasks升至 0.5.0、@backstage/catalog-client升至 1.4.0、@backstage/core-app-api升至 1.6.0、@backstage/plugin-catalog-backend升至 1.8.0、@backstage/plugin-scaffolder-backend升至 1.12.0 等。

二、核心亮点:用 zod 定义 Scaffolder 动作的输入输出

2.1 为什么引入 zod

此前编写自定义 Scaffolder 动作时,需要在inputoutput中手写 JSON Schema,并同时维护对应的 TypeScript 类型,二者极易失步。v1.12.0 起,动作作者可以改用zodschema 声明输入与输出,编辑器内即可获得即时类型反馈,比手工编写 JSON Schema 更直观、更安全。

2.2 源码层面的实现机制

本仓库 plugins/scaffolder-node/src/actions/createTemplateAction.ts 中,createTemplateAction被泛型化为同时接受"普通 JSON Schema 风格对象"与"zod schema(zImpl => z.ZodType)"两种形态:

  • 泛型参数TInputSchema/TOutputSchema既可以是一组字段函数对象{ [key in string]: (zImpl: typeof z) => z.ZodType },也可以是单个函数(zImpl: typeof z) => z.ZodType
  • 内部通过z.infer<...>z.output<...>推导出输入/输出的精确 TypeScript 类型,从而让动作的handler参数获得完整类型检查;
  • 函数内部(createTemplateAction.ts)通过parseSchemas将 zod schema 转换为 JSON Schema,再以统一格式交给系统校验与渲染。也就是说,zod 只是"编写时"的便利层,最终在整个系统中流转的仍是 JSON Schema,TemplateAction的对外契约保持不变。

在 plugins/scaffolder-node/src/actions/createTemplateAction.test.ts 中可找到对应测试,验证了 zod 定义被正确转换为 JSON Schema 并参与safeParse校验。

2.3 编写一个使用 zod 的模板动作

在自定义动作模块中,createTemplateAction的入参可简化为如下形态(示意,需按实际安装的版本引入依赖):

import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import { z } from 'zod/v3'; export const exampleAction = createTemplateAction({ id: 'example:hello', description: '输出一段问候', schema: { input: (zImpl) => zImpl.object({ name: zImpl.string().describe('被问候者的名字'), times: zImpl.number().default(1).describe('重复次数'), }), output: (zImpl) => zImpl.object({ message: zImpl.string(), }), }, async handler(ctx) { ctx.output('message', `hello ${ctx.input.name}`.repeat(ctx.input.times)); }, });

要点说明:

  • input/output中每个字段的.describe()会被带入最终的 JSON Schema 描述,供模板参数表单展示;
  • 通过zod.default().optional()等能力,可以自然表达参数默认值与可选性;
  • 由于类型由 schema 自动推导,ctx.inputctx.output的键和值在编辑器内即可获得静态校验,避免了"类型与 schema 不一致"的经典问题。

2.4 配套的 Scaffolder 前端与行为增强

同版本中@backstage/plugin-scaffolder@backstage/plugin-scaffolder-react@backstage/plugin-scaffolder-backend也同步更新:

  • EntityPicker改为使用完整限定的实体引用(fully qualified entity ref)而不是"人类可读"的简化名称;
  • useTaskStreamTaskBorderTaskLogStreamTaskSteps等组件/钩子从plugin-scaffolder迁移进plugin-scaffolder-react,便于其他前端复用任务流展示;
  • catalog:fetch动作扩展为可按实体引用一次获取多个实体;catalog:write动作允许写入任意形状的对象;当catalog:fetch获取不到实体且optionalfalse时会抛出错误。

三、核心亮点:从目录读取分页数据(/entities/by-query)

3.1 新增的后端端点与客户端方法

v1.12.0 为软件目录新增了带游标的分页查询端点GET /entities/by-query与对应的客户端方法queryEntities。它支持:

  • 游标式分页:首请求返回nextCursor,后续请求携带cursor获取下一页,同时响应中包含prevCursor以便回溯;
  • 服务端过滤:支持传统的 key-valuefilter语法与基于谓词的query语法($all$any$not$exists$in$hasPrefix$contains等逻辑与匹配操作符);
  • 服务端排序:通过orderFields(如metadata.name,asc)指定排序字段与方向;
  • 字段裁剪:通过fields仅返回所需字段,减小响应体积。

3.2 请求与响应类型

本仓库 packages/catalog-client/src/types/api.ts 中完整定义了相关类型:

  • QueryEntitiesRequest = QueryEntitiesInitialRequest | QueryEntitiesCursorRequest(api.ts);
  • QueryEntitiesInitialRequest支持fieldslimitoffsetfilterqueryorderFieldsfullTextFilter以及totalItems(取值'include'/'exclude',默认'include',设'exclude'可跳过总数统计以提升游标分页 UI 的性能)(api.ts);
  • QueryEntitiesCursorRequest仅需cursor,并可选fieldslimit(api.ts);
  • QueryEntitiesResponse返回itemstotalItems以及含nextCursor/prevCursorpageInfo(api.ts)。

其中filter用于传统 key-value 过滤,query用于谓词式过滤,二者可以同时提供。

3.3 客户端调用示例

// 首次请求:过滤 + 排序 + 限制条数 const response = await catalogClient.queryEntities({ filter: [{ kind: 'group' }], limit: 20, fields: ['metadata', 'kind'], fullTextFilter: { term: 'A' }, orderFields: { field: 'metadata.name', order: 'asc' }, }); // 游标翻页:携带 nextCursor 获取下一批 const nextPage = await catalogClient.queryEntities({ cursor: response.pageInfo.nextCursor, limit: 20, fields: ['metadata', 'kind'], });

上述示例会匹配所有名称以 "A" 开头、kind 为 group 的实体,按名称升序返回;若结果超过 20 条,则可通过nextCursor继续获取,prevCursor用于回到上一批。

3.4 服务端路由与 OpenAPI 契约

后端路由定义位于 plugins/catalog-backend/src/service/createRouter.ts:

  • POST /entities/by-query(createRouter.ts)承载谓词式过滤查询;
  • GET /entities/by-query(createRouter.ts)承载 key-value 过滤与排序查询。

服务端的 OpenAPI 描述位于 plugins/catalog-backend/src/schema/openapi.yaml,其中给出了丰富的过滤示例,例如:

/entities/by-query?filter=kind=user,metadata.namespace=default&filter=kind=group,spec.type

表示"kind=user 且 namespace=default,或 kind=group 且存在 spec.type"(同一 filter 内条件为 AND,多个 filter 之间为 OR)。排序示例:

/entities/by-query?orderField=metadata.name,asc

默认情况下实体按其内部uid排序;orderField后可跟asc(升序)或desc(降序)。此外该版本还同步新增了POST /locations/by-query,用于对 Location 实体做同样的游标式查询。

对应的路由测试集中在 plugins/catalog-backend/src/service/createRouter.test.ts(如GET /entities/by-queryPOST /entities/by-query两组 describe),覆盖了过滤、排序、游标编解码以及非法游标/非法 limit 的错误处理,可作为接口行为的权威参照。

3.5 目录客户端与其他配套更新

  • @backstage/catalog-client新增queryEntities方法,并修复了getEntitiesByRefs对缺失项返回undefined而非null的问题;
  • 批量按引用获取(batch fetch by ref)与过滤(例如启用授权时)组合使用的缺陷得到修复;
  • @backstage/plugin-catalog-backend为一批久已迁往@backstage/plugin-catalog-node的符号(CatalogProcessorEntityProviderprocessingResultEntityRelationSpec等)补充了弃用标记,并将locationSpecToLocationEntitylocationSpecToMetadataName迁至plugin-catalog-node作为新家;
  • 前端@backstage/plugin-catalog-react支持在EntityPicker过滤器中复用多选能力。

四、新后端系统:插件导出重命名(按推荐命名模式)

随着新后端系统(new backend system)逐步定型,v1.12.0 将一批插件的模块导出更名为官方推荐的命名模式(推荐规范可参见仓库文档 docs/backend-system/architecture/naming-patterns.md)。核心规则为:以catalogModule<Name>eventsModule<Name>等作为前缀,例如:

变更前(旧导出)变更后(新导出)所属包
githubEntityProviderCatalogModulecatalogModuleGithubEntityProviderplugin-catalog-backend-module-github
awsS3EntityProviderCatalogModulecatalogModuleAwsS3EntityProvidersplugin-catalog-backend-module-aws
azureDevOpsEntityProviderCatalogModulecatalogModuleAzureDevOpsEntityProviderplugin-catalog-backend-module-azure
bitbucketCloudEntityProviderCatalogModulecatalogModuleBitbucketCloudEntityProviderplugin-catalog-backend-module-bitbucket-cloud
bitbucketServerEntityProviderCatalogModulecatalogModuleBitbucketServerEntityProviderplugin-catalog-backend-module-bitbucket-server
gerritEntityProviderCatalogModulecatalogModuleGerritEntityProviderplugin-catalog-backend-module-gerrit
gitlabDiscoveryEntityProviderCatalogModulecatalogModuleGitlabDiscoveryEntityProviderplugin-catalog-backend-module-gitlab
incrementalIngestionEntityProviderCatalogModulecatalogModuleIncrementalIngestionEntityProviderplugin-catalog-backend-module-incremental-ingestion
microsoftGraphOrgEntityProviderCatalogModulecatalogModuleMicrosoftGraphOrgEntityProviderplugin-catalog-backend-module-msgraph
awsSqsConsumingEventPublisherEventsModuleeventsModuleAwsSqsConsumingEventPublisherplugin-events-backend-module-aws-sqs
githubEventRouterEventsModuleeventsModuleGithubEventRouterplugin-events-backend-module-github
githubWebhookEventsModuleeventsModuleGithubWebhookplugin-events-backend-module-github
gitlabEventRouterEventsModuleeventsModuleGitlabEventRouterplugin-events-backend-module-gitlab
azureDevOpsEventRouterEventsModuleeventsModuleAzureDevOpsEventRouterplugin-events-backend-module-azure

这些导出仍处于 alpha 阶段,因此本次重命名被官方视为非破坏性变更(non-breaking),但如果你已经在使用新后端系统,需要同步更新import语句。同一批变更还对所有包的/alpha导出做了内部重构(changeset928a12a9b3e),并在@backstage/plugin-catalog-backend-module-gitlab中弃用了GitlabDiscoveryEntityProviderbranch配置键,改用fallbackBranch

五、新插件:catalog-backend 的 PuppetDB 模块

@backstage/plugin-catalog-backend-module-puppetdb@0.1.0为本版本首次发布,用于将 PuppetDB,可作为 Entity Provider 定时把 PuppetDB 中的节点/事实同步为目录实体,适用于以 Puppet 做配置管理的团队构建基础设施目录视图。

六、新插件:Octopus Deploy 与 StackStorm

6.1 Octopus Deploy 部署插件

@backstage/plugin-octopus-deploy@0.1.0为本版本首次发布的正式插件,用于集成 Octopus 部署平台,源码位于 plugins/octopus-deploy。它面向使用 Octopus 作为发布/部署编排工具的团队,可将部署信息(环境、项目、发布版本等)纳入 Backstage 的软件目录实体详情页。该插件随包携带 Octopus Deploy 官方 Logo 资源。

6.2 StackStorm 集成插件

@backstage/plugin-stackstorm@0.1.0提供与 StackStorm 的集成,源码位于 plugins/stackstorm,通过对接 StackStorm API 让用户直接在 Backstage 中查看工作流执行(workflow executions)、包(packs)与动作(actions)。安装与配置指引以该插件目录内的 README 为准。

七、其他值得关注的功能与修复

7.1 目录前端:EntitySwitch 支持渲染多个匹配分支

@backstage/plugin-catalogEntitySwitch组件新增renderMultipleMatches="all"参数:当多个EntitySwitch.Caseif条件同时为真时,将所有匹配分支一并渲染,未匹配时渲染默认分支(若有)。典型场景是在同一页面上展示多个 CI/CD 系统:

<EntitySwitch renderMultipleMatches="all"> <EntitySwitch.Case if={isJenkinsAvailable}>Jenkins</EntitySwitch.Case> <EntitySwitch.Case if={isCodebuildAvailable}>CodeBuild</EntitySwitch.Case> <EntitySwitch.Case>No CI/CD</EntitySwitch.Case> </EntitySwitch>

7.2 OAuth2 与 OIDC 语义对齐

@backstage/core-app-apiOAuth2在申请openidscope 的会话时现在会显式获取 ID Token。这并非破坏性变更——符合规范的 OIDC 提供方本就会在授予openidscope 时返回 ID Token;该改动只是将这一依赖显式化,使基于 OAuth2 的提供方无需再手动把openid加入默认 scope,从而可以避免为资源型访问令牌申请多余的 ID Token 相关 scope。同时 GitLab 认证提供方现在可以用于获取 OpenID 令牌。

7.3 UrlReaderService 的 lastModified 支持

@backstage/backend-plugin-apiUrlReaderService.readUrl响应新增lastModifiedAt字段,并支持lastModifiedAfter选项,便于按文件修改时间做增量读取或缓存决策。

7.4 后端基础设施细节

  • @backstage/backend-common新增backend.database.role配置,用于设置 Postgres 中新建 schema 与表的归属用户(配合pluginDivisionMode: schema),例如:

    backend: database: client: pg pluginDivisionMode: schema role: backstage connection: user: v-backstage-123 # ...

    上例以v-backstage-123连接数据库,但新建对象的属主为backstage

  • AwsS3UrlReader升级到 AWS SDK v3;

  • @backstage/errors新增NotImplementedError@backstage/backend-app-api会将其正确映射为 501 状态码;

  • @backstage/plugin-proxy-backendcreateRouter支持reviveConsumedRequestBodies: true,可恢复被 express 中间件(如express.json())消费过的请求体,默认不启用;

  • backend-tasks新增从调度器获取任务描述(description)的能力,便于展示任务触发原因。

7.5 TechDocs 与 CLI

  • @techdocs/cli generate --verbose会输出 mkdocs 构建过程日志;techdocs AWS S3 请求支持 HTTPS 代理;
  • @backstage/plugin-techdocs-backend引入新后端系统下的techdocsPluginalpha 导出;
  • TechDocs 前端修复了某些 mkdocs-material 版本下上一篇/下一篇链接失效的问题,并保留插入到 shadow DOM 中文档内容的 HTML 标签属性以改善可访问性;
  • @backstage/cli新增migrate package-exports命令,用于同步所有package.jsonexports字段,并新增了 Web 与 Node.js 库类型的新插件模板。

7.6 其余代表性修复

  • Catalog 相关:getEntitiesByRefs缺失项返回undefined;修复批量按引用获取与过滤(如授权)组合使用的缺陷;
  • Scaffolder 相关:RepoUrlPicker对无 owner 的目标(如 Bitbucket Server)也能获取凭据;修复数组字段校验、空对象hasErrors判断等;
  • 前端通用:core-components中 Sidebar 按钮文案不再强制大写(按给定大小写原样显示);Table组件支持columns[*].headerStyle;搜索分页在最后一页正确禁用"下一页"按钮;快捷方式插件修复了新增快捷方式会覆盖整个列表的问题;
  • 主题相关:一批插件将硬编码的黑/白颜色改为感知主题(theme aware)。

八、升级到 v1.12.0 的注意事项清单

综合以上变更,从旧版本升级到 v1.12.0 时建议重点检查以下几点:

  1. 新后端系统导入路径:如已使用 alpha 导出,按上文表格将旧的xxxEntityProviderCatalogModule/xxxEventRouterEventsModule等重命名为新命名模式;
  2. Scaffolder 动作 schema:可逐步将手写 JSON Schema 迁移为zod声明以获得类型安全;系统仍兼容原有 JSON Schema 形态;
  3. GitLab Discovery Provider 配置:若使用了branch键,重命名为fallbackBranch
  4. 目录查询:需要游标分页/服务端排序时,优先采用queryEntities//entities/by-querygetEntities依旧可用;
  5. 数据库归属:如使用 Postgres schema 划分模式,可评估backend.database.role以统一对象属主;
  6. 代理行为:proxy-backend 默认不复活已消费请求体,需要该行为时显式开启reviveConsumedRequestBodies: true
  7. UI 覆盖样式:Sidebar 按钮文案不再自动大写、多个组件切换为主题感知颜色,如有自定义样式覆盖需复核。

九、相关文档与进一步阅读

  • 发布说明:docs/releases/v1.12.0.md
  • 逐包变更记录:docs/releases/v1.12.0-changelog.md
  • 新后端系统架构:docs/backend-system/architecture
  • 后端系统命名模式:docs/backend-system/architecture/naming-patterns.md
  • 保持 Backstage 更新:docs/getting-started/keeping-backstage-updated.md
  • 版本化与支持策略:docs/overview/versioning-policy.md

说明:本仓库为 Backstage 官方仓库的快照,文章中引用的源码路径(如 createTemplateAction.ts、api.ts、createRouter.ts)与文档路径均可在当前仓库中直接查阅;文中所有版本号与配置均以本仓库 v1.12.0 版本内容为准。

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

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

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

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

立即咨询