Backstage 1.28.0-next.1 版本解读:核心服务迁移、TestCaches 缓存测试与权限安全增强
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
本篇技术指南基于当前仓库 docs/releases/v1.28.0-next.1-changelog.md 展开,系统梳理 Backstage 1.28.0-next.1(预发布里程碑)中涉及的后端核心服务归位、外部访问令牌安全加固、通知处理器过滤、Scaffolder 任务级权限与 GitLab 流水线触发等关键变更。读者读完本文,能够掌握本次迭代的升级影响面、新 API 的用法,以及结合仓库源码理解每个变更背后的实现原理与测试验证方式。
说明:
*-next.*版本属于正式发布前的预发布版本,本文所述 API 与行为以当前仓库代码为准,正式版本可能在此基础上继续演进。
一、版本总览:本次迭代改动分布
v1.28.0-next.1 覆盖了后端框架、测试工具、Catalog、Kubernetes、Notifications、Scaffolder、CLI 等多个包,主要变更集中在以下几类:
| 变更类别 | 涉及包 | 变更内容 |
|---|---|---|
| 核心服务迁移 | @backstage/backend-common、@backstage/backend-defaults | 核心服务从backend-common迁移并废弃,统一归位到backend-defaults |
| 工厂类型重命名 | @backstage/backend-plugin-api | BackendPluginConfig等重命名为CreateBackendPluginOptions等 |
| 测试工具增强 | @backstage/backend-test-utils | 新增TestCaches;mockCredentials.service支持访问限制 |
| 外部令牌安全 | @backstage/backend-app-api、plugin-permission-node | 支持 JWKS 令牌;外部访问令牌支持accessRestrictions |
| 通知过滤 | plugin-notifications-backend、notifications-node | 新增按处理器(processor)过滤通知的能力 |
| Scaffolder 权限 | plugin-scaffolder、scaffolder-backend、scaffolder-common | 新增scaffolder.task.create/cancel/read三个任务级权限 |
| GitLab 集成 | plugin-scaffolder-backend-module-gitlab | 新增gitlab:pipeline:trigger动作 |
| Kubernetes 适配 | plugin-kubernetes-* | 全面迁移到autoscaling/v2API |
| 前端请求统一 | plugin-catalog-import、plugin-kubernetes、plugin-search | 从identityApi迁移到fetchApi |
二、后端核心服务迁移:backend-common废弃与backend-defaults归位
2.1 变更内容
本次变更(changeset02103be)同时作用于@backstage/backend-common@0.23.0-next.1与@backstage/backend-defaults@0.3.0-next.1:Deprecated and moved over core services to@backstage/backend-defaults,即把后端核心服务(core services)从backend-common中标记为废弃,并整体迁移到backend-defaults包。
这是 Backstage 新后端系统(new backend system)演进过程中的一次关键"归位"动作。在新后端系统下,应用入口通过createBackend()组装后端,而所有核心服务(日志、配置、数据库、缓存、调度、URL 读取等)的默认实现集中在backend-defaults。你可以在仓库 packages/backend-defaults/src/CreateBackend.ts 及其测试 packages/backend-defaults/src/CreateBackend.test.ts 中看到createBackend的组装逻辑。
2.2 对开发者的影响
- 新代码应优先从
@backstage/backend-defaults引入默认服务实现; - 旧代码中直接从
@backstage/backend-common引入核心服务的方式仍可运行,但会收到废弃提示,应尽快迁移; - 升级时只需把依赖声明从
backend-common调整到backend-defaults,并按新后端系统的导入路径更新 import 语句。
从依赖变化列表看,backend-common@0.23.0-next.1仍依赖backend-app-api、backend-plugin-api、config-loader、plugin-auth-node,说明它是作为过渡层存在,负责把旧 API 桥接到新实现,最终目标是将backend-common收敛为纯工具库。
2.3 工厂类型重命名:统一前后端签名
@backstage/backend-plugin-api@0.6.19-next.1(changeset0665b7e)将三个后端工厂配置类型重命名,以标准化前后端工厂函数的签名:
| 旧名称 | 新名称 |
|---|---|
BackendPluginConfig | CreateBackendPluginOptions |
BackendModuleConfig | CreateBackendModuleOptions |
ExtensionPointConfig | CreateExtensionPointOptions |
在仓库源码中可以看到重命名后的实际落点:packages/backend-plugin-api/src/wiring/createBackendPlugin.ts 定义了CreateBackendPluginOptions,packages/backend-plugin-api/src/wiring/createBackendModule.ts 定义了CreateBackendModuleOptions。这与前端插件体系(createPlugin/createExtensionPoint)的选项类型命名风格保持一致。
三、测试工具箱升级:TestCaches与凭据访问限制
3.1TestCaches:与TestDatabases对标的缓存测试框架
@backstage/backend-test-utils@0.4.0-next.1的核心新增(changeset805cbe7)是TestCaches,它的定位与既有的TestDatabases完全对应,只不过面向的是缓存存储。其实现位于 packages/backend-test-utils/src/cache/TestCaches.ts,支持四种缓存目标(定义于 packages/backend-test-utils/src/cache/types.ts):
| 测试缓存 ID | 底层存储 | 说明 |
|---|---|---|
MEMORY | 内存(Keyv) | 无需 Docker,开箱即用 |
REDIS_7 | Redis 7.x | 通过 Docker 拉起,或连接外部实例 |
VALKEY_8 | Valkey 8.x | 通过 Docker 拉起,或连接外部实例 |
MEMCACHED_1 | Memcached 1.x | 通过 Docker 拉起,或连接外部实例 |
从 types.ts 可以看到每种缓存的连接配置细节:Redis、Valkey、Memcached 都有对应的connectionStringEnvironmentVariableName环境变量(BACKSTAGE_TEST_CACHE_REDIS7_CONNECTION_STRING、BACKSTAGE_TEST_CACHE_VALKEY8_CONNECTION_STRING、BACKSTAGE_TEST_CACHE_MEMCACHED1_CONNECTION_STRING)。也就是说:
- 设置环境变量时,
TestCaches会连接你提供的外部实例(connectToExternalRedis等分支); - 未设置环境变量且 Docker 可用时,
TestCaches会用 testcontainers 自动拉起对应容器(startRedisContainer等); - Docker 被禁用(
isDockerDisabledForTests())时,需要 Docker 的缓存 ID 会被自动过滤掉,只剩MEMORY等无需 Docker 的选项。
3.2 典型用法
参照官方测试 packages/backend-test-utils/src/cache/TestCaches.test.ts,使用模式如下:
import { TestCaches } from '@backstage/backend-test-utils'; // 在文件/describe 顶部创建单个实例(会自动注册 afterAll 清理) const caches = TestCaches.create(); // 对每个支持的缓存逐一跑参数化用例 describe.each(caches.eachSupportedId())('TestCaches, %p', cacheId => { it('fires up a cache', async () => { const { keyv } = await caches.init(cacheId); await keyv.set('test', 'value'); await expect(keyv.get('test')).resolves.toBe('value'); }); });关键设计要点:
- 单实例复用:
TestCaches.create()在文件顶部创建一次,避免每个测试都去拉起容器(容器启动很耗时); - init 快速清空:每次
init(id)返回全新、已清空的缓存实例(await instance.keyv.clear()),保证测试间无脏数据;测试文件中的clears between tests用例专门验证了这一点; - 参数化遍历:
eachSupportedId()让同一组断言跑遍所有支持的缓存驱动; - 自动回收:
afterAll中调用shutdown()统一停止容器。
你还可以用TestCaches.create({ ids: ['MEMORY'] })或TestCaches.setDefaults({ ids: [...] })限定测试目标,supports(id)用于在运行时判断当前环境是否支持某缓存。
3.3mockCredentials.service支持访问限制
同为backend-test-utils@0.4.0-next.1的另一个变更(changeset9e63318)允许为mockCredentials.service传入访问限制(access restrictions),使其能在测试中模拟带accessRestrictions的服务凭据。这配合下文"外部访问令牌加固"一起使用:既有mockCredentials.service()返回基础服务凭据(参见测试 packages/backend-test-utils/src/services/MockAuthService.test.ts),现在可以进一步构造受限凭据来验证授权拦截逻辑。
四、外部访问令牌加固:JWKS 支持与accessRestrictions
4.1ExternalTokenHandler支持 JWKS 令牌
@backstage/backend-app-api@0.7.6-next.1(changeset398b82a)为ExternalTokenHandler添加了 JWKS(JSON Web Key Set)令牌支持。在此之前,外部访问令牌依赖静态密钥或预共享密钥验证;引入 JWKS 后,Backstage 后端可以对接提供 JWKS 端点的身份提供方,用公开密钥动态校验由外部系统签发的 JWT,从而支持更标准、可轮换密钥的外部服务到服务认证场景。
这与仓库中 docs/architecture-decisions/adr013-use-node-fetch.md 一脉相承——本次迭代中多个包(plugin-notifications-node、plugin-auth-backend-module-cloudflare-access-provider、plugin-scaffolder-backend-module-gitea、plugin-scaffolder-backend-module-sentry,changeset1354d81)同时把fetch调用统一替换为node-fetch,确保 Node 环境下的 HTTP 行为一致且可测试。
4.2 服务主体/外部访问令牌的accessRestrictions
另一个更重要的安全特性(changeset9e63318,同时作用于backend-app-api与backend-plugin-api):为外部访问服务令牌(external access service tokens)及服务主体(service principals)增加了可选的accessRestrictions,用于把令牌的访问范围限制到特定插件或特定权限。
配合@backstage/plugin-permission-node@0.7.30-next.1的变更("Ensure that service token access restrictions, when present, are taken into account"),权限框架会在鉴权时主动读取并强制执行这些限制。这一机制的实际价值是:当第三方系统通过服务令牌调用 Backstage API 时,管理员可以按最小权限原则限定它只能访问某几个插件、执行某几类权限操作,而不是默认放行全部接口。
五、通知系统:按处理器过滤与性能修复
5.1 处理器过滤(processor filters)
本次迭代对通知系统做了集中增强:
@backstage/plugin-notifications-backend@0.3.0-next.1:adding filtering of notifications by processors(changeset07a789b);@backstage/plugin-notifications-backend-module-email@0.1.0-next.1:add notification filters(同一 changeset);@backstage/plugin-notifications-node@0.2.0-next.1:add notifications filtering by processors(同一 changeset)。
在 plugins/notifications-node/src/extensions.ts 中可以看到NotificationProcessor接口新增的可选方法:
/** * notification filters are used to call the processor only in certain conditions */ getNotificationFilters?(): NotificationProcessorFilters;在 plugins/notifications-backend/src/service/router.ts 的filterProcessors实现中,发送通知时会逐个处理器执行两级过滤:
- 用户偏好过滤:如果通知有明确的接收用户,先检查该用户是否启用了该处理器的通知渠道(
isNotificationsEnabled,结合channel: processor.getName()与topic); - 处理器自定义过滤:若处理器实现了
getNotificationFilters,则用返回的过滤器判断当前通知是否应该交给该处理器处理。
这意味着像 email 处理器这样的下游通道,可以只在满足特定 topic、来源等条件时才被触发,避免对每条通知都做无谓的外部发送。
5.2 标题计数器性能修复
@backstage/plugin-notifications@0.2.2-next.1(changeset6d196b4)修复了通知标题未读计数器的性能问题。前端通知插件通过 signals 机制实时接收未读数更新,本次修复优化了计数器更新的计算路径,减少在高频通知场景下的渲染与计算开销。
六、Scaffolder:任务级权限与 GitLab 流水线触发
6.1 三个新任务权限
本次迭代(changesetbcec60f)为 Scaffolder 引入了三个任务级(task-level)权限,前后端同步落地:
| 权限名 | 说明 | 定义位置 |
|---|---|---|
scaffolder.task.create | 创建任务(create 动作) | plugins/scaffolder-common/src/permissions.ts |
scaffolder.task.cancel | 取消任务 | plugins/scaffolder-common/src/permissions.ts |
scaffolder.task.read | 读取任务及任务日志(read 动作) | plugins/scaffolder-common/src/permissions.ts |
从 permissions.ts 可以看到配套的资源类型RESOURCE_TYPE_SCAFFOLDER_TASK = 'scaffolder-task',其中taskCreatePermission未声明 resourceType(作用于全局创建动作),taskReadPermission与taskCancelPermission则绑定scaffolder-task资源类型,可基于具体任务做细粒度授权。
后端方面,plugin-scaffolder-backend@1.22.8-next.1将这三个权限接入对应端点;前端方面,plugin-scaffolder@1.20.2-next.1与plugin-catalog@1.20.1-next.1同步更新了ContextMenu、ActionsPage、OngoingTask、TemplateCard等组件,让 UI 根据当前用户的权限动态显示/隐藏"创建任务""取消任务""查看任务"等入口。这样管理员可以通过权限策略(如permission-backend-module-allow-all-policy或自定义策略)精细控制哪些用户能操作 Scaffolder 任务。
6.2 新动作gitlab:pipeline:trigger
@backstage/plugin-scaffolder-backend-module-gitlab@0.4.1-next.1(changeset829e0ec)新增gitlab:pipeline:trigger动作,用于在模板中触发 GitLab 流水线。其完整实现位于 plugins/scaffolder-backend-module-gitlab/src/actions/gitlabPipelineTrigger.ts,输入输出 schema 如下:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
repoUrl | string | 是 | 格式gitlab.com?repo=project_name&owner=group_name |
projectId | number | 是 | GitLab 项目 ID |
tokenDescription | string | 是 | 流水线触发令牌(pipeline trigger token)的描述 |
branch | string | 是 | 要触发的分支 |
token | string | 否 | 用于 GitLab 授权的令牌(缺省时使用 SCM 用户凭据) |
variables | object | 否 | 传给流水线的键值变量 |
输出pipelineUrl | string | — | 触发的流水线 URL |
实现要点(结合 gitlabPipelineTrigger.ts):
- 动作内部先
create一个临时流水线触发令牌,用trigger触发流水线,最后在finally中remove该令牌,避免凭据残留; - 整个触发过程包裹在
ctx.checkpoint中,checkpoint 键为trigger.pipeline.${projectId}.${branch}.${tokenDescription}——这与 Scaffolder 任务幂等机制配合,任务重试时不会重复触发流水线;只有非敏感的pipeline.web_url被写入 checkpoint 状态; - 触发失败(无
pipeline.id)时抛出InputError。
示例定义与测试见 plugins/scaffolder-backend-module-gitlab/src/actions/gitlabPipelineTrigger.examples.ts 与 gitlabPipelineTrigger.examples.test.ts。
模板中使用示例:
steps: - id: triggerPipeline action: gitlab:pipeline:trigger name: Trigger GitLab Pipeline input: repoUrl: 'gitlab.com?repo=my-service&owner=my-group' projectId: 42 branch: main tokenDescription: 'release-trigger' variables: ENVIRONMENT: production6.3 其他修复
plugin-scaffolder@1.20.2-next.1(changeset75dcd7e)修复formData类型应为可选(optional)的问题,因为它可能为undefined;同时plugin-scaffolder-react@1.8.7-next.1修复一处拼写错误(changeset928cfa0)。
七、Kubernetes 插件:迁移到autoscaling/v2
plugin-kubernetes-backend@0.18.0-next.1、plugin-kubernetes-common@0.8.0-next.0、plugin-kubernetes-react@0.4.0-next.1统一执行了Update kubernetes plugins to use autoscaling/v2(changeset0177f75)。
autoscaling/v2是 Kubernetes HPA(Horizontal Pod Autoscaler)的稳定版本 API(autoscaling/v1之后引入,autoscaling/v2beta2的正式化),支持按多个指标(CPU、内存、自定义指标等)自动扩缩容。仓库中 Kubernetes 相关插件在错误检测等场景的 fixture 已切换到该版本,例如 plugins/kubernetes-common/src/error-detection/fixtures/hpa-healthy.json 中"apiVersion": "autoscaling/v2"。本次升级意味着 Backstage 的 Kubernetes 展示与错误检测逻辑全面面向新版 HPA 资源结构解析spec.metrics(支持多条指标及目标类型)。
八、Catalog:LDAP 模块迁移与 commit hash 编辑链接修复
8.1 LDAP 目录模块迁移到新后端系统
@backstage/plugin-catalog-backend-module-ldap@0.6.0-next.1(changesetdebcc8c)完成了Migrate LDAP catalog module to the new backend system。LDAP 作为企业目录数据源,其 provider 现在可以直接作为新后端系统的模块注册(catalogModuleLdap风格的入口),无需再走旧的后端插件工厂,配置也统一纳入新后端的backend.plugins/backend.modules配置体系。
8.2 commit hash 正则校验
@backstage/plugin-catalog-backend@1.23.0-next.1(changesetd779e3b)为编辑链接(edit URL)生成逻辑增加了commit hash 正则测试:当 Catalog 位置指向一个 git commit 时,不再为其生成"编辑"链接。
实现位于 plugins/catalog-backend/src/processors/AnnotateLocationEntityProcessor.ts:
const commitHashRegExp = /\b[0-9a-f]{40,}\b/; // ... if (location.type === 'url') { const scmIntegration = integrations.byUrl(location.target); viewUrl = location.target; // 若 URL 来自 git commit(40 位以上十六进制哈希),跳过编辑链接 if (!commitHashRegExp.test(location.target)) { editUrl = scmIntegration?.resolveEditUrl(location.target); } // ... }这样,指向某个具体 commit 的 catalog-info 不会错误地生成一个指向"分支"的编辑链接(因为 commit 是只读快照),避免用户在 UI 上点击编辑却无法提交的困惑。
8.3 前端请求统一:identityApi→fetchApi
plugin-catalog-import@0.12.0-next.1、plugin-kubernetes@0.11.11-next.1、plugin-search@1.4.12-next.1等多个前端插件(changeset4f92394)完成Migrate from identityApi to fetchApi in frontend plugins。这是 Backstage 前端 API 规范化的长期动作:插件不再直接通过identityApi.getCredentials()手工拼接请求头,而是统一使用fetchApi服务(@backstage/core-app-api提供的FetchApi),由框架统一注入认证与代理逻辑,既减少样板代码,也避免因忘记携带凭据导致的 401。
九、CLI 与工具链更新
9.1 repo-tools:--client-additional-properties
@backstage/repo-tools@0.9.1-next.1(changeset8721a02)为openapi generate命令新增--client-additional-properties选项,允许在生成 OpenAPI 客户端时追加额外的属性配置,便于按项目需要定制生成的客户端代码。
9.2 CLI 修复
@backstage/cli@0.26.7-next.1包含两个修复:
788eca7:修复通过 CLI 新建插件时生成的 README 内容问题;c00f7ee:修复 Vite 依赖在esm加载与cjsimport 之间不一致的问题,保证前端构建与依赖解析行为一致。
9.3 其他包级变更
@backstage/backend-tasks@0.5.24-next.1(changeseted473cd):TaskScheduleDefinitionConfig的废弃注释更新为指向SchedulerServiceTaskScheduleDefinitionConfig,引导开发者使用新的调度任务配置类型;@backstage/plugin-catalog@1.20.1-next.1(changeseta2d2649):在/alpha子路径下导出catalogTranslationRef,支持 Catalog 插件的国际化(i18n)翻译引用;@backstage/plugin-catalog-backend-module-gitlab@0.3.17-next.1:修复GitlabOrgDiscoveryEntityProvider在缺少orgEnabled配置键时报错的问题(150fc77),以及GitlabDiscoveryEntityProvider中 fallback 分支优先于 GitLab 默认分支的问题(f271164);@backstage/plugin-search-backend@1.5.10-next.1:将@backstage/repo-tools移至 devDependencies(34dc47d)。
十、升级建议与验证路径
对于准备升级到 v1.28.0-next.1 的开发者,建议按以下顺序处理:
- 先处理后端服务导入迁移:把从
@backstage/backend-common引入核心服务的代码改为从@backstage/backend-defaults引入,消除废弃警告; - 同步重命名工厂类型:将
BackendPluginConfig→CreateBackendPluginOptions、BackendModuleConfig→CreateBackendModuleOptions、ExtensionPointConfig→CreateExtensionPointOptions; - 评估外部服务令牌安全:如需限制第三方调用范围,为外部访问服务令牌配置
accessRestrictions;如需对接 JWKS 身份提供方,启用ExternalTokenHandler的 JWKS 校验; - 为缓存类代码补测试:使用
TestCaches编写 Redis/Valkey/Memcached 集成测试,方式与TestDatabases完全对称; - 调整 Scaffolder 权限策略:如果现有自定义权限策略对 Scaffolder 做了通配放行,建议补充对
scaffolder.task.create/cancel/read的显式规则,避免新权限默认被拒绝或过度放行; - Kubernetes 插件:确认集群 HPA 资源使用
autoscaling/v2格式,Backstage 侧解析已兼容。
以上每项变更都能在当前仓库中找到对应源码与测试作为验证依据:TestCaches的实现与测试位于 packages/backend-test-utils/src/cache/,任务权限定义位于 plugins/scaffolder-common/src/permissions.ts,通知处理器过滤逻辑位于 plugins/notifications-backend/src/service/router.ts,GitLab 流水线触发动作位于 plugins/scaffolder-backend-module-gitlab/src/actions/gitlabPipelineTrigger.ts。读者可直接深入这些路径核对实现细节,或参考 docs/releases/v1.28.0.md 查看正式版的变化收敛情况。
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考