Backstage v1.3.0 版本深度解析:Token 安全强化、Catalog Entity Provider 迁移与 Scaffolder 任务管理
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
本篇技术指南基于 Backstage 官方 v1.3.0 变更日志(docs/releases/v1.3.0-changelog.md),系统性梳理该版本引入的破坏性变更与核心新能力:ServerTokenManager强制校验exp声明、Catalog 发现机制从 Processor 向 Entity Provider 迁移(Bitbucket Cloud / Azure DevOps / GitLab)、Scaffolder 任务列表页与 Gerrit 支持、搜索结果的rank与discover分析事件等。阅读本文后,你将掌握 v1.2.0 → v1.3.0 升级过程中需要处理的全部迁移要点,并能直接复刻各插件的新配置与代码写法。
v1.3.0 版本主题概览
v1.3.0 是 Backstage 在 1.0 系列稳定期的一次重要功能版本,涉及数十个@backstage/*包同步发版,核心主题集中在以下几个方面:
| 主题领域 | 涉及包 | 关键变化 |
|---|---|---|
| 服务间认证安全 | @backstage/backend-common@0.14.0 | 破坏性变更:服务端 token 必须携带未过期的exp声明 |
| Catalog 发现机制演进 | catalog-backend-module-bitbucket-cloud、-azure、-gitlab | 新增/补全 Entity Provider,替代传统 Discovery Processor |
| 脚手架任务可观测性 | @backstage/plugin-scaffolder@1.3.0、scaffolder-backend@1.3.0 | 新增/create/tasks任务列表页、listTasksAPI、/v2/tasks路由 |
| 搜索与分析 | plugin-search、plugin-catalog、plugin-techdocs | 搜索结果新增rank,点击事件升级为discover事件 |
| 新插件 | dynatrace、vault、github-pull-requests-board | 三个全新插件首次发布 |
下文按"升级必读 → 迁移实操 → 新功能"的顺序展开。
服务端 Token 强制校验exp:v1.3.0 最重要的破坏性变更
@backstage/backend-common@0.14.0的 Minor Changes 中有一条BREAKING声明:所有由ServerTokenManager认证的服务端到服务端(server-to-server)token,现在必须携带尚未过期的exp声明。凡是exp缺失或已过期的 token 一律视为无效并抛出错误。
这条变更承接自 v1.2.0 中对"永久 token(perpetual tokens)"的弃用声明,是对该弃用的最终落地。升级后必须注意:
- 更新所有
getToken()的调用方式:每次需要 token 时都重新调用,不要在应用启动时获取一次然后长期存储复用; - 由于 token 现在带有过期时间,任何"获取一次、反复使用"的缓存逻辑都会在过期后触发认证失败;
- 仓库当前代码中仍能看到该管理器的使用痕迹,例如 packages/backend-defaults/CHANGELOG.md 记录的
ServerTokenManager.fromConfig(config, ...)构造方式,它是后端默认服务装配中 token 管理的标准入口。
从架构角度看,这一变更让 Backstage 的插件后端之间通信具备了真正的时效性安全边界:即使 token 意外泄露,其有效窗口也受到exp限制,而不是无限期有效。同时它也提醒所有插件作者:token 的获取与使用应当"按需即取",与服务生命周期解耦。
Catalog 发现机制演进:从 Processor 到 Entity Provider
v1.3.0 在 Catalog 后端模块上集中发力,将多个 Git 托管平台的自动发现能力从"处理器(Processor)"模式迁移到"实体提供者(Entity Provider)"模式。后者由调度器(Scheduler)驱动,周期性拉取仓库列表并注册catalog-info.yaml,相比 Processor 具备更明确的配置结构、支持多实例并行与更细粒度的过滤。
新增@backstage/plugin-bitbucket-cloud-common:统一的 Bitbucket Cloud 客户端
该版本新增了通用库@backstage/plugin-bitbucket-cloud-common@0.1.0,提供一个可复用的 Bitbucket Cloud API 客户端。变更日志明确指出:这个客户端可以在所有包之间复用,未来很可能成为承载限流管理等额外能力的公共基础层;客户端部分代码由@openapitools/openapi-generator-cli生成。它被随后发布的新 Entity Provider 模块作为底层依赖引用。
新模块catalog-backend-module-bitbucket-cloud:用 Provider 取代 Discovery Processor
新发布的@backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.0提供了BitbucketCloudEntityProvider,官方定位是BitbucketDiscoveryProcessor在Bitbucket Cloud(仅限云端)场景下的替代品,明确覆盖原先使用search=true的用例,并可作为完整替代。迁移步骤如下。
迁移前(Processor 模式),在 packages/backend/src/plugins/catalog.ts 中注册处理器,并在app-config.yaml中配置 location:
// packages/backend/src/plugins/catalog.ts builder.addProcessor( BitbucketDiscoveryProcessor.fromConfig(env.config, { logger: env.logger }), );# app-config.yaml catalog: locations: - type: bitbucket-discovery target: 'https://bitbucket.org/workspaces/workspace-name/projects/apis-*/repos/service-*?search=true&catalogPath=/catalog-info.yaml'迁移后(Entity Provider 模式):
// packages/backend/src/plugins/catalog.ts builder.addEntityProvider( BitbucketCloudEntityProvider.fromConfig(env.config, { logger: env.logger, schedule: env.scheduler.createScheduledTaskRunner({ frequency: { minutes: 30 }, timeout: { minutes: 3 }, }), }), );# app-config.yaml catalog: providers: bitbucketCloud: yourProviderId: # identifies your ingested dataset catalogPath: /catalog-info.yaml # default value filters: # optional projectKey: '^apis-.*源码级配置说明。结合 plugins/catalog-backend-module-bitbucket-cloud/config.d.ts 与 plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProviderConfig.ts 的解析逻辑,配置项细节如下:
workspace:必填,指定要发现的 Bitbucket 工作区。注意config.d.ts中该字段被标记为 Required;catalogPath:可选,默认/catalog-info.yaml(常量DEFAULT_CATALOG_PATH定义于配置解析文件中);filters.projectKey/filters.repoSlug:可选正则表达式,分别按项目 Key 与仓库 slug 过滤。底层compileRegExp会自动为模式补全^与$锚点(BitbucketCloudEntityProviderConfig.ts),因此无论你写不写锚点,匹配都是整行全匹配语义;schedule:可选,调度定义;也可在代码中通过env.scheduler.createScheduledTaskRunner(...)传入。从 BitbucketCloudEntityProvider.ts 的实现可见,代码与配置二者必须提供其一,否则fromConfig会直接抛出'Either schedule or scheduler must be provided.'异常;pagelen:可选,每页从 Bitbucket API 拉取的结果数,默认 100;- 配置支持"单配置变体"(直接写
workspace键)与"命名多 Provider 变体"两种形式:当配置顶层存在workspace字段时按default作为 provider id 解析,否则遍历所有子键作为多个独立 provider(见 BitbucketCloudEntityProviderConfig.ts)。
此外,该 Provider 与事件系统集成(源码顶部常量TOPIC_REPO_PUSH、TOPIC_REPO_UPDATED,见 BitbucketCloudEntityProvider.ts),可响应仓库推送等事件实现增量发现。
Azure DevOps:AzureDevOpsEntityProvider迁移指南
@backstage/plugin-catalog-backend-module-azure@0.1.4新增AzureDevOpsEntityProvider,作为AzureDevOpsDiscoveryProcessor的替代。迁移前后对比如下。
迁移前,使用azure-discovery类型的 location 与 Processor:
# app-config.yaml catalog: locations: - type: azure-discovery target: https://dev.azure.com/myorg/myproject/_git/service-*?path=/catalog-info.yaml/* packages/backend/src/plugins/catalog.ts */ import { AzureDevOpsDiscoveryProcessor } from '@backstage/plugin-catalog-backend-module-azure'; const builder = await CatalogBuilder.create(env); /** ... other processors ... */ builder.addProcessor(new AzureDevOpsDiscoveryProcessor(env.reader));迁移后,改用catalog.providers.azureDevOps配置与AzureDevOpsEntityProvider.fromConfig:
# app-config.yaml catalog: providers: azureDevOps: anyProviderId: host: selfhostedazure.yourcompany.com # This is only really needed for on-premise user, defaults to dev.azure.com organization: myorg # For on-premise this would be your Collection project: myproject repository: service-* path: /catalog-info.yaml/* packages/backend/src/plugins/catalog.ts */ import { AzureDevOpsEntityProvider } from '@backstage/plugin-catalog-backend-module-azure'; const builder = await CatalogBuilder.create(env); /** ... other processors and/or providers ... */ builder.addEntityProvider( AzureDevOpsEntityProvider.fromConfig(env.config, { logger: env.logger, schedule: env.scheduler.createScheduledTaskRunner({ frequency: { minutes: 30 }, timeout: { minutes: 3 }, }), }), );要点:host仅本地部署(on-premise)才需要显式配置,默认为dev.azure.com;organization在本地部署场景对应你的 Collection;repository支持service-*这样的通配符匹配。
GitLab:GitlabDiscoveryEntityProvider与性能优化标志
@backstage/plugin-catalog-backend-module-gitlab@0.1.4新增GitlabDiscoveryEntityProvider(实现见 plugins/catalog-backend-module-gitlab/src/providers/GitlabDiscoveryEntityProvider.ts),替代GitlabDiscoveryProcessor。
迁移前:
# app-config.yaml catalog: locations: - type: gitlab-discovery target: https://company.gitlab.com/prefix/*/catalog-info.yaml/* packages/backend/src/plugins/catalog.ts */ import { GitlabDiscoveryProcessor } from '@backstage/plugin-catalog-backend-module-gitlab'; const builder = await CatalogBuilder.create(env); /** ... other processors ... */ builder.addProcessor( GitLabDiscoveryProcessor.fromConfig(env.config, { logger: env.logger }), );迁移后:
# app-config.yaml catalog: providers: gitlab: yourProviderId: # identifies your dataset / provider independent of config changes host: gitlab-host # Identifies one of the hosts set up in the integrations branch: main # Optional. Uses `master` as default group: example-group # Group and subgroup (if needed) to look for repositories entityFilename: catalog-info.yaml # Optional. Defaults to `catalog-info.yaml`/* packages/backend/src/plugins/catalog.ts */ import { GitlabDiscoveryEntityProvider } from '@backstage/plugin-catalog-backend-module-gitlab'; const builder = await CatalogBuilder.create(env); /** ... other processors and/or providers ... */ builder.addEntityProvider( ...GitlabDiscoveryEntityProvider.fromConfig(env.config, { logger: env.logger, schedule: env.scheduler.createScheduledTaskRunner({ frequency: { minutes: 30 }, timeout: { minutes: 3 }, }), }), );注意 Provider 返回的是数组,注册时需用展开运算符...展开。该模块还带了两项值得关注的优化:
- 首次查询 GitLab API 时不再携带
last_activity_after时间戳; - 新增
skipReposWithoutExactFileMatch标志:当仓库中不存在catalog-info.yaml时不再创建 location 对象,从而显著降低 GitLab 返回 404 的请求量:
const processor = GitLabDiscoveryProcessor.fromConfig(config, { logger, skipReposWithoutExactFileMatch: true, });警告:该新功能不支持在仓库文件路径中使用 glob 通配符。
Scaffolder 增强:任务列表页、listTasksAPI 与 Gerrit 支持
v1.3.0 对 Scaffolder 的改进覆盖前后端,使模板执行任务的可见性与控制能力大幅提升。
新增/create/tasks任务列表页
@backstage/plugin-scaffolder@1.3.0新增/create/tasks页面,用于展示 Scaffolder 已运行的任务,并支持按"当前登录用户"与"全部任务"两种维度过滤。其前端路由定义可见 plugins/scaffolder/src/routes.ts 中的scaffolderListTaskRouteRef(路径为/tasks,挂在/create之下构成/create/tasks)。
对应地,ScaffolderApi接口新增了可选的listTasks方法,调用时需传入必填参数filterByOwnership,用于按归属过滤任务。
后端/v2/tasks列表路由
@backstage/plugin-scaffolder-backend@1.3.0为TaskBroker与TaskStore接口新增了可选的list方法(按可选的userEntityRef过滤),并在DatabaseTaskStore中实现了该方法。同时新增/v2/tasks路由,可通过createdBy查询参数按用户实体引用(userEntityRef)列出任务。当前仓库中该路由的实现位于 plugins/scaffolder-backend/src/service/router.ts,GET /v2/tasks会解析createdBy参数并透传给任务存储层进行过滤。同文件还提供了/v2/tasks/:taskId、cancel、retry、eventstream等任务生命周期管理端点。
表单字段访问:自定义字段读取其他表单数据
ScaffolderApi与字段扩展机制支持自定义字段组件通过props.formContext.formData读取表单中其他字段的值:
const CustomFieldExtensionComponent = (props: FieldExtensionComponentProps<string[]>) => { const { formData } = props.formContext; ... }; const CustomFieldExtension = scaffolderPlugin.provide( createScaffolderFieldExtension({ name: ..., component: CustomFieldExtensionComponent, validation: ... }) );这一能力让字段间的联动(如根据仓库类型动态调整可见选项)成为可能。
新的 Gerrit 集成与gerrit:publish动作
- 前端新增针对 Gerrit 的
RepoUrlPicker(@backstage/plugin-scaffolder@1.3.0); - 后端新增
gerrit:publishscaffolder 动作(@backstage/plugin-scaffolder-backend@1.3.0); @backstage/integration@1.2.1同步修复了 Gerrit 集成中resolveUrl对绝对路径的处理。
publish:github协作者参数修复(破坏性行为变化)
publish:github动作修复了"无法添加用户为协作者"的缺陷,但代价是参数语义发生了变化:
- 添加团队为协作者:使用
team字段(username字段仍可用但已弃用,官方建议迁移到team); - 添加用户为协作者:使用
user字段。
- id: publish name: Publish action: publish:github input: repoUrl: ... collaborators: - access: ... team: my_team - access: ... user: my_username同时,publish:gitlab:merge-request动作的projectid输入参数被弃用——它已能从repoUrl中解码,不再需要单独传入;其projectid输出也被projectPath取代。另外该版本还新增了"不保护默认分支"的选项,并在仓库创建失败时给出更详尽的错误说明。
模板脱离default命名空间运行
Scaffolder 前端与后端均新增了对非default命名空间模板的支持(@backstage/plugin-scaffolder@1.3.0与@backstage/plugin-scaffolder-backend@1.3.0各自的f93af969cd变更),并修复了MultistepJsonForm的 review mask 行为(设置 mask 后不再需要额外的show: true),以及 dry-run 内容上传时对二进制文件与超大文件的处理。
搜索体验升级:结果rank与discover分析事件
v1.3.0 围绕搜索体验做了一轮跨插件联动优化,核心是让搜索结果的可分析性更强:
@backstage/plugin-search-common@0.3.5在Result类型上新增可选的rank属性,表示某结果在结果集中的排名(从 1 开始);@backstage/plugin-search-backend@0.5.3以及-elasticsearch@0.1.5、-pg@0.3.4提供的搜索引擎现在都会为所有结果附加分页感知(pagination-aware)的rank值;@backstage/plugin-catalog@1.3.0、@backstage/plugin-techdocs@1.2.0提供的<*ResultListItem />组件将点击分析事件从click升级为discover:事件以结果排名作为value属性,同时保留点击目标作为to属性。这一设计简化了搜索漏斗分析——discover事件语义上代表"发现",比"点击"更贴合搜索结果场景。
应用侧如需让自定义搜索组件参与分析,可在渲染结果项时透传rank。此外,@backstage/plugin-search@0.9.0移除了SearchPageNext、SearchBarNext等 pre-alpha 组件,请改用@backstage/plugin-search-react或@backstage/plugin-search中的非*Next等价组件;DefaultResultListItem、SearchBar(含SearchBarBase)、SearchFilter(含.Checkbox/.Select/.Autocomplete)、SearchResult、SearchResultPager等组件均已从@backstage/plugin-search迁移至@backstage/plugin-search-react导出,旧位置已弃用、未来将移除。
TechDocs 改进:并发构建限制与构建日志输出
@backstage/plugin-techdocs-backend@1.1.2带来两项运维向增强:
- 并发构建上限:当
techdocs.builder配置为local时,并发构建数被限制为 10,超出部分将排队等待。若确有更高并发需求,官方建议横向扩容 TechDocs 后端部署,或改用external构建方式; - 构建日志输出到日志传输层:
createRouter新增buildLogTransport参数,可将构建日志同时输出到后端日志流(而不只是前端事件流),便于在浏览器之外捕获构建失败原因。典型用法如下(完整示例见 plugins/techdocs-backend 相关代码):
import { DockerContainerRunner } from '@backstage/backend-common'; import { createRouter, Generators, Preparers, Publisher, } from '@backstage/plugin-techdocs-backend'; import Docker from 'dockerode'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; export default async function createPlugin( env: PluginEnvironment, ): Promise<Router> { const preparers = await Preparers.fromConfig(env.config, { logger: env.logger, reader: env.reader, }); const dockerClient = new Docker(); const containerRunner = new DockerContainerRunner({ dockerClient }); const generators = await Generators.fromConfig(env.config, { logger: env.logger, containerRunner, }); const publisher = await Publisher.fromConfig(env.config, { logger: env.logger, discovery: env.discovery, }); await publisher.getReadiness(); return await createRouter({ preparers, generators, publisher, logger: env.logger, // Passing a buildLogTransport as a parameter in createRouter will enable // capturing build logs to a backend log stream buildLogTransport: env.logger, config: env.config, discovery: env.discovery, cache: env.cache, }); }同期前端@backstage/plugin-techdocs@1.2.0的改进包括:EntityTechdocsContent改用对象而非<Route>元素以修复子页面 outlet 为空导致 addon 不渲染的问题;读者页样式转换逻辑被重构为若干 hooks(sanitizeDOM等转换器改为 hook);addons 渲染过程修复了侧边栏闪烁与重复创建的问题;TechDocsReaderPageHeader与TechDocsSearch优先使用实体标题作为文案;并为 Catalog / TechDocs 搜索结果新增可选图标。
其他值得关注的新插件与能力
新插件首发
@backstage/plugin-dynatrace@0.1.0:Dynatrace 观测平台前端插件;@backstage/plugin-vault@0.1.0与@backstage/plugin-vault-backend@0.1.0:HashiCorp Vault 密钥管理的前后端插件(首次实现,详情见各插件 README);@backstage/plugin-github-pull-requests-board@0.1.0:GitHub Pull Requests 看板插件。
Kubernetes 支持扩展
@backstage/plugin-kubernetes-backend@0.6.0与@backstage/plugin-kubernetes-common@0.3.0新增对 StatefulSet 的数据拉取支持,前端@backstage/plugin-kubernetes@0.6.6以与 Deployments 相同的折叠面板方式展示 StatefulSet,并新增 CPU/内存 request/limit 展示、Kubernetes 页签刷新间隔可配置、多命名空间下 HPA 匹配修复、Azure token 缓存刷新等改进。
权限体系完善
@backstage/plugin-permission-node@0.6.2新增权限元数据聚合端点/.well-known/backstage/permissions/metadata,默认返回插件支持的权限规则信息;插件作者可通过createPermissionIntegrationRouter的可选permissions参数补充Permission对象(未来该参数将变为必填)。
Catalog 杂项
CatalogBuilder.addEntityProvider支持以数组形式一次传入多个 Provider,无需再逐个展开(builder.addEntityProvider(getArrayOfProviders()));- Catalog 后端禁止通过 location 服务注册除
'url'类型以外的任何 location 类型; plugin-catalog@1.3.0的isKind、isComponentType、isNamespace过滤器支持传入值数组进行匹配;plugin-org@0.5.6的MyGroupsSidebarItem新增filter属性,可按spec.type等条件过滤所展示的组,例如filter={{ 'spec.type': 'team' }};- LDAP 模块新增 TLS 连接配置支持;
plugin-catalog-backend-module-github@0.1.4为 GitHub Teams Group 实体补充了编辑 URL。
升级到 v1.3.0 的检查清单
综合上文,从 v1.2.0 升级到 v1.3.0 时建议逐项核对:
- Token 生命周期:检查所有
getToken()调用点,确保每次按需获取,不缓存复用;为旧 token 的exp过期留出切换窗口; - Git 平台发现迁移:若使用 Bitbucket Cloud / Azure DevOps / GitLab 的 discovery Processor,迁移到对应的 Entity Provider 并补充
schedule配置(代码或配置二选一); - Scaffolder:核对
publish:github协作者字段(user/team),评估是否迁移publish:gitlab:merge-request的projectid用法; - 搜索组件导入:将
SearchBar、SearchFilter、DefaultResultListItem等组件改从@backstage/plugin-search-react导入,删除*Next组件引用; - TechDocs:如需构建日志,在
createRouter中传入buildLogTransport;评估local构建模式下 10 并发上限是否满足需求; - 权限端点:可选地在
createPermissionIntegrationRouter中补充permissions参数,为元数据端点提供更丰富的信息。
本文所有代码示例均来自变更日志原文与仓库当前实现(如 plugins/catalog-backend-module-bitbucket-cloud 的 Provider 与配置解析源码、plugins/scaffolder-backend/src/service/router.ts 的/v2/tasks实现),可在对应路径继续深入研读。
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考