Backstage Bitbucket Server 目录发现:Entity Provider 安装、配置与源码原理
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
本文围绕 Backstage 软件目录(Software Catalog)的 Bitbucket Server 集成,完整讲解如何通过@backstage/plugin-catalog-backend-module-bitbucket-server提供的实体提供器(Entity Provider)自动发现 Bitbucket Server 上各仓库中的 catalog 配置文件(默认catalog-info.yaml),并将其注册为 Location 实体、进而接入目录处理流水线。读完本文,你将掌握该 Provider 的安装注册方式、事件驱动通道的选择、catalog.providers.bitbucketServer全部配置项的含义与默认值,并能从源码层理解其分页扫描、过滤、位置校验与增量更新机制。
工作原理:从静态注册到自动发现
Backstage 目录的数据来源通常有两种方式:在静态配置中声明 Location,或通过 catalog-import 插件手工注册。当 Bitbucket Server 上的仓库数量庞大、变更频繁时,这两种方式都难以维护。
Bitbucket Server 集成为此提供了一个专用的实体提供器(BitbucketServerEntityProvider),其工作流程是:
- 通过 Bitbucket Server REST API 分页枚举全部项目(Project)与仓库(Repository);
- 按配置的过滤器(项目键、仓库 slug、是否跳过归档仓库)筛选;
- 对命中的仓库,构造
catalogPath指向的 catalog 文件位置,将其作为Location 实体输出; - Location 实体进入目录处理流水线后,catalog 文件内声明的所有实体(Component、API、System 等)会被逐一解析并收录进目录。
这套机制可以作为静态 Location 或手动注册的替代方案,实现"仓库里放了catalog-info.yaml,目录就自动有对应实体"的自动化效果。
前置条件:配置 Bitbucket Server 集成
使用该 Provider 之前,必须先完成 Bitbucket Server 集成配置,因为 Provider 在启动时会用host去匹配已注册的集成实例(详见下文源码剖析)。
在app-config.yaml的integrations节点下添加 Bitbucket Server 条目,支持 Token 与 Basic Auth 两种认证方式:
# Token 认证 integrations: bitbucketServer: - host: bitbucket.mycompany.com apiBaseUrl: https://bitbucket.mycompany.com/rest/api/1.0 token: ${BITBUCKET_SERVER_TOKEN}# Basic Auth 认证 integrations: bitbucketServer: - host: bitbucket.company.com apiBaseUrl: https://bitbucket.mycompany.com/rest/api/1.0 username: ${BITBUCKET_SERVER_USERNAME} password: ${BITBUCKET_SERVER_PASSWORD}各字段说明:
| 字段 | 必填 | 说明 |
|---|---|---|
host | 是 | Bitbucket Server 实例主机名,如bitbucket.mycompany.com |
token | 否 | Bitbucket Server 期望的个人访问令牌(Personal Access Token) |
username | 否 | Basic Auth 用户名 |
password | 否 | Basic Auth 密码;注意 token 也可作为 password 的替代品使用 |
apiBaseUrl | 否 | Bitbucket Server REST API 地址,自托管实例通常为https://<host>/rest/api/1.0 |
安装与后端注册
该 Provider 默认不会被安装,需要先向 backend 包添加依赖。在 Backstage 仓库根目录执行:
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-bitbucket-server随后在 backend 入口(新后端系统的packages/backend/src/index.ts)中注册相关模块:
// 可选:如果希望通过 HTTP 端点接收外部事件 // backend.add(import('@backstage/plugin-events-backend')); // 可选:如果希望改用 AWS SQS 而非 HTTP 端点接收外部事件 // backend.add(import('@backstage/plugin-events-backend-module-aws-sqs')); backend.add(import('@backstage/plugin-events-backend-module-bitbucket-server')); backend.add( import('@backstage/plugin-catalog-backend-module-bitbucket-server'), );注册后,后端模块 catalogModuleBitbucketServerEntityProvider 会自动读取配置、实例化 Provider 并挂载到目录处理扩展点,同时启动 BitbucketServerScmEventsBridge 用于接收 Bitbucket Server 的 webhook 事件。
选择外部事件接收通道
事件是 Provider 实现"推"式增量更新的关键。你需要决定如何从 Bitbucket Server 接收事件,可选通道包括:
- 通过 HTTP 端点接收(events-backend);
- 通过 AWS SQS 队列接收(events-backend-module-aws-sqs);
- 通过 Google Pub/Sub 接收(events-backend-module-google-pubsub);
- 通过 Kafka 主题接收(events-backend-module-kafka)。
无论选择哪种通道,都需要 Bitbucket Server 侧配置对应的 webhook 订阅,将仓库的repo:refs_changed(推送)等事件投递到上述通道。
目录发现配置详解
在app-config.yaml的catalog.providers下添加bitbucketServer配置段,可配置一个或多个 Provider 实例:
catalog: providers: bitbucketServer: yourProviderId: # 用于标识你摄入的数据集 host: 'bitbucket.mycompany.com' catalogPath: /catalog-info.yaml # 默认值 filters: # 可选 projectKey: '^apis-.*$' # 可选;正则表达式 repoSlug: '^service-.*$' # 可选;正则表达式 skipArchivedRepos: true # 可选;布尔值 validateLocationsExist: false # 可选;布尔值 schedule: # 与 SchedulerServiceTaskScheduleDefinition 的选项一致 # 支持 cron、ISO duration、代码中使用的 "human duration" frequency: { minutes: 30 } # 支持 ISO duration、"human duration" timeout: { minutes: 3 }配置项说明
host(必填):Bitbucket Server 实例主机名。注意:该主机必须同时注册为 integration,否则 Provider 启动时会报错(见下文)。catalogPath(可选):查找catalog-info.yaml的路径,默认/catalog-info.yaml。以/开头时表示相对仓库根目录的绝对路径,例如/catalog-info.yaml、/backstage/catalog-info.yaml。filters(可选):projectKey(可选):用于按项目键过滤的正则表达式;repoSlug(可选):用于按仓库 slug 过滤的正则表达式;skipArchivedRepos(可选):布尔值,过滤掉已归档的仓库。
validateLocationsExist(可选):默认false。为true时,会在产出 Location 之前校验其对应的 catalog 文件在源仓库中真实存在,避免为不存在的文件生成无意义的 Location。schedule(可选):调度配置,用于周期性全量刷新,包含以下子项:frequency:任务执行频率(多久运行一次),系统会尽量避免重叠调用;timeout:单次任务运行的最大耗时;initialDelay(可选):首次执行前的等待时间;scope(可选):'global'或'local',设置并发控制的作用域。
提示:
frequency、timeout、initialDelay均支持 cron 表达式、ISO 时长(如PT30M)以及代码中常见的可读时长格式(如{ minutes: 30 })。
配置读取的两种形态
从源码 BitbucketServerEntityProviderConfig.ts 可以看到,配置读取支持两种形态:
- 单实例简写:若
catalog.providers.bitbucketServer节点下直接存在host键,则按单个 Provider 处理,其id固定为default; - 多实例形态:否则按
keys()遍历每个子键,将子键作为 Provider 的id,因此yourProviderId会体现在 Provider 名称中。
对应的 Provider 名称格式为bitbucketServer-provider:<id>(见 BitbucketServerEntityProvider.ts),日志与任务 ID 中均会出现。
源码剖析:发现流程与底层实现
集成校验与调度绑定
在 BitbucketServerEntityProvider.fromConfig 中:
- 通过
ScmIntegrations.fromConfig(config)构建集成注册表,并调用integrations.bitbucketServer.byHost(providerConfig.host)匹配集成实例——若找不到匹配集成,会抛出InputError,提示No BitbucketServer integration found that matches host ...,这正是"host 必须注册为 integration"的源码依据; - 调度来源二选一:代码传入的
schedule(任务执行器)或配置中的schedule;两者都没有时抛错拒绝启动。
全量刷新(Refresh)
周期性任务最终调用 refresh:
- 调用
findEntities()扫描并解析全部候选实体; - 通过
connection.applyMutation({ type: 'full', ... })一次性提交,将 Provider 发现的所有实体与目录当前状态做全量对齐(替换式更新)。
findEntities()的内部流程(BitbucketServerEntityProvider.ts)与前面"工作原理"一节完全对应:
- 使用 BitbucketServerClient 分页拉取项目(
/projects)与仓库(/projects/{key}/repos); - 依次应用
projectKey、repoSlug正则过滤与skipArchivedRepos过滤; - 若开启
validateLocationsExist,会调用getFile()请求.../raw/<catalogPath>端点:404 时跳过该仓库(debug 日志),其他异常状态码记 warn,网络异常记 error; - 对每个通过的仓库,构造
type: 'url'、presence: 'optional'的 Location 交给解析器。默认解析器 defaultBitbucketServerLocationParser 会把它转换为一个 Location 实体(locationSpecToLocationEntity); - 为每个实体补充
bitbucket.org/default-branch注解(默认分支信息),供后续事件处理判断是否为默认分支推送。
事件驱动的增量更新
Provider 在connect()时订阅主题bitbucketServer.repo:refs_changed(BitbucketServerEntityProvider.ts)。收到推送事件后,onRepoPush 会:
- 校验事件处理所需依赖(
catalogApi与auth,即 Catalog 服务与认证服务)是否齐全; - 重新解析该仓库的 Location 实体,并对比目录中已存在的 Location(按
target匹配); - 只有当事件确实发生在默认分支上时才继续处理,避免功能分支推送触发无意义的目录变更;
- 对仍在的实体执行
connection.refresh()(刷新处理),对有增删的实体通过applyMutation({ type: 'delta', added, removed })做增量对齐。
此外,外部通道收到的 webhook 原始事件会先经过 BitbucketServerScmEventsBridge(订阅bitbucketServer主题),由 analyzeBitbucketServerWebhookEvent 解析事件类型与负载,再发布为目录 SCM 事件供各 Provider 消费。
测试验证
该模块的单元测试覆盖了上述关键路径,例如 BitbucketServerEntityProvider.test.ts 通过 MSW mock REST API,验证了项目/仓库分页枚举、过滤规则(项目键、仓库 slug、归档仓库)、validateLocationsExist的行为以及repo:refs_changed事件触发的增量更新;配置解析的测试见 BitbucketServerEntityProviderConfig.test.ts。如需深入理解,可从这些文件入手。
实战注意事项
- host 一致性:
catalog.providers.bitbucketServer.<id>.host必须与integrations.bitbucketServer列表中某一项的host完全一致,否则 Provider 初始化即失败; - catalogPath 的写法:以
/开头表示仓库根目录下的绝对路径;客户端请求 raw 文件时会剥离前导/(见 BitbucketServerClient.getFile); - 性能权衡:全量刷新会遍历所有项目与仓库(分页拉取),仓库规模大时建议合理设置
frequency拉长周期,并尽量用filters缩小扫描范围;validateLocationsExist会为每个候选仓库额外发起一次 raw 请求,开启后扫描请求量明显上升,仅在有需要时启用; - 事件通道 vs 轮询:周期性调度属于"拉"式兜底,事件驱动属于"推"式实时更新;两者可同时启用,事件通道保证推送后的近实时同步,调度保证最终一致性;
- 单实例简写:如果只有一个 Provider 且不关心命名,可直接在
bitbucketServer下写host等键(简写形态),此时 Provider ID 为default。
通过上述配置,即可在 Backstage 中实现对 Bitbucket Server 仓库目录文件的自动发现与持续同步,让目录数据与代码仓库始终保持一致。
【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考