pipeline-template-module
25
总安装量
19
周安装量
#15082
全站排名
安装命令
npx skills add https://github.com/tencentblueking/bk-ci --skill pipeline-template-module
Agent 安装分布
claude-code
12
opencode
10
gemini-cli
10
antigravity
8
codex
8
Skill 文档
æµæ°´çº¿æ¨¡æ¿æ¨¡åæ¶ææå
æ¦è¿°
æµæ°´çº¿æ¨¡æ¿ï¼Pipeline Templateï¼æ¯ BK-CI çæ ¸å¿åè½æ¨¡åä¹ä¸ï¼å è®¸ç¨æ·å°æµæ°´çº¿é ç½®æ½è±¡ä¸ºå¯å¤ç¨ç模æ¿ï¼æ¯ææ¨¡æ¿çå建ãçæ¬ç®¡çãå®ä¾åãæéæ§å¶ä»¥åä¸ç åååºçéæã
æ ¸å¿ä»·å¼
- é ç½®å¤ç¨ï¼å°éç¨çæµæ°´çº¿é ç½®æ½è±¡ä¸ºæ¨¡æ¿ï¼é¿å éå¤é ç½®
- æ åå管çï¼éè¿æ¨¡æ¿ç»ä¸ç®¡çæµæ°´çº¿æ åï¼ç¡®ä¿ä¸è´æ§
- çæ¬æ§å¶ï¼æ¯ææ¨¡æ¿çæ¬ç®¡çï¼å¯è¿½æº¯åå²åæ´
- æ¹éæä½ï¼æ¯ææ¹éå®ä¾ååæ´æ°ï¼æé«æç
- ååºéæï¼æ¯ææ¨¡æ¿åå¸å°ç åååºï¼å®ç°è·¨é¡¹ç®å ±äº«
ç³»ç»æ¶æ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â æµæ°´çº¿æ¨¡æ¿æ¨¡å â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ â
â â API æ¥å£å± â â ä¸å¡æå¡å± â â æ°æ®è®¿é®å± â â
â â (V1 + V2) â â (Service) â â (DAO) â â
â ââââââââââ¬âââââââââ ââââââââââ¬âââââââââ ââââââââââ¬âââââââââ â
â â â â â
â â¼ â¼ â¼ â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â æ°æ®åºè¡¨ â â
â â T_TEMPLATE | T_TEMPLATE_PIPELINE | T_PIPELINE_TEMPLATE_INFO â â
â â T_PIPELINE_TEMPLATE_RESOURCE_VERSION | T_TEMPLATE_INSTANCE_* â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ â
â â æéæ§å¶ â â ç åååºéæ â â äºä»¶é©±å¨ â â
â â (RBAC) â â (Store) â â (MQ) â â
â âââââââââââââââââââ âââââââââââââââââââ âââââââââââââââââââ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
ä¸ãçæ¬æ¶æ
ç³»ç»åå¨ä¸¤ä¸ªçæ¬çå®ç°ï¼V2 çæ¬æ¯æ°æ¶æï¼åè½æ´å®åï¼
| çæ¬ | ç¹ç¹ | éç¨åºæ¯ |
|---|---|---|
| V1 | åå§å®ç°ï¼åè½åºç¡ | å ¼å®¹èçæ¬ï¼ç®ååºæ¯ |
| V2 | æ°æ¶æï¼æ¯æè稿ãPACãå®åççæ¬ç®¡ç | æ°åè½å¼åï¼å¤æåºæ¯ |
模æ¿ç±»å
// æä»¶: process/api-process/.../pojo/template/TemplateType.kt
enum class TemplateType(val value: String) {
CUSTOMIZE("customize"), // èªå®ä¹æ¨¡æ¿ - 项ç®å
å建
CONSTRAINT("constraint"), // çº¦ææ¨¡æ¿ - æ¥èªç åååº
PUBLIC("public") // å
Œ
±æ¨¡æ¿ - ç³»ç»çº§å
Œ
±æ¨¡æ¿
}
äºãç®å½ç»æ
2.1 API æ¥å£å±
src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/
âââ api/template/ # V1 çæ¬ API
â âââ UserPTemplateResource.kt # ç¨æ·æ¨¡æ¿æ¥å£
â âââ UserTemplateInstanceResource.kt # 模æ¿å®ä¾åæ¥å£
â âââ UserPipelineTemplateResource.kt # æµæ°´çº¿æ¨¡æ¿æ¥å£
â âââ UserTemplateAtomResource.kt # æ¨¡æ¿æä»¶æ¥å£
â âââ ServicePTemplateResource.kt # æå¡é´è°ç¨æ¥å£
â âââ ServiceTemplateInstanceResource.kt # æå¡é´å®ä¾æ¥å£
â âââ v2/ # V2 çæ¬ API
â âââ UserPipelineTemplateV2Resource.kt # V2 ç¨æ·æ¨¡æ¿æ¥å£
â âââ UserPipelineTemplateInstanceV2Resource.kt # V2 å®ä¾åæ¥å£
â âââ ServicePipelineTemplateV2Resource.kt # V2 æå¡é´æ¥å£
â âââ OpPipelineTemplateResource.kt # V2 è¿è¥ç®¡çæ¥å£
â âââ UserTemplateAtomV2Resource.kt # V2 æä»¶æ£æ¥æ¥å£
âââ api/op/
â âââ OpPipelineTemplateResource.kt # è¿è¥ç®¡çæ¨¡æ¿æ¥å£
âââ api/builds/
â âââ BuildTemplateAcrossResource.kt # è·¨é¡¹ç®æ¨¡æ¿è®¿é®
âââ api/service/
âââ ServiceTemplateAcrossResource.kt # æå¡é´è·¨é¡¹ç®æ¨¡æ¿
2.2 POJO æ°æ®æ¨¡å
src/backend/ci/core/process/api-process/src/main/kotlin/com/tencent/devops/process/pojo/template/
âââ TemplateType.kt # 模æ¿ç±»åæä¸¾
âââ TemplateModel.kt # æ¨¡æ¿æ¨¡å
âââ TemplateModelDetail.kt # æ¨¡æ¿æ¨¡å详æ
âââ TemplateVersion.kt # 模æ¿çæ¬ä¿¡æ¯
âââ TemplateId.kt # 模æ¿ID
âââ TemplateInstanceCreate.kt # å®ä¾å建请æ±
âââ TemplateInstanceUpdate.kt # å®ä¾æ´æ°è¯·æ±
âââ TemplateInstanceParams.kt # å®ä¾åæ°
âââ TemplatePipeline.kt # æ¨¡æ¿æµæ°´çº¿
âââ TemplateWithPermission.kt # 带æéçæ¨¡æ¿
âââ TemplateCompareModel.kt # 模æ¿å¯¹æ¯æ¨¡å
âââ CopyTemplateReq.kt # å¤å¶æ¨¡æ¿è¯·æ±
âââ SaveAsTemplateReq.kt # å¦å为模æ¿è¯·æ±
âââ MarketTemplateRequest.kt # ååºæ¨¡æ¿è¯·æ±
âââ v2/ # V2 çæ¬ POJO
âââ PipelineTemplateInfoV2.kt # V2 模æ¿åºç¡ä¿¡æ¯
âââ PipelineTemplateResource.kt # V2 模æ¿èµæº(çæ¬)
âââ PipelineTemplateDetailsResponse.kt # V2 模æ¿è¯¦æ
ååº
âââ PipelineTemplateVersionInfo.kt # V2 çæ¬ä¿¡æ¯
âââ PipelineTemplateCustomCreateReq.kt # V2 èªå®ä¹å建请æ±
âââ PipelineTemplateCopyCreateReq.kt # V2 å¤å¶å建请æ±
âââ PipelineTemplateMarketCreateReq.kt # V2 ååºå¯¼å
¥è¯·æ±
âââ PipelineTemplateDraftSaveReq.kt # V2 è稿ä¿å请æ±
âââ PipelineTemplateDraftReleaseReq.kt # V2 è稿åå¸è¯·æ±
âââ PipelineTemplateInstancesRequest.kt # V2 æ¹éå®ä¾å请æ±
âââ PipelineTemplateCompareResponse.kt # V2 çæ¬å¯¹æ¯ååº
âââ TemplateInstanceType.kt # å®ä¾ç±»åæä¸¾
2.3 ä¸å¡æå¡å±
src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/service/template/
âââ TemplateFacadeService.kt # V1 æ ¸å¿é¨é¢æå¡ (120KB)
âââ TemplateCommonService.kt # 模æ¿éç¨æå¡
âââ TemplateSettingService.kt # 模æ¿è®¾ç½®æå¡
âââ TemplateAtomService.kt # æ¨¡æ¿æä»¶æå¡
âââ TemplatePACService.kt # æ¨¡æ¿ PAC æå¡
âââ v2/ # V2 çæ¬æå¡
âââ PipelineTemplateFacadeService.kt # V2 æ ¸å¿é¨é¢æå¡ (71KB)
âââ PipelineTemplateInstanceService.kt # V2 å®ä¾åæå¡ (41KB)
âââ PipelineTemplatePersistenceService.kt # V2 æä¹
åæå¡ (38KB)
âââ PipelineTemplateMigrateService.kt # V2 è¿ç§»æå¡ (38KB)
âââ PipelineTemplateGenerator.kt # 模æ¿çæå¨
âââ PipelineTemplateMarketFacadeService.kt # ååºæ¨¡æ¿æå¡
âââ PipelineTemplateInfoService.kt # 模æ¿ä¿¡æ¯æå¡
âââ PipelineTemplateResourceService.kt # 模æ¿èµæºæå¡
âââ PipelineTemplateRelatedService.kt # 模æ¿å
³èæå¡
âââ PipelineTemplateSettingService.kt # V2 模æ¿è®¾ç½®æå¡
âââ PipelineTemplateCommonService.kt # V2 éç¨æå¡
âââ PipelineTemplateAtomService.kt # V2 æä»¶æå¡
âââ PipelineTemplateVersionValidator.kt # çæ¬æ ¡éªå¨
âââ PipelineTemplateModelInitializer.kt # 模ååå§åå¨
âââ PipelineTemplateInstanceListener.kt # å®ä¾åäºä»¶çå¬å¨
âââ version/ # çæ¬ç®¡ç
âââ PipelineTemplateVersionManager.kt # çæ¬ç®¡çå¨
âââ PipelineTemplateVersionCreateContext.kt # çæ¬å建ä¸ä¸æ
âââ PipelineTemplateVersionDeleteContext.kt # çæ¬å é¤ä¸ä¸æ
âââ convert/ # 请æ±è½¬æ¢å¨
â âââ PipelineTemplateCustomCreateReqConverter.kt
â âââ PipelineTemplateCopyCreateReqConverter.kt
â âââ PipelineTemplateMarketCreateReqConverter.kt
â âââ PipelineTemplateDraftSaveReqConverter.kt
â âââ PipelineTemplateDraftReleaseReqConverter.kt
â âââ PipelineTemplateDraftRollbackReqConverter.kt
âââ hander/ # çæ¬å¤çå¨
â âââ PipelineTemplateVersionCreateHandler.kt
â âââ PipelineTemplateDraftSaveHandler.kt
â âââ PipelineTemplateDraftReleaseHandler.kt
â âââ PipelineTemplateReleaseCreateHandler.kt
â âââ PipelineTemplateBranchCreateHandler.kt
â âââ PipelineTemplateVersionDeleteHandler.kt
âââ processor/ # çæ¬åå¤çå¨
âââ PTemplateVersionCreatePostProcessor.kt
âââ PTemplateVersionDeletePostProcessor.kt
âââ PTemplateCompatibilityVersionPostProcessor.kt
âââ PTemplateMarketInstallVersionPostProcessor.kt
âââ PTemplateOperationLogVersionPostProcessor.kt
2.4 æ°æ®è®¿é®å±
src/backend/ci/core/process/biz-base/src/main/kotlin/com/tencent/devops/process/
âââ engine/dao/template/ # V1 çæ¬ DAO
â âââ TemplateDao.kt # æ ¸å¿æ¨¡æ¿ DAO (25KB)
â âââ TemplatePipelineDao.kt # æ¨¡æ¿æµæ°´çº¿ DAO (16KB)
âââ dao/template/ # V2 çæ¬ DAO
âââ PipelineTemplateInfoDao.kt # V2 模æ¿ä¿¡æ¯ DAO (16KB)
âââ PipelineTemplateResourceDao.kt # V2 模æ¿èµæº DAO (23KB)
âââ PipelineTemplateSettingDao.kt # V2 模æ¿è®¾ç½® DAO (13KB)
âââ PipelineTemplateRelatedDao.kt # V2 模æ¿å
³è DAO (15KB)
âââ PipelineTemplateMigrationDao.kt # V2 è¿ç§» DAO
2.5 æéæ§å¶
src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/permission/template/
âââ PipelineTemplatePermissionService.kt # æéæå¡æ¥å£
âââ AbstractPipelineTemplatePermissionService.kt # æ½è±¡å®ç°
âââ RbacPipelineTemplatePermissionService.kt # RBAC æéå®ç°
âââ MockPipelineTemplatePermissionService.kt # Mock å®ç°
âââ config/
âââ PipelineTemplatePermConfiguration.kt # æéé
ç½®
ä¸ãæ°æ®åºè¡¨ç»æ
3.1 V1 çæ¬è¡¨
T_TEMPLATE – 模æ¿ä¿¡æ¯è¡¨
CREATE TABLE IF NOT EXISTS `T_TEMPLATE` (
`VERSION` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'çæ¬å·',
`ID` varchar(32) NOT NULL COMMENT '模æ¿ID',
`TEMPLATE_NAME` varchar(64) NOT NULL COMMENT '模æ¿åç§°',
`PROJECT_ID` varchar(34) NOT NULL COMMENT '项ç®ID',
`VERSION_NAME` varchar(64) NOT NULL COMMENT 'çæ¬åç§°',
`CREATOR` varchar(64) NOT NULL COMMENT 'å建è
',
`CREATED_TIME` datetime(3) DEFAULT NULL COMMENT 'å建æ¶é´',
`TEMPLATE` mediumtext COMMENT '模æ¿å
容(JSON)',
`TYPE` varchar(32) NOT NULL DEFAULT 'CUSTOMIZE' COMMENT '模æ¿ç±»å',
`CATEGORY` varchar(128) DEFAULT NULL COMMENT 'åç±»',
`LOGO_URL` varchar(512) DEFAULT NULL COMMENT 'Logoå°å',
`SRC_TEMPLATE_ID` varchar(32) DEFAULT NULL COMMENT 'æºæ¨¡æ¿ID',
`STORE_FLAG` bit(1) DEFAULT b'0' COMMENT 'æ¯å¦æ¥èªååº',
`WEIGHT` int(11) DEFAULT '0' COMMENT 'æé',
`LATEST_FLAG` bit(1) DEFAULT b'0' COMMENT 'æ¯å¦ææ°çæ¬',
`DRAFT_FLAG` bit(1) DEFAULT b'0' COMMENT 'æ¯å¦è稿',
PRIMARY KEY (`VERSION`),
KEY `IDX_PROJECT_ID` (`PROJECT_ID`),
KEY `IDX_ID` (`ID`),
KEY `IDX_SRC_TEMPLATE_ID` (`SRC_TEMPLATE_ID`)
);
T_TEMPLATE_PIPELINE – æ¨¡æ¿æµæ°´çº¿å ³è表
CREATE TABLE IF NOT EXISTS `T_TEMPLATE_PIPELINE` (
`PIPELINE_ID` varchar(34) NOT NULL COMMENT 'æµæ°´çº¿ID',
`INSTANCE_TYPE` varchar(32) NOT NULL DEFAULT 'CONSTRAINT' COMMENT 'å®ä¾ç±»å',
`ROOT_TEMPLATE_ID` varchar(32) DEFAULT NULL COMMENT 'æ ¹æ¨¡æ¿ID',
`VERSION` bigint(20) NOT NULL COMMENT '模æ¿çæ¬',
`VERSION_NAME` varchar(64) NOT NULL COMMENT 'çæ¬åç§°',
`TEMPLATE_ID` varchar(32) NOT NULL COMMENT '模æ¿ID',
`CREATOR` varchar(64) NOT NULL COMMENT 'å建è
',
`UPDATOR` varchar(64) NOT NULL COMMENT 'æ´æ°è
',
`CREATED_TIME` datetime NOT NULL COMMENT 'å建æ¶é´',
`UPDATED_TIME` datetime NOT NULL COMMENT 'æ´æ°æ¶é´',
`BUILD_NO` text COMMENT 'æå»ºå·ä¿¡æ¯',
`PARAM` mediumtext COMMENT 'åæ°',
`DELETED` bit(1) DEFAULT b'0' COMMENT 'æ¯å¦å é¤',
PRIMARY KEY (`PIPELINE_ID`),
KEY `IDX_TEMPLATE_ID` (`TEMPLATE_ID`),
KEY `IDX_ROOT_TEMPLATE_ID` (`ROOT_TEMPLATE_ID`)
);
3.2 V2 çæ¬è¡¨
T_PIPELINE_TEMPLATE_INFO – 模æ¿åºç¡ä¿¡æ¯è¡¨
CREATE TABLE IF NOT EXISTS `T_PIPELINE_TEMPLATE_INFO` (
`TEMPLATE_ID` varchar(34) NOT NULL COMMENT '模æ¿ID',
`PROJECT_ID` varchar(64) NOT NULL COMMENT '项ç®ID',
`TEMPLATE_NAME` varchar(255) NOT NULL COMMENT '模æ¿åç§°',
`TEMPLATE_TYPE` varchar(32) NOT NULL DEFAULT 'CUSTOMIZE' COMMENT '模æ¿ç±»å',
`CREATOR` varchar(64) NOT NULL COMMENT 'å建è
',
`CREATE_TIME` datetime(3) NOT NULL COMMENT 'å建æ¶é´',
`LATEST_VERSION` bigint(20) DEFAULT NULL COMMENT 'ææ°çæ¬å·',
`RELEASE_VERSION` bigint(20) DEFAULT NULL COMMENT 'åå¸çæ¬å·',
`DRAFT_VERSION` bigint(20) DEFAULT NULL COMMENT 'èç¨¿çæ¬å·',
`DELETE` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦å é¤',
PRIMARY KEY (`TEMPLATE_ID`),
KEY `IDX_PROJECT_ID` (`PROJECT_ID`)
);
T_PIPELINE_TEMPLATE_RESOURCE_VERSION – 模æ¿èµæºçæ¬è¡¨
CREATE TABLE IF NOT EXISTS `T_PIPELINE_TEMPLATE_RESOURCE_VERSION` (
`TEMPLATE_ID` varchar(34) NOT NULL COMMENT '模æ¿ID',
`VERSION` bigint(20) NOT NULL COMMENT 'çæ¬å·',
`VERSION_NAME` varchar(64) NOT NULL COMMENT 'çæ¬åç§°',
`PROJECT_ID` varchar(64) NOT NULL COMMENT '项ç®ID',
`CREATOR` varchar(64) NOT NULL COMMENT 'å建è
',
`CREATE_TIME` datetime(3) NOT NULL COMMENT 'å建æ¶é´',
`MODEL` mediumtext COMMENT '模åå
容(JSON)',
`STATUS` varchar(32) DEFAULT NULL COMMENT 'çæ¬ç¶æ',
`BRANCH_ACTION` varchar(32) DEFAULT NULL COMMENT '忝æä½',
`DESCRIPTION` varchar(1024) DEFAULT NULL COMMENT 'çæ¬æè¿°',
`YAML` mediumtext COMMENT 'YAMLå
容',
`YAML_VERSION` varchar(34) DEFAULT NULL COMMENT 'YAMLçæ¬',
`BASE_VERSION` bigint(20) DEFAULT NULL COMMENT 'åºç¡çæ¬',
`DEBUG_BUILD_ID` varchar(64) DEFAULT NULL COMMENT 'è°è¯æå»ºID',
`REFER_FLAG` bit(1) DEFAULT NULL COMMENT 'å¼ç¨æ å¿',
`REFER_TEMPLATE_ID` varchar(34) DEFAULT NULL COMMENT 'å¼ç¨æ¨¡æ¿ID',
PRIMARY KEY (`TEMPLATE_ID`, `VERSION`),
KEY `IDX_PROJECT_ID` (`PROJECT_ID`)
);
T_TEMPLATE_INSTANCE_BASE – å®ä¾ååºç¡è¡¨
CREATE TABLE IF NOT EXISTS `T_TEMPLATE_INSTANCE_BASE` (
`ID` varchar(32) NOT NULL COMMENT '主é®ID',
`TEMPLATE_ID` varchar(32) DEFAULT NULL COMMENT '模æ¿ID',
`TEMPLATE_VERSION` bigint(20) DEFAULT NULL COMMENT '模æ¿çæ¬',
`USE_TEMPLATE_SETTINGS_FLAG` bit(1) DEFAULT b'1' COMMENT 'ä½¿ç¨æ¨¡æ¿è®¾ç½®',
`PROJECT_ID` varchar(64) NOT NULL COMMENT '项ç®ID',
`TOTAL_ITEM_NUM` int(11) NOT NULL COMMENT 'æ»å®ä¾æ°',
`SUCCESS_ITEM_NUM` int(11) NOT NULL DEFAULT '0' COMMENT 'æåå®ä¾æ°',
`FAIL_ITEM_NUM` int(11) NOT NULL DEFAULT '0' COMMENT '失败å®ä¾æ°',
`STATUS` varchar(32) NOT NULL COMMENT 'ç¶æ',
`CREATOR` varchar(50) NOT NULL COMMENT 'å建è
',
`MODIFIER` varchar(50) NOT NULL COMMENT 'ä¿®æ¹è
',
`UPDATE_TIME` datetime(3) NOT NULL COMMENT 'æ´æ°æ¶é´',
`CREATE_TIME` datetime(3) NOT NULL COMMENT 'å建æ¶é´',
PRIMARY KEY (`ID`),
KEY `IDX_TEMPLATE_ID` (`TEMPLATE_ID`),
KEY `IDX_PROJECT_ID` (`PROJECT_ID`)
);
T_TEMPLATE_INSTANCE_ITEM – å®ä¾å项表
CREATE TABLE IF NOT EXISTS `T_TEMPLATE_INSTANCE_ITEM` (
`ID` varchar(32) NOT NULL COMMENT '主é®ID',
`BASE_ID` varchar(32) NOT NULL COMMENT 'åºç¡ID',
`PIPELINE_ID` varchar(34) DEFAULT NULL COMMENT 'æµæ°´çº¿ID',
`PIPELINE_NAME` varchar(255) NOT NULL COMMENT 'æµæ°´çº¿åç§°',
`BUILD_NO_INFO` varchar(512) DEFAULT NULL COMMENT 'æå»ºå·ä¿¡æ¯',
`STATUS` varchar(32) NOT NULL COMMENT 'ç¶æ',
`PARAM` mediumtext COMMENT 'åæ°',
`CREATE_TIME` datetime(3) NOT NULL COMMENT 'å建æ¶é´',
`UPDATE_TIME` datetime(3) NOT NULL COMMENT 'æ´æ°æ¶é´',
PRIMARY KEY (`ID`),
KEY `IDX_BASE_ID` (`BASE_ID`),
KEY `IDX_PIPELINE_ID` (`PIPELINE_ID`)
);
åãæ ¸å¿åè½å®ç°
4.1 模æ¿å建
V1 çæ¬å建æµç¨
// æä»¶: process/biz-process/.../service/template/TemplateFacadeService.kt
@Service
class TemplateFacadeService {
fun createTemplate(
projectId: String,
userId: String,
template: Model,
templateType: TemplateType = TemplateType.CUSTOMIZE
): String {
// 1. æéæ ¡éª
pipelineTemplatePermissionService.checkPipelineTemplatePermission(
userId = userId,
projectId = projectId,
permission = AuthPermission.CREATE
)
// 2. 模æ¿åç§°æ ¡éª
if (templateDao.countByName(dslContext, projectId, template.name) > 0) {
throw ErrorCodeException(errorCode = ProcessMessageCode.ERROR_TEMPLATE_NAME_IS_EXISTS)
}
// 3. çææ¨¡æ¿ID
val templateId = UUIDUtil.generate()
// 4. ä¿å模æ¿
templateDao.create(
dslContext = dslContext,
templateId = templateId,
projectId = projectId,
templateName = template.name,
versionName = INIT_TEMPLATE_VERSION_NAME,
userId = userId,
template = JsonUtil.toJson(template),
type = templateType.name
)
// 5. 注åæéèµæº
pipelineTemplatePermissionService.createResource(
userId = userId,
projectId = projectId,
templateId = templateId,
templateName = template.name
)
return templateId
}
}
V2 çæ¬å建æµç¨
// æä»¶: process/biz-process/.../service/template/v2/PipelineTemplateFacadeService.kt
@Service
class PipelineTemplateFacadeService {
fun create(
userId: String,
projectId: String,
request: PipelineTemplateCustomCreateReq
): PipelineTemplateCreateResp {
// 1. æéæ ¡éª
pipelineTemplatePermissionService.checkPipelineTemplatePermission(
userId = userId,
projectId = projectId,
permission = AuthPermission.CREATE
)
// 2. è°ç¨çæ¬ç®¡çå¨
val result = pipelineTemplateVersionManager.deployTemplate(
userId = userId,
projectId = projectId,
request = request
)
// 3. 注åæéèµæº
pipelineTemplatePermissionService.createResource(
userId = userId,
projectId = projectId,
templateId = result.templateId,
templateName = request.name
)
return PipelineTemplateCreateResp(
templateId = result.templateId,
version = result.version
)
}
}
4.2 模æ¿å®ä¾å
模æ¿å®ä¾åæ¯å°æ¨¡æ¿è½¬æ¢ä¸ºå ·ä½æµæ°´çº¿çè¿ç¨ï¼
// æä»¶: process/biz-process/.../service/template/v2/PipelineTemplateInstanceService.kt
@Service
class PipelineTemplateInstanceService {
/**
* æ¹éå®ä¾å模æ¿
*/
fun createTemplateInstances(
userId: String,
projectId: String,
templateId: String,
version: Long,
request: PipelineTemplateInstancesRequest
): List<PipelineTemplateInstanceItem> {
// 1. æ ¡éªåå»ºæµæ°´çº¿æé
pipelinePermissionService.validPipelinePermission(
userId = userId,
projectId = projectId,
permission = AuthPermission.CREATE
)
// 2. è·å模æ¿è¯¦æ
val templateDetail = pipelineTemplateFacadeService.getTemplateDetail(
userId = userId,
projectId = projectId,
templateId = templateId,
version = version
)
// 3. éååå»ºæµæ°´çº¿å®ä¾
return request.instances.map { instance ->
createInstance(
userId = userId,
projectId = projectId,
templateDetail = templateDetail,
instance = instance
)
}
}
private fun createInstance(
userId: String,
projectId: String,
templateDetail: PipelineTemplateDetailsResponse,
instance: PipelineTemplateInstanceItem
): PipelineTemplateInstanceItem {
// 1. å并模æ¿åæ°åå®ä¾åæ°
val model = mergeTemplateAndInstanceParams(
templateModel = templateDetail.model,
instanceParams = instance.params
)
// 2. åå»ºæµæ°´çº¿
val pipelineId = pipelineInfoFacadeService.create(
userId = userId,
projectId = projectId,
model = model,
channelCode = ChannelCode.BS
)
// 3. å»ºç«æ¨¡æ¿-æµæ°´çº¿å
³è
templatePipelineDao.create(
dslContext = dslContext,
pipelineId = pipelineId,
templateId = templateDetail.templateId,
version = templateDetail.version,
versionName = templateDetail.versionName,
userId = userId
)
return instance.copy(pipelineId = pipelineId)
}
}
4.3 çæ¬ç®¡ç
V2 çæ¬éç¨çç¥æ¨¡å¼å®ç°çæ¬ç®¡çï¼
// æä»¶: process/biz-process/.../service/template/v2/version/PipelineTemplateVersionManager.kt
@Service
class PipelineTemplateVersionManager(
private val versionReqConverters: List<PipelineTemplateVersionReqConverter>,
private val versionCreateHandlers: List<PipelineTemplateVersionCreateHandler>,
private val pipelineTemplateVersionValidator: PipelineTemplateVersionValidator,
private val versionDeleteHandler: PipelineTemplateVersionDeleteHandler
) {
/**
* é¨ç½²æ¨¡æ¿ï¼å建/æ´æ°çæ¬ï¼
*/
fun deployTemplate(
userId: String,
projectId: String,
templateId: String? = null,
version: Long? = null,
request: PipelineTemplateVersionReq
): DeployTemplateResult {
// 1. 转æ¢è¯·æ±ä¸ºä¸ä¸æ
val context = getConverter(request).convert(
userId = userId,
projectId = projectId,
templateId = templateId,
version = version,
request = request
)
// 2. æ ¡éªçæ¬
pipelineTemplateVersionValidator.validate(context = context)
// 3. è°ç¨å¯¹åºå¤çå¨
return getHandler(context).handle(context = context)
}
/**
* å é¤çæ¬
*/
fun deleteVersion(
userId: String,
projectId: String,
templateId: String,
version: Long?,
versionName: String? = null
) {
val context = PipelineTemplateVersionDeleteContext(
userId = userId,
projectId = projectId,
templateId = templateId,
version = version,
versionAction = PipelineVersionAction.DELETE_VERSION
)
versionDeleteHandler.handle(context = context)
}
private fun getHandler(context: PipelineTemplateVersionCreateContext): PipelineTemplateVersionCreateHandler {
return versionCreateHandlers.find { it.support(context) }
?: throw IllegalArgumentException("Unsupported version event")
}
private fun getConverter(request: PipelineTemplateVersionReq): PipelineTemplateVersionReqConverter {
return versionReqConverters.find { it.support(request) }
?: throw IllegalArgumentException("Unsupported version request")
}
}
çæ¬å¤çå¨ç±»å
| å¤çå¨ | åè½ | 触ååºæ¯ |
|---|---|---|
PipelineTemplateDraftSaveHandler |
ä¿åè稿 | ç¼è¾æ¨¡æ¿åä¿åè稿 |
PipelineTemplateDraftReleaseHandler |
åå¸è稿 | å°è稿åå¸ä¸ºæ£å¼çæ¬ |
PipelineTemplateReleaseCreateHandler |
å建åå¸çæ¬ | ç´æ¥å建æ£å¼çæ¬ |
PipelineTemplateBranchCreateHandler |
åå»ºåæ¯çæ¬ | PAC åºæ¯ä¸çåæ¯çæ¬ |
PipelineTemplateVersionDeleteHandler |
å é¤çæ¬ | å 餿å®çæ¬ |
4.4 æéæ§å¶
// æä»¶: process/biz-process/.../permission/template/PipelineTemplatePermissionService.kt
interface PipelineTemplatePermissionService {
/**
* æ ¡éªæ¨¡æ¿æé
*/
fun checkPipelineTemplatePermission(
userId: String,
projectId: String,
templateId: String? = null,
permission: AuthPermission,
message: String? = null
)
/**
* å建æéèµæº
*/
fun createResource(
userId: String,
projectId: String,
templateId: String,
templateName: String
)
/**
* å 餿éèµæº
*/
fun deleteResource(
projectId: String,
templateId: String
)
/**
* è·åææéçæ¨¡æ¿å表
*/
fun filterTemplates(
userId: String,
projectId: String,
permission: AuthPermission,
templateIds: List<String>
): List<String>
/**
* æ¯å¦å¯ç¨æ¨¡æ¿æé管ç
*/
fun enableTemplatePermissionManage(projectId: String): Boolean
}
RBAC æéå®ç°
// æä»¶: process/biz-process/.../permission/template/RbacPipelineTemplatePermissionService.kt
@Service
class RbacPipelineTemplatePermissionService(
private val client: Client,
private val authPermissionApi: AuthPermissionApi,
private val authResourceApi: AuthResourceApi
) : AbstractPipelineTemplatePermissionService() {
override fun checkPipelineTemplatePermission(
userId: String,
projectId: String,
templateId: String?,
permission: AuthPermission,
message: String?
) {
// è°ç¨æéä¸å¿æ ¡éª
val hasPermission = authPermissionApi.validateUserResourcePermission(
userId = userId,
serviceCode = AuthServiceCode.PIPELINE,
resourceType = AuthResourceType.PIPELINE_TEMPLATE,
projectCode = projectId,
resourceCode = templateId ?: "*",
permission = permission
)
if (!hasPermission) {
throw PermissionForbiddenException(message ?: "æ æ¨¡æ¿æä½æé")
}
}
override fun createResource(
userId: String,
projectId: String,
templateId: String,
templateName: String
) {
authResourceApi.createResource(
userId = userId,
serviceCode = AuthServiceCode.PIPELINE,
resourceType = AuthResourceType.PIPELINE_TEMPLATE,
projectCode = projectId,
resourceCode = templateId,
resourceName = templateName
)
}
}
äºãPAC (Pipeline as Code) 模æ¿
5.1 PAC æ¦è¿°
PACï¼Pipeline as Codeï¼æ¯ BK-CI çæ ¸å¿ç¹æ§ï¼å è®¸ç¨æ·éè¿ YAML æä»¶å®ä¹åç®¡çæµæ°´çº¿æ¨¡æ¿ãæ¨¡æ¿ PAC æ¯æï¼
- YAML å®ä¹æ¨¡æ¿ï¼ä½¿ç¨ YAML æ ¼å¼å®ä¹æ¨¡æ¿é ç½®
- Git ä»åºæç®¡ï¼æ¨¡æ¿ YAML æä»¶åå¨å¨ Git ä»åºä¸
- Webhook èªå¨åæ¥ï¼ä»£ç æ¨éèªå¨è§¦åæ¨¡æ¿æ´æ°
- åæ¯çæ¬ç®¡çï¼æ¯æåºäº Git 忝ççæ¬ç®¡ç
- åå转æ¢ï¼Model â YAML åå转æ¢
5.2 模æ¿ç±»åï¼PAC è§è§ï¼
// æä»¶: common/common-pipeline/.../template/PipelineTemplateType.kt
enum class PipelineTemplateType(val value: String) {
PIPELINE("pipeline"), // 宿´æµæ°´çº¿æ¨¡æ¿
STAGE("stage"), // Stage çº§å«æ¨¡æ¿
JOB("job"), // Job çº§å«æ¨¡æ¿
STEP("step"), // Step çº§å«æ¨¡æ¿
VARIABLE("variable") // å鿍¡æ¿
}
5.3 PAC æ ¸å¿æå¡
5.3.1 TemplatePACServiceï¼V1 PAC æå¡ï¼
// æä»¶: process/biz-process/.../service/template/TemplatePACService.kt
@Service
class TemplatePACService(
private val templateDao: TemplateDao,
private val transferYamlService: PipelineTransferYamlService,
private val templateCommonService: TemplateCommonService
) {
/**
* é¢è§æ¨¡æ¿ï¼è¿å Model + YAML + é«äº®æ è®°ï¼
*/
fun previewTemplate(
userId: String,
projectId: String,
templateId: String,
highlightType: HighlightType?
): TemplatePreviewDetail {
// 1. è·å模æ¿
val template = templateDao.getLatestTemplate(dslContext, projectId, templateId)
val model: Model = objectMapper.readValue(template.template)
// 2. è·å设置
val setting = pipelineRepositoryService.getSetting(projectId, templateId)
// 3. Model 转 YAML
val yaml = transferYamlService.transfer(
userId = userId,
projectId = projectId,
actionType = TransferActionType.FULL_MODEL2YAML,
data = TransferBody(PipelineModelAndSetting(model, setting))
).yamlWithVersion?.yamlStr
// 4. çæé«äº®æ è®°ï¼ç¨äº UI å±ç¤ºï¼
val highlightMarkList = buildHighlightMarks(yaml, highlightType)
return TemplatePreviewDetail(
template = model,
templateYaml = yaml,
setting = setting,
hasPermission = hasPermission,
highlightMarkList = highlightMarkList
)
}
}
5.3.2 PTemplateYamlResourceServiceï¼YAML èµæºæå¡ï¼
// æä»¶: process/biz-process/.../yaml/resource/PTemplateYamlResourceService.kt
@Service
class PTemplateYamlResourceService(
private val pipelineTemplateFacadeService: PipelineTemplateFacadeService,
private val pipelineTemplateInfoService: PipelineTemplateInfoService
) : IPipelineYamlResourceService {
/**
* éè¿ YAML å建模æ¿ï¼Git Webhook 触åï¼
*/
override fun createYamlPipeline(
userId: String,
projectId: String,
yaml: String,
event: PipelineYamlFileEvent
): DeployPipelineResult {
with(event) {
val isDefaultBranch = ref == defaultBranch
val yamlFileName = GitActionCommon.getCiTemplateName(filePath)
// è°ç¨ V2 æå¡å建 YAML 模æ¿
val result = pipelineTemplateFacadeService.createYamlTemplate(
userId = userId,
projectId = projectId,
yaml = yaml,
yamlFileName = yamlFileName,
branchName = ref,
isDefaultBranch = isDefaultBranch,
description = commit!!.commitMsg,
yamlFileInfo = PipelineYamlFileInfo(repoHashId, filePath)
)
return DeployPipelineResult(
pipelineId = result.templateId,
pipelineName = result.templateName,
version = result.version.toInt(),
versionName = result.versionName
)
}
}
/**
* éè¿ YAML æ´æ°æ¨¡æ¿
*/
override fun updateYamlPipeline(
userId: String,
projectId: String,
pipelineId: String,
yaml: String,
event: PipelineYamlFileEvent
): DeployPipelineResult {
// 类似å建é»è¾ï¼è°ç¨ updateYamlTemplate
}
/**
* åæ¯å¤±æ´»ï¼åæ¯å 餿¶è°ç¨ï¼
*/
override fun updateBranchAction(
userId: String,
projectId: String,
pipelineId: String,
branchName: String,
branchVersionAction: BranchVersionAction
) {
pipelineTemplateFacadeService.inactiveBranch(
userId = userId,
projectId = projectId,
templateId = pipelineId,
branch = branchName
)
}
}
5.3.3 PipelineYamlResourceManagerï¼ç»ä¸ç®¡çå¨ï¼
// æä»¶: process/biz-process/.../yaml/resource/PipelineYamlResourceManager.kt
@Service
class PipelineYamlResourceManager(
private val pipelineYamlResourceService: PipelineYamlResourceService,
@Lazy private val pTemplateYamlResourceService: PTemplateYamlResourceService
) {
/**
* æ ¹æ® isTemplate æ å¿éæ©å¯¹åºçæå¡
*/
fun getService(isTemplate: Boolean): IPipelineYamlResourceService {
return if (isTemplate) {
pTemplateYamlResourceService // æ¨¡æ¿ YAML æå¡
} else {
pipelineYamlResourceService // æµæ°´çº¿ YAML æå¡
}
}
fun createYamlPipeline(userId: String, projectId: String, yaml: String, event: PipelineYamlFileEvent) =
getService(event.isTemplate).createYamlPipeline(userId, projectId, yaml, event)
fun updateYamlPipeline(userId: String, projectId: String, pipelineId: String, yaml: String, event: PipelineYamlFileEvent) =
getService(event.isTemplate).updateYamlPipeline(userId, projectId, pipelineId, yaml, event)
}
5.4 YAML Webhook 请æ±å¤ç
5.4.1 PipelineTemplateYamlWebhookReqï¼è¯·æ±å¯¹è±¡ï¼
// æä»¶: process/api-process/.../pojo/template/v2/PipelineTemplateYamlWebhookReq.kt
@Schema(title = "模çyamlæä»¶æ¨é请æ±")
data class PipelineTemplateYamlWebhookReq(
@get:Schema(title = "模æ¿YAML", required = true)
val yaml: String,
@get:Schema(title = "yamlæä»¶å", required = true)
val yamlFileName: String,
@get:Schema(title = "忝å", required = true)
val branchName: String,
@get:Schema(title = "æ¯å¦é»è®¤åæ¯", required = true)
val isDefaultBranch: Boolean,
@get:Schema(title = "æè¿°", required = true)
val description: String? = null,
@get:Schema(title = "yamlæä»¶ä¿¡æ¯", required = true)
val yamlFileInfo: PipelineYamlFileInfo? = null
) : PipelineTemplateVersionReq // ç»§æ¿çæ¬è¯·æ±æ¥å£
5.4.2 PipelineTemplateYamlWebhookReqConverterï¼è¯·æ±è½¬æ¢å¨ï¼
// æä»¶: process/biz-process/.../version/convert/PipelineTemplateYamlWebhookReqConverter.kt
@Service
class PipelineTemplateYamlWebhookReqConverter(
private val pipelineTemplateGenerator: PipelineTemplateGenerator,
private val pipelineTemplateInfoService: PipelineTemplateInfoService
) : PipelineTemplateVersionReqConverter {
override fun support(request: PipelineTemplateVersionReq) =
request is PipelineTemplateYamlWebhookReq
override fun convert(
userId: String,
projectId: String,
templateId: String?,
version: Long?,
request: PipelineTemplateVersionReq
): PipelineTemplateVersionCreateContext {
request as PipelineTemplateYamlWebhookReq
// 1. YAML 转 Model
val transferResult = pipelineTemplateGenerator.transfer(
userId = userId,
projectId = projectId,
storageType = PipelineStorageType.YAML,
yaml = request.yaml
)
// 2. æ ¹æ®æ¯å¦é»è®¤åæ¯å³å®çæ¬ç¶æ
val (status, versionAction) = if (request.isDefaultBranch) {
Pair(VersionStatus.RELEASED, PipelineVersionAction.CREATE_RELEASE)
} else {
Pair(VersionStatus.BRANCH, PipelineVersionAction.CREATE_BRANCH)
}
// 3. 模æ¿åç§°ä¼å
级ï¼setting > model > fileName
val templateName = transferResult.templateSetting.pipelineName
.takeIf { it.isNotBlank() }
?: (transferResult.templateModel as? Model)?.name?.ifBlank { request.yamlFileName }
?: request.yamlFileName
// 4. æå»ºä¸ä¸æ
return PipelineTemplateVersionCreateContext(
userId = userId,
projectId = projectId,
templateId = templateId ?: pipelineTemplateGenerator.generateTemplateId(),
versionAction = versionAction,
newTemplate = templateId == null,
enablePac = true, // æ 记为 PAC 模æ¿
yamlFileInfo = request.yamlFileInfo,
branchName = request.branchName
)
}
}
5.5 Model â YAML 转æ¢
5.5.1 PipelineTemplateGeneratorï¼æ¨¡æ¿çæå¨ï¼
// æä»¶: process/biz-process/.../service/template/v2/PipelineTemplateGenerator.kt
@Service
class PipelineTemplateGenerator(
private val transferService: PipelineTransferYamlService
) {
/**
* åå转æ¢ï¼Model â YAML
*/
fun transfer(
userId: String,
projectId: String,
storageType: PipelineStorageType,
templateType: PipelineTemplateType?,
templateModel: ITemplateModel?,
templateSetting: PipelineSetting?,
params: List<BuildFormProperty>?,
yaml: String?,
fallbackOnError: Boolean = false
): PTemplateModelTransferResult {
return if (storageType == PipelineStorageType.YAML) {
// YAML â Model
transferYamlToModel(userId, projectId, templateType, params, yaml)
} else {
// Model â YAML
transferModelToYamlWithFallback(
userId, projectId, templateType,
templateModel, templateSetting, params, fallbackOnError
)
}
}
/**
* YAML â Model 转æ¢
*/
private fun transferYamlToModel(...): PTemplateModelTransferResult {
val transferResult = transferService.transfer(
userId = userId,
projectId = projectId,
actionType = TransferActionType.TEMPLATE_YAML2MODEL_PIPELINE,
data = TransferBody(oldYaml = yaml)
)
return PTemplateModelTransferResult(
templateType = templateType ?: PipelineTemplateType.PIPELINE,
templateModel = transferResult.templateModelAndSetting?.templateModel,
templateSetting = transferResult.templateModelAndSetting?.setting,
yamlWithVersion = transferResult.yamlWithVersion
)
}
/**
* Model â YAML 转æ¢ï¼å¸¦å¼å¸¸å
åºï¼
*/
private fun transferModelToYamlWithFallback(...): PTemplateModelTransferResult {
val actionType = getTransferActionType(templateType)
// TransferActionType æ ¹æ®æ¨¡æ¿ç±»åéæ©ï¼
// PIPELINE â TEMPLATE_MODEL2YAML_PIPELINE
// STAGE â TEMPLATE_MODEL2YAML_STAGE
// JOB â TEMPLATE_MODEL2YAML_JOB
// STEP â TEMPLATE_MODEL2YAML_STEP
return try {
val result = transferService.transfer(
actionType = actionType,
data = TransferBody(
templateModelAndSetting = TemplateModelAndSetting(templateModel, templateSetting)
)
)
PTemplateModelTransferResult(yamlWithVersion = result.yamlWithVersion, ...)
} catch (ex: Exception) {
if (fallbackOnError) {
// å
åºï¼è¿ååå§ Modelï¼YAML 为空
PTemplateModelTransferResult(yamlWithVersion = null, ...)
} else {
throw ex
}
}
}
}
5.5.2 TransferActionTypeï¼è½¬æ¢å¨ä½ç±»åï¼
// 转æ¢å¨ä½ç±»åæä¸¾
enum class TransferActionType {
// æ¨¡æ¿ YAML â Model
TEMPLATE_YAML2MODEL_PIPELINE,
// æ¨¡æ¿ Model â YAMLï¼ææ¨¡æ¿ç±»åï¼
TEMPLATE_MODEL2YAML_PIPELINE,
TEMPLATE_MODEL2YAML_STAGE,
TEMPLATE_MODEL2YAML_JOB,
TEMPLATE_MODEL2YAML_STEP,
// 宿´è½¬æ¢ï¼å
å«è®¾ç½®ï¼
FULL_MODEL2YAML,
FULL_YAML2MODEL
}
5.6 PAC çæ¬ç¶æ
// çæ¬ç¶ææä¸¾
enum class VersionStatus {
COMMITTING, // èç¨¿ç¶æ
RELEASED, // å·²åå¸ï¼é»è®¤åæ¯ï¼
BRANCH // åæ¯çæ¬ï¼éé»è®¤åæ¯ï¼
}
| ç¶æ | 触ååºæ¯ | 说æ |
|---|---|---|
RELEASED |
æ¨éå°é»è®¤åæ¯ | æ£å¼åå¸çæ¬ |
BRANCH |
æ¨éå°éé»è®¤åæ¯ | åæ¯çæ¬ï¼å¯ç¨äºæµè¯ |
COMMITTING |
UI ä¿åè稿 | èç¨¿ç¶æï¼æªåå¸ |
5.7 PAC çæ¬çæ
// æä»¶: PipelineTemplateGenerator.kt
/**
* çæåæ¯çæ¬
*/
fun generateBranchVersion(
projectId: String,
templateId: String,
branchName: String
): PTemplateResourceOnlyVersion {
val latestResource = pipelineTemplateResourceService.getLatestVersionResource(projectId, templateId)
// 妿已åå¨åååæ¯çæ¬ï¼åºäºåæ¯çæ¬å建
val branchResource = pipelineTemplateResourceService.getLatestBranchResource(
projectId, templateId, branchName
)
return PTemplateResourceOnlyVersion(
version = generateTemplateVersion(),
number = latestResource.number + 1,
versionName = branchName, // åæ¯çæ¬å = 忝å
baseVersion = branchResource?.version ?: latestResource.version
)
}
/**
* è稿å叿¶ç PAC çæ¬çæ
*/
fun generateDraftReleaseVersionWithPac(
projectId: String,
templateId: String,
draftResource: PipelineTemplateResource,
repoHashId: String,
targetAction: CodeTargetAction?,
targetBranch: String?
): Pair<VersionStatus, PTemplateResourceOnlyVersion> {
return when (targetAction) {
// ç´æ¥æäº¤å°ä¸»åæ¯ â åå¸çæ¬
CodeTargetAction.COMMIT_TO_MASTER -> {
Pair(VersionStatus.RELEASED, generateReleaseVersion(...))
}
// æäº¤å°æºåæ¯ â åæ¯çæ¬
CodeTargetAction.COMMIT_TO_SOURCE_BRANCH -> {
Pair(VersionStatus.BRANCH, ...)
}
// æ°å»ºåæ¯å¹¶æäº¤ â åæ¯çæ¬
CodeTargetAction.CHECKOUT_BRANCH_AND_REQUEST_MERGE -> {
val versionName = "bk-ci-template-$templateId-${draftResource.number}"
Pair(VersionStatus.BRANCH, ...)
}
// æäº¤å°æå®åæ¯
CodeTargetAction.COMMIT_TO_BRANCH -> {
// 妿æ¯é»è®¤åæ¯ â åå¸çæ¬
// å¦å â åæ¯çæ¬
}
}
}
5.8 PAC ç®å½ç»æ
src/backend/ci/core/process/biz-process/src/main/kotlin/com/tencent/devops/process/
âââ yaml/
â âââ resource/
â â âââ IPipelineYamlResourceService.kt # YAML èµæºæå¡æ¥å£
â â âââ PipelineYamlResourceService.kt # æµæ°´çº¿ YAML æå¡
â â âââ PTemplateYamlResourceService.kt # æ¨¡æ¿ YAML æå¡
â â âââ PipelineYamlResourceManager.kt # ç»ä¸ç®¡çå¨
â âââ mq/
â â âââ PipelineYamlFileEvent.kt # YAML æä»¶äºä»¶
â âââ PipelineYamlFileManager.kt # YAML æä»¶ç®¡ç
â âââ PipelineYamlFacadeService.kt # YAML é¨é¢æå¡
â âââ PipelineYamlSyncService.kt # YAML 忥æå¡
âââ service/template/
â âââ TemplatePACService.kt # V1 PAC æå¡
â âââ v2/
â âââ PipelineTemplateGenerator.kt # 模æ¿çæå¨ï¼å«è½¬æ¢ï¼
â âââ version/convert/
â âââ PipelineTemplateYamlWebhookReqConverter.kt # Webhook 转æ¢å¨
âââ common/common-pipeline-yaml/ # YAML è§£æå
Œ
±åº
âââ src/main/kotlin/.../yaml/
âââ v2/parsers/template/
â âââ TemplateYamlMapper.kt # YAML æ å°
â âââ TemplateYamlUtil.kt # YAML å·¥å
·
âââ v3/parsers/template/
âââ TemplateYamlMapper.kt
âââ TemplateYamlUtil.kt
5.9 PAC 宿´æµç¨
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â PAC 模æ¿å建/æ´æ°æµç¨ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â â
â âââââââââââââââ ââââââââââââââââââââ âââââââââââââââââââââââââââ â
â â Git Push âââââ¶â Webhook Event âââââ¶â PipelineYamlFileEvent â â
â â (YAMLæä»¶) â â (代ç ä»åºè§¦å) â â (isTemplate=true) â â
â âââââââââââââââ ââââââââââââââââââââ âââââââââââââ¬ââââââââââââââ â
â â â
â â¼ â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â PipelineYamlResourceManager â â
â â (æ ¹æ® isTemplate è·¯ç±) â â
â âââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââââââ â
â â â
â â¼ â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â PTemplateYamlResourceService â â
â â (æ¨¡æ¿ YAML èµæºæå¡) â â
â âââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââââââ â
â â â
â â¼ â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â PipelineTemplateFacadeService.createYamlTemplate() â â
â â æå»º PipelineTemplateYamlWebhookReq â â
â âââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââââââ â
â â â
â â¼ â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â PipelineTemplateVersionManager â â
â â deployTemplate() â â
â âââââââââââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââââââ â
â â â
â ââââââââââââââââââââââââââ¼âââââââââââââââââââââââââ â
â â¼ â¼ â¼ â
â âââââââââââââââ ââââââââââââââââââââââ âââââââââââââââââââââ â
â â Converter âââââ¶â Validator âââââ¶â Handler â â
â â (YAMLâModel)â â (æ ¡éªæ¨¡æ¿) â â (å建/æ´æ°çæ¬) â â
â âââââââââââââââ ââââââââââââââââââââââ âââââââââââ¬ââââââââââ â
â â â
â âââââââââââââââââââââââââââââââââââââââââââââââââ â
â â â
â â¼ â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â é»è®¤åæ¯ï¼ â â
â â âââ YES â VersionStatus.RELEASED â æ£å¼çæ¬ â â
â â âââ NO â VersionStatus.BRANCH â åæ¯çæ¬ â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
5.10 PAC æä½³å®è·µ
5.10.1 æ¨¡æ¿ YAML æä»¶å½å
- æä»¶è·¯å¾ï¼
.ci/templates/xxx.ymlæ.ci/templates/xxx.yaml - 模æ¿åç§°é»è®¤ä» YAML ä¸ç
nameåæ®µè·åï¼è¥æ åä½¿ç¨æä»¶å
5.10.2 忝çç¥
| åæ¯ç±»å | çæ¬ç¶æ | 使ç¨åºæ¯ |
|---|---|---|
| é»è®¤åæ¯ï¼main/masterï¼ | RELEASED |
æ£å¼åå¸ï¼å¯è¢«å®ä¾å |
| ç¹æ§åæ¯ | BRANCH |
å¼åæµè¯ï¼ä¸å½±åæ£å¼çæ¬ |
| PR 忝 | BRANCH |
代ç 审æ¥ï¼åå¹¶åèªå¨åå¸ |
5.10.3 enablePac æ å¿
// 模æ¿ä¿¡æ¯ä¸ç PAC æ å¿
data class PipelineTemplateInfoV2(
val id: String,
val projectId: String,
val name: String,
val enablePac: Boolean = false, // æ¯å¦å¯ç¨ PAC
// ...
)
enablePac = trueï¼æ¨¡æ¿ç± YAML æä»¶ç®¡çï¼UI ç¼è¾ä¼åæ¥å°ä»£ç ä»åºenablePac = falseï¼ä¼ ç»æ¨¡æ¿ï¼ä» å¨ BK-CI å 管ç
å ãç åååºéæ
6.1 Store æ¨¡åæ¨¡æ¿æå¡
src/backend/ci/core/store/biz-store/src/main/kotlin/com/tencent/devops/store/template/
âââ service/
â âââ MarketTemplateService.kt # ååºæ¨¡æ¿æå¡æ¥å£
â âââ MarketTemplateServiceImpl.kt # ååºæ¨¡æ¿æå¡å®ç°
â âââ TemplateReleaseService.kt # 模æ¿å叿塿¥å£
â âââ TemplateReleaseServiceImpl.kt # 模æ¿å叿å¡å®ç°
â âââ OpTemplateService.kt # è¿è¥æ¨¡æ¿æå¡æ¥å£
â âââ OpTemplateServiceImpl.kt # è¿è¥æ¨¡æ¿æå¡å®ç°
âââ dao/
âââ MarketTemplateDao.kt # ååºæ¨¡æ¿ DAO
âââ TemplateCategoryRelDao.kt # 模æ¿åç±»å
³è DAO
âââ TemplateLabelRelDao.kt # æ¨¡æ¿æ ç¾å
³è DAO
6.2 ååºæ¨¡æ¿æ°æ®åºè¡¨
-- Store 模åçæ¨¡æ¿è¡¨
CREATE TABLE IF NOT EXISTS `T_TEMPLATE` (
`ID` varchar(32) NOT NULL COMMENT '主é®ID',
`TEMPLATE_NAME` varchar(200) NOT NULL COMMENT '模æ¿åç§°',
`TEMPLATE_CODE` varchar(64) NOT NULL COMMENT '模æ¿ä»£ç ',
`CLASSIFY_ID` varchar(32) NOT NULL COMMENT 'åç±»ID',
`VERSION` varchar(20) NOT NULL COMMENT 'çæ¬å·',
`TEMPLATE_TYPE` tinyint(4) NOT NULL DEFAULT '1' COMMENT '模æ¿ç±»å',
`TEMPLATE_STATUS` tinyint(4) NOT NULL COMMENT '模æ¿ç¶æ',
`TEMPLATE_STATUS_MSG` varchar(1024) DEFAULT NULL COMMENT 'ç¶æä¿¡æ¯',
`LOGO_URL` varchar(256) DEFAULT NULL COMMENT 'Logoå°å',
`SUMMARY` varchar(256) DEFAULT NULL COMMENT 'ç®ä»',
`DESCRIPTION` text COMMENT 'æè¿°',
`PUBLISHER` varchar(50) NOT NULL COMMENT 'åå¸è
',
`PUB_DESCRIPTION` text COMMENT 'åå¸æè¿°',
`PUBLIC_FLAG` bit(1) NOT NULL DEFAULT b'0' COMMENT 'æ¯å¦å
¬å¼',
`LATEST_FLAG` bit(1) NOT NULL COMMENT 'æ¯å¦ææ°',
`CREATOR` varchar(50) NOT NULL COMMENT 'å建è
',
`MODIFIER` varchar(50) NOT NULL COMMENT 'ä¿®æ¹è
',
`CREATE_TIME` datetime NOT NULL COMMENT 'å建æ¶é´',
`UPDATE_TIME` datetime NOT NULL COMMENT 'æ´æ°æ¶é´',
PRIMARY KEY (`ID`),
UNIQUE KEY `UNI_TEMPLATE_CODE_VERSION` (`TEMPLATE_CODE`, `VERSION`)
);
6.3 模æ¿å®è£ æµç¨
// ä»ååºå®è£
模æ¿å°é¡¹ç®
fun installTemplateFromStore(
userId: String,
projectId: String,
templateCode: String,
version: String
): String {
// 1. è·åååºæ¨¡æ¿ä¿¡æ¯
val storeTemplate = marketTemplateService.getTemplateByCode(templateCode, version)
// 2. è·åæ¨¡æ¿æ¨¡å
val templateModel = storeTemplate.templateModel
// 3. åå»ºé¡¹ç®æ¨¡æ¿ï¼ç±»å为 CONSTRAINTï¼
val templateId = templateFacadeService.createTemplate(
projectId = projectId,
userId = userId,
template = templateModel,
templateType = TemplateType.CONSTRAINT
)
// 4. è®°å½å®è£
åå²
templateVersionInstallHistoryDao.create(
projectId = projectId,
templateId = templateId,
templateCode = templateCode,
version = version,
userId = userId
)
return templateId
}
ä¸ãäºä»¶é©±å¨æºå¶
7.1 模æ¿ç¸å ³äºä»¶
// æä»¶: process/biz-base/.../engine/pojo/event/
// 模æ¿å®ä¾åäºä»¶
data class PipelineTemplateInstanceEvent(
val source: String,
val projectId: String,
val templateId: String,
val version: Long,
val instanceBaseId: String,
val userId: String
) : IEvent
// 模æ¿è¿ç§»äºä»¶
data class PipelineTemplateMigrateEvent(
val source: String,
val projectId: String,
val templateId: String,
val userId: String
) : IEvent
// 模æ¿è§¦åå¨å级äºä»¶
data class PipelineTemplateTriggerUpgradesEvent(
val source: String,
val projectId: String,
val templateId: String,
val version: Long,
val userId: String
) : IEvent
7.2 äºä»¶çå¬å¨
// æä»¶: process/biz-process/.../service/template/v2/PipelineTemplateInstanceListener.kt
@Service
class PipelineTemplateInstanceListener(
private val pipelineTemplateInstanceService: PipelineTemplateInstanceService
) {
@StreamListener(PipelineTemplateInstanceEvent.TOPIC)
fun onTemplateInstance(event: PipelineTemplateInstanceEvent) {
// å¤ç弿¥æ¹éå®ä¾å
pipelineTemplateInstanceService.processAsyncInstance(
projectId = event.projectId,
templateId = event.templateId,
version = event.version,
instanceBaseId = event.instanceBaseId,
userId = event.userId
)
}
}
å «ãåå¸å¼é
8.1 模æ¿ç¸å ³é
// æä»¶: process/biz-base/.../engine/control/lock/
// å®ä¾è®¡æ°é - 鲿¢å¹¶åå®ä¾åæ¶è®¡æ°é误
class PipelineTemplateInstanceCountLock(
private val redisOperation: RedisOperation,
private val templateId: String
) : BaseLock(redisOperation, "template:instance:count:$templateId")
// 触åå¨å级é - 鲿¢å¹¶åå级触åå¨
class PipelineTemplateTriggerUpgradesLock(
private val redisOperation: RedisOperation,
private val templateId: String
) : BaseLock(redisOperation, "template:trigger:upgrade:$templateId")
// æä»¶: process/biz-process/.../service/template/v2/
// V2 å®ä¾åé
class PipelineTemplateInstanceLock(
private val redisOperation: RedisOperation,
private val templateId: String,
private val pipelineId: String
) : BaseLock(redisOperation, "template:v2:instance:$templateId:$pipelineId")
// V2 模åé
class PipelineTemplateModelLock(
private val redisOperation: RedisOperation,
private val templateId: String
) : BaseLock(redisOperation, "template:v2:model:$templateId")
ä¹ãOpenAPI æ¥å£
9.1 API ç½å ³æ¥å£
src/backend/ci/core/openapi/api-openapi/src/main/kotlin/com/tencent/devops/openapi/api/apigw/
âââ v3/
â âââ ApigwTemplateResourceV3.kt # V3 æ¨¡æ¿æ¥å£
â âââ ApigwTemplateInstanceResourceV3.kt # V3 å®ä¾åæ¥å£
â âââ ApigwMarketTemplateResourceV3.kt # V3 ååºæ¨¡æ¿æ¥å£
âââ v4/
âââ ApigwTemplateResourceV4.kt # V4 æ¨¡æ¿æ¥å£
âââ ApigwTemplateInstanceResourceV4.kt # V4 å®ä¾åæ¥å£
âââ ApigwMarketTemplateResourceV4.kt # V4 ååºæ¨¡æ¿æ¥å£
9.2 ä¸»è¦ API 端ç¹
| æ¹æ³ | è·¯å¾ | 说æ |
|---|---|---|
| POST | /v4/projects/{projectId}/templates |
åå»ºæ¨¡æ¿ |
| GET | /v4/projects/{projectId}/templates |
è·å模æ¿å表 |
| GET | /v4/projects/{projectId}/templates/{templateId} |
è·å模æ¿è¯¦æ |
| PUT | /v4/projects/{projectId}/templates/{templateId} |
æ´æ°æ¨¡æ¿ |
| DELETE | /v4/projects/{projectId}/templates/{templateId} |
å 餿¨¡æ¿ |
| POST | /v4/projects/{projectId}/templates/{templateId}/instances |
å®ä¾åæ¨¡æ¿ |
| GET | /v4/projects/{projectId}/templates/{templateId}/instances |
è·åå®ä¾å表 |
| GET | /v4/projects/{projectId}/templates/{templateId}/versions |
è·åçæ¬å表 |
åãæä½³å®è·µ
10.1 æ°å¢æ¨¡æ¿åè½
- API å±ï¼å¨
api/template/v2/ä¸å®ä¹æ¥å£ - POJO å±ï¼å¨
pojo/template/v2/ä¸å®ä¹è¯·æ±/ååºå¯¹è±¡ - Service å±ï¼å¨
service/template/v2/ä¸å®ç°ä¸å¡é»è¾ - DAO å±ï¼å¨
dao/template/ä¸å®ç°æ°æ®è®¿é® - æéæ§å¶ï¼è°ç¨
PipelineTemplatePermissionServiceè¿è¡æéæ ¡éª
10.2 çæ¬ç®¡çæ©å±
å¦éæ°å¢çæ¬æä½ç±»åï¼
- å¨
PipelineVersionActionæä¸¾ä¸æ·»å æ°æä½ - å®ç°
PipelineTemplateVersionReqConverter转æ¢å¨ - å®ç°
PipelineTemplateVersionCreateHandlerå¤çå¨ - å¯éï¼å®ç°
PTemplateVersionPostProcessoråå¤çå¨
10.3 ååºéææ©å±
- å¨ Store 模åç
template/service/ä¸å®ç°æå¡ - è°ç¨ Process 模åçæ¨¡æ¿æå¡è¿è¡æ¨¡æ¿æä½
- ç»´æ¤ååºç¹æçå æ°æ®ï¼åç±»ãæ ç¾ãè¯è®ºçï¼
åä¸ã常è§é®é¢
Q1: V1 å V2 çæ¬å¦ä½éæ©ï¼
- æ°åè½å¼åä¼å ä½¿ç¨ V2 çæ¬
- V1 çæ¬ç¨äºå ¼å®¹èæ°æ®åç®ååºæ¯
- V2 çæ¬æ¯æè稿ãPACãå®åççæ¬ç®¡ç
Q2: 模æ¿å®ä¾å失败å¦ä½ææ¥ï¼
- æ£æ¥æ¨¡æ¿æ¯å¦åå¨ä¸çæ¬æ£ç¡®
- æ£æ¥ç¨æ·æ¯å¦æåå»ºæµæ°´çº¿æé
- æ£æ¥æ¨¡æ¿åæ°æ¯å¦å®æ´
- æ¥ç
T_TEMPLATE_INSTANCE_ITEM表ä¸çé误信æ¯
Q3: å¦ä½å®ç°æ¨¡æ¿çæ¹éæ´æ°ï¼
使ç¨å¼æ¥å®ä¾åæ¥å£ï¼
- è°ç¨
createAsyncTemplateInstancesåå»ºå¼æ¥ä»»å¡ - ç³»ç»éè¿ MQ äºä»¶å¼æ¥å¤çæ¯ä¸ªå®ä¾
- éè¿
getTemplateInstanceStatusæ¥è¯¢è¿åº¦
Q4: æ¨¡æ¿æéå¦ä½é ç½®ï¼
- 项ç®çº§å«å¼å
³ï¼
enableTemplatePermissionManage - æéç±»åï¼CREATEãEDITãDELETEãLIST
- ä¸è鲸æéä¸å¿éæï¼æ¯æ RBAC 模å
Q5: PAC 模æ¿åæ®éæ¨¡æ¿æä»ä¹åºå«ï¼
| ç¹æ§ | PAC æ¨¡æ¿ | æ®éæ¨¡æ¿ |
|---|---|---|
| å卿¹å¼ | Git ä»åº YAML æä»¶ | BK-CI æ°æ®åº |
| ç¼è¾æ¹å¼ | 代ç ç¼è¾å¨ / IDE | BK-CI UI |
| çæ¬ç®¡ç | Git 忝 | BK-CI çæ¬å· |
| 忥æºå¶ | Webhook èªå¨åæ¥ | æå¨ä¿å |
| å使¹å¼ | Git 工使µï¼PR/MRï¼ | BK-CI æéæ§å¶ |
| åæ»æ¹å¼ | Git revert | BK-CI çæ¬åæ» |
Q6: PAC 模æ¿ç YAML 转æ¢å¤±è´¥æä¹åï¼
- æ£æ¥ YAML è¯æ³æ¯å¦æ£ç¡®
- 确认使ç¨çæ¯æ¯æç YAML çæ¬ï¼v2/v3ï¼
- æ¥ç
PipelineTemplateGenerator.transfer()çå¼å¸¸æ¥å¿ - 使ç¨
fallbackOnError=trueå¯ä»¥å¨è½¬æ¢å¤±è´¥æ¶è¿ååå§ Model
Q7: å¦ä½å¯ç¨æ¨¡æ¿ç PAC åè½ï¼
- å¨ä»£ç ä»åºä¸å建
.ci/templates/xxx.ymlæä»¶ - é ç½® Webhook 触åå¨
- æ¨é代ç åèªå¨å建/æ´æ°æ¨¡æ¿
- 模æ¿ç
enablePacæ å¿ä¼èªå¨è®¾ä¸ºtrue
Q8: åæ¯çæ¬åæ£å¼çæ¬çå ³ç³»ï¼
- æ¨éå°é»è®¤åæ¯ï¼main/masterï¼â å建
RELEASEDæ£å¼çæ¬ - æ¨éå°å
¶ä»åæ¯ â å建
BRANCHåæ¯çæ¬ - åæ¯çæ¬å¯ç¨äºæµè¯ï¼ä¸å½±åæ£å¼çæ¬
- 忝åå¹¶å°é»è®¤åæ¯åï¼èªå¨åå¸ä¸ºæ£å¼çæ¬
åäºãç¸å ³ Skill
| Skill | 说æ |
|---|---|
yaml-pipeline-transfer |
YAML æµæ°´çº¿è½¬æ¢ï¼çè§£ Model â YAML è½¬æ¢æºå¶ |
pipeline-model-architecture |
æµæ°´çº¿æ¨¡åæ¶æï¼ç解模æ¿ç模åç»æ |
process-module-architecture |
Process æ¨¡åæ¶æï¼çè§£æ¨¡æ¿æå¨æ¨¡å |
auth-module-architecture |
æéæ¨¡åæ¶æï¼çè§£æ¨¡æ¿æéæ§å¶ |
store-module-architecture |
ç åååºæ¶æï¼ç解模æ¿ååºéæ |
microservice-infrastructure |
å¾®æå¡åºç¡è®¾æ½ï¼äºä»¶é©±å¨ï¼ï¼çè§£å¼æ¥å®ä¾åæºå¶ |
common-technical-practices |
éç¨ææ¯å®è·µï¼åå¸å¼éï¼ï¼ç解模æ¿å¹¶åæ§å¶ |