--- name: 34-artifactory-module-architecture description: Artifactory 制品库模块架构指南,涵盖制品上传下载、存储后端适配、制品元数据、清理策略、权限控制。当用户开发制品库功能、处理制品存储、配置清理策略或实现制品管理时使用。 --- # Artifactory 制品库模块架构指南 > **模块定位**: Artifactory 是 BK-CI 的制品库模块,负责构建产物的存储、下载、管理,支持对接本地磁盘存储或 BkRepo(蓝鲸制品库)等后端存储系统。 ## 一、模块整体结构 ### 1.1 子模块划分 ``` src/backend/ci/core/artifactory/ ├── api-artifactory/ # API 接口定义层 │ └── src/main/kotlin/com/tencent/devops/artifactory/ │ ├── api/ │ │ ├── builds/ # 构建时接口 │ │ ├── service/ # 服务间接口 │ │ └── user/ # 用户接口 │ ├── constant/ # 常量和消息码 │ └── pojo/ # 数据对象 │ └── enums/ # 枚举定义 │ ├── biz-artifactory/ # 业务逻辑层 │ └── src/main/kotlin/com/tencent/devops/artifactory/ │ ├── config/ # 配置类 │ ├── dao/ # 数据访问层 │ ├── mq/ # 消息队列监听 │ ├── resources/ # API 实现 │ ├── service/ # 业务服务 │ │ └── impl/ # 服务实现 │ ├── store/ # 研发商店相关 │ │ ├── resources/ # 商店 API 实现 │ │ └── service/ # 商店归档服务 │ └── util/ # 工具类 │ ├── model-artifactory/ # 数据模型层(JOOQ 生成) └── boot-artifactory/ # Spring Boot 启动模块 ``` ### 1.2 存储后端类型 | 类型 | 说明 | 实现类 | |------|------|--------| | **BkRepo** | 蓝鲸制品库(推荐) | `BkRepoArchiveFileServiceImpl` | | **Disk** | 本地磁盘存储 | `DiskArchiveFileServiceImpl` | ## 二、核心概念 ### 2.1 制品类型 ```kotlin enum class ArtifactoryType(val type: String) { PIPELINE("PIPELINE"), // 流水线产物 CUSTOM_DIR("CUSTOM_DIR"), // 自定义目录 REPORT("REPORT"), // 报告文件 } ``` ### 2.2 文件类型 ```kotlin enum class FileTypeEnum(val type: String) { BK_ARCHIVE("BK_ARCHIVE"), // 构建归档 BK_CUSTOM("BK_CUSTOM"), // 自定义文件 BK_REPORT("BK_REPORT"), // 报告文件 BK_LOG("BK_LOG"), // 日志文件 BK_PLUGIN_FE("BK_PLUGIN_FE"), // 插件前端 BK_STATIC("BK_STATIC"), // 静态资源 } ``` ### 2.3 文件路径规范 ``` # 流水线产物路径 /{projectId}/{pipelineId}/{buildId}/{fileName} # 自定义目录路径 /{projectId}/custom/{customPath}/{fileName} # 报告文件路径 /{projectId}/report/{pipelineId}/{buildId}/{taskId}/{fileName} ``` ## 三、核心数据库表 ### 3.1 文件信息表 | 表名 | 说明 | 核心字段 | |------|------|----------| | `T_FILE_INFO` | 文件信息主表 | `ID`, `PROJECT_CODE`, `FILE_TYPE`, `FILE_PATH`, `FILE_NAME`, `FILE_SIZE` | | `T_FILE_PROPS_INFO` | 文件元数据表 | `FILE_ID`, `PROPS_KEY`, `PROPS_VALUE` | | `T_TOKEN` | 下载令牌表 | `USER_ID`, `PROJECT_ID`, `PATH`, `TOKEN`, `EXPIRE_TIME` | | `T_FILE_TASK` | 文件任务表 | `TASK_ID`, `FILE_TYPE`, `FILE_PATH`, `STATUS`, `BUILD_ID` | ### 3.2 字段说明 > ⚠️ **重要**: `PROJECT_CODE` / `PROJECT_ID` 都是 `T_PROJECT.english_name` | 字段 | 说明 | |------|------| | `PROJECT_CODE` | 项目标识(= T_PROJECT.english_name) | | `FILE_TYPE` | 文件类型(BK_ARCHIVE/BK_CUSTOM 等) | | `FILE_PATH` | 文件存储路径 | | `ARTIFACTORY_TYPE` | 制品库类型(PIPELINE/CUSTOM_DIR) | ## 四、分层架构 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ 请求入口 │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ API 层 (api-artifactory) │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │BuildFile │ │ServiceArti │ │UserFile │ │UserArtifact │ │ │ │Resource │ │factoryRes │ │Resource │ │oryResource │ │ │ │(构建时上传) │ │(服务间调用) │ │(用户文件) │ │(用户制品) │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │BuildArtifact │ │ServiceBkRepo │ │UserReport │ │ │ │oryResource │ │Resource │ │StorageRes │ │ │ │(构建制品) │ │(BkRepo操作) │ │(报告存储) │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ 业务层 (biz-artifactory) │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ 核心 Service │ │ │ │ ArchiveFileService - 文件归档服务(接口) │ │ │ │ BkRepoArchiveFileServiceImpl - BkRepo 实现 (29KB) │ │ │ │ DiskArchiveFileServiceImpl - 磁盘存储实现 (28KB) │ │ │ │ FileTaskService - 文件任务服务 │ │ │ │ PipelineBuildArtifactoryService - 流水线构建制品服务 │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ 商店归档服务 (store/service/) │ │ │ │ ArchiveAtomService - 插件归档服务 │ │ │ │ ArchiveStorePkgService - 商店包归档服务 │ │ │ │ ArchiveAtomToBkRepoServiceImpl - 插件归档到 BkRepo │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ 消息监听 (mq/) │ │ │ │ PipelineBuildArtifactoryListener - 构建完成后处理制品 │ │ │ └──────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ DAO 层 (biz-artifactory/dao) │ │ FileDao (7.5KB) | FileTaskDao (4.8KB) │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ 数据层 (model-artifactory + MySQL) │ │ 数据库:devops_ci_artifactory(共 4 张表) │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ 存储后端 (BkRepo / 本地磁盘) │ └─────────────────────────────────────────────────────────────────────────┘ ``` ## 五、核心类速查 ### 5.1 API 接口层 | 类名 | 路径前缀 | 职责 | |------|----------|------| | `BuildFileResource` | `/build/files` | 构建时文件上传下载 | | `BuildArtifactoryResource` | `/build/artifactories` | 构建时制品操作 | | `ServiceArtifactoryResource` | `/service/artifactories` | 服务间制品操作 | | `ServiceFileResource` | `/service/files` | 服务间文件操作 | | `UserFileResource` | `/user/files` | 用户文件操作 | | `UserArtifactoryResource` | `/user/artifactories` | 用户制品操作 | | `ServiceArchiveAtomResource` | `/service/archive/atom` | 插件归档 | ### 5.2 Service 层 | 类名 | 文件大小 | 职责 | |------|----------|------| | `BkRepoArchiveFileServiceImpl` | 29KB | BkRepo 文件归档实现 | | `DiskArchiveFileServiceImpl` | 28KB | 磁盘文件归档实现 | | `ArchiveAtomServiceImpl` | 16KB | 插件归档服务 | | `ArchiveStorePkgServiceImpl` | 16KB | 商店包归档服务 | | `FileTaskServiceImpl` | 10KB | 文件任务服务 | | `ArchiveFileService` | 8KB | 文件归档接口 | ### 5.3 DAO 层 | 类名 | 职责 | |------|------| | `FileDao` | 文件信息访问 | | `FileTaskDao` | 文件任务访问 | ## 六、核心流程 ### 6.1 构建产物上传流程 ``` 构建插件上传文件 │ ▼ BuildFileResource.uploadFile() │ ▼ ArchiveFileService.uploadFile() │ ├─► BkRepoArchiveFileServiceImpl.uploadFile() │ └─► 调用 BkRepo API 上传文件 │ └─► DiskArchiveFileServiceImpl.uploadFile() └─► 写入本地磁盘 │ ▼ FileDao.create() │ └─► 记录文件信息到数据库 ``` ### 6.2 构建产物下载流程 ``` 用户/插件请求下载 │ ▼ UserFileResource.downloadFile() / BuildFileResource.downloadFile() │ ▼ ArchiveFileService.downloadFile() │ ├─► 验证权限 │ └─► 检查用户是否有项目权限 │ ├─► 获取文件 │ ├─► BkRepo: 调用 BkRepo API 获取 │ └─► Disk: 从本地磁盘读取 │ └─► 返回文件流 ``` ### 6.3 插件包归档流程 ``` 插件发布时归档 │ ▼ ServiceArchiveAtomResource.archiveAtom() │ ▼ ArchiveAtomService.archiveAtom() │ ├─► 下载插件包 │ └─► 从代码库下载构建产物 │ ├─► 上传到制品库 │ └─► ArchiveAtomToBkRepoServiceImpl.archiveAtom() │ └─► 更新插件环境信息 └─► 记录 PKG_PATH ``` ## 七、与其他模块的关系 ### 7.1 依赖关系 ``` ┌─────────────────────────────────────────────────────────────────┐ │ Artifactory 模块依赖关系 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌───────────────┐ │ │ │ artifactory │ │ │ └───────┬───────┘ │ │ │ │ │ ┌────────────────┼────────────────┐ │ │ ▼ ▼ ▼ │ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ project │ │ auth │ │ BkRepo │ │ │ │ (项目信息) │ │ (权限校验) │ │ (存储后端) │ │ │ └───────────┘ └───────────┘ └───────────┘ │ │ │ │ 被依赖: │ │ - process(流水线归档产物) │ │ - store(插件包归档) │ │ - worker(构建机上传下载) │ └─────────────────────────────────────────────────────────────────┘ ``` ### 7.2 服务间调用示例 ```kotlin // Process 模块获取构建产物列表 // 注意:projectId 是 T_PROJECT.english_name client.get(ServiceArtifactoryResource::class).search( projectId = projectId, // english_name pipelineId = pipelineId, buildId = buildId ) // 获取文件下载 URL client.get(ServiceArtifactoryResource::class).getFileDownloadUrls( projectId = projectId, artifactoryType = ArtifactoryType.PIPELINE, filePath = filePath ) // Worker 上传文件 client.get(BuildFileResource::class).uploadFile( projectId = projectId, pipelineId = pipelineId, buildId = buildId, file = file ) ``` ## 八、BkRepo 集成 ### 8.1 BkRepo 配置 ```yaml # application-artifactory.yml bkrepo: # BkRepo 服务地址 gatewayUrl: http://bkrepo.example.com # 是否启用 BkRepo enabled: true # 仓库名称 repoName: pipeline ``` ### 8.2 BkRepo 工具类 ```kotlin // BkRepoUtils.kt object BkRepoUtils { // 构建 BkRepo 路径 fun buildPath(projectId: String, pipelineId: String, buildId: String, fileName: String): String // 上传文件到 BkRepo fun uploadFile(path: String, file: File): Boolean // 从 BkRepo 下载文件 fun downloadFile(path: String): InputStream } ``` ## 九、开发规范 ### 9.1 新增存储后端 1. 实现 `ArchiveFileService` 接口 2. 创建对应的 `*ArchiveFileServiceImpl` 类 3. 在配置中添加存储后端选择逻辑 4. 实现文件上传、下载、删除等方法 ### 9.2 文件操作示例 ```kotlin // 上传文件 archiveFileService.uploadFile( userId = userId, projectId = projectId, // english_name pipelineId = pipelineId, buildId = buildId, file = file, fileType = FileTypeEnum.BK_ARCHIVE ) // 下载文件 val inputStream = archiveFileService.downloadFile( userId = userId, projectId = projectId, filePath = filePath ) // 查询文件列表 val files = fileDao.listByPath( dslContext = dslContext, projectCode = projectId, filePath = path ) ``` ## 十、常见问题 **Q: 如何切换存储后端?** A: 通过配置 `bkrepo.enabled` 控制,`true` 使用 BkRepo,`false` 使用本地磁盘。 **Q: 构建产物保留多久?** A: 根据项目配置的保留策略,默认跟随构建记录保留时间。 **Q: 如何获取文件下载链接?** A: 调用 `getFileDownloadUrls` 接口获取带 Token 的临时下载链接。 **Q: 大文件上传有限制吗?** A: 有,默认限制在配置文件中设置,可根据需要调整。 --- **版本**: 1.0.0 | **更新日期**: 2025-12-11