From dea1e5d0c70cc094ab44f3689b0479a065763b41 Mon Sep 17 00:00:00 2001 From: dengqichen Date: Tue, 7 Jan 2025 17:41:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=A7=E5=A3=B0=E9=81=93=E6=92=92=E6=97=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/RepositoryGroupApiController.java | 43 ++++-- .../sync/JenkinsSyncContext.java | 2 +- .../deploy/entity/RepositoryGroup.java | 7 + .../integration/IGitServiceIntegration.java | 47 ++++++ .../integration/impl/GitIntegration.java | 50 ------ .../impl/GitServiceIntegrationImpl.java | 142 ++++++++++++++++++ ...ava => JenkinsServiceIntegrationImpl.java} | 4 +- .../response/GitBranchResponse.java | 37 +++++ .../response/GitGroupResponse.java | 26 ++++ .../response/GitProjectResponse.java | 34 +++++ .../IRepositoryGroupRepository.java | 31 +++- .../service/IRepositoryGroupService.java | 20 ++- .../service/impl/JenkinsBuildServiceImpl.java | 2 +- .../impl/RepositoryGroupServiceImpl.java | 90 ++++++++++- .../db/migration/V1.0.0__init_schema.sql | 2 +- 15 files changed, 465 insertions(+), 72 deletions(-) rename backend/src/main/java/com/qqchen/deploy/backend/deploy/{service => dto}/sync/JenkinsSyncContext.java (90%) create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/IGitServiceIntegration.java delete mode 100644 backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/GitIntegration.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/GitServiceIntegrationImpl.java rename backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/{JenkinsServiceIntegration.java => JenkinsServiceIntegrationImpl.java} (99%) create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitBranchResponse.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitGroupResponse.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitProjectResponse.java diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryGroupApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryGroupApiController.java index 268da625..e69651a2 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryGroupApiController.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryGroupApiController.java @@ -1,28 +1,51 @@ package com.qqchen.deploy.backend.deploy.api; -import com.qqchen.deploy.backend.framework.controller.BaseController; import com.qqchen.deploy.backend.deploy.entity.RepositoryGroup; import com.qqchen.deploy.backend.deploy.dto.RepositoryGroupDTO; import com.qqchen.deploy.backend.deploy.query.RepositoryGroupQuery; +import com.qqchen.deploy.backend.deploy.service.IRepositoryGroupService; +import com.qqchen.deploy.backend.framework.api.Response; +import com.qqchen.deploy.backend.framework.controller.BaseController; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + import java.util.List; /** - * GIT分组 Controller + * Git仓库组Controller */ @Slf4j @RestController @RequestMapping("/api/v1/repo-group") -@Tag(name = "GIT分组管理", description = "GIT分组管理相关接口") +@Tag(name = "Git仓库组管理", description = "Git仓库组管理相关接口") public class RepositoryGroupApiController extends BaseController { - + + @Resource + private IRepositoryGroupService repositoryGroupService; + + @Operation(summary = "同步仓库组") + @PostMapping("/{externalSystemId}/sync") + public Response syncGroups( + @Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId + ) { + return Response.success(repositoryGroupService.syncGroups(externalSystemId)); + } + + @Operation(summary = "获取仓库组数量") + @GetMapping("/{externalSystemId}/count") + public Response countGroups( + @Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId + ) { + return Response.success(repositoryGroupService.countByExternalSystemId(externalSystemId)); + } + @Override protected void exportData(HttpServletResponse response, List data) { - // TODO: 实现导出逻辑 - log.info("导出GIT分组数据,数据量:{}", data.size()); + } -} \ No newline at end of file +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/sync/JenkinsSyncContext.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/dto/sync/JenkinsSyncContext.java similarity index 90% rename from backend/src/main/java/com/qqchen/deploy/backend/deploy/service/sync/JenkinsSyncContext.java rename to backend/src/main/java/com/qqchen/deploy/backend/deploy/dto/sync/JenkinsSyncContext.java index 54a12b63..f0756735 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/sync/JenkinsSyncContext.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/dto/sync/JenkinsSyncContext.java @@ -1,4 +1,4 @@ -package com.qqchen.deploy.backend.deploy.service.sync; +package com.qqchen.deploy.backend.deploy.dto.sync; import com.qqchen.deploy.backend.deploy.dto.JenkinsSyncHistoryDTO; import com.qqchen.deploy.backend.deploy.entity.ExternalSystem; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/entity/RepositoryGroup.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/entity/RepositoryGroup.java index 9adc4fce..4a70af97 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/entity/RepositoryGroup.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/entity/RepositoryGroup.java @@ -42,4 +42,11 @@ public class RepositoryGroup extends Entity { @Column(name = "external_system_id") private Long externalSystemId; + @Column(name = "group_id", nullable = false) + private Long groupId; + + private Integer sort; + + private Boolean enabled = true; + } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/IGitServiceIntegration.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/IGitServiceIntegration.java new file mode 100644 index 00000000..e9df8c19 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/IGitServiceIntegration.java @@ -0,0 +1,47 @@ +package com.qqchen.deploy.backend.deploy.integration; + +import com.qqchen.deploy.backend.deploy.entity.ExternalSystem; +import com.qqchen.deploy.backend.deploy.integration.response.GitBranchResponse; +import com.qqchen.deploy.backend.deploy.integration.response.GitGroupResponse; +import com.qqchen.deploy.backend.deploy.integration.response.GitProjectResponse; +import com.qqchen.deploy.backend.system.enums.ExternalSystemTypeEnum; + +import java.util.List; + +/** + * Git服务集成接口 + * 定义与外部Git系统交互的方法 + */ +public interface IGitServiceIntegration extends IExternalSystemIntegration { + + /** + * 获取所有Git组 + * + * @param system 外部系统配置 + * @return Git组列表 + */ + List groups(ExternalSystem system); + + /** + * 获取指定组下的所有项目 + * + * @param system 外部系统配置 + * @param groupId 组ID + * @return 项目列表 + */ + List projects(ExternalSystem system, Long groupId); + + /** + * 获取指定项目的所有分支 + * + * @param system 外部系统配置 + * @param projectId 项目ID + * @return 分支列表 + */ + List branches(ExternalSystem system, Long projectId); + + @Override + default ExternalSystemTypeEnum getSystemType() { + return ExternalSystemTypeEnum.GIT; + } +} diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/GitIntegration.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/GitIntegration.java deleted file mode 100644 index 3cb48a7c..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/GitIntegration.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.qqchen.deploy.backend.deploy.integration.impl; - -import com.qqchen.deploy.backend.deploy.entity.ExternalSystem; -import com.qqchen.deploy.backend.system.enums.ExternalSystemTypeEnum; -import com.qqchen.deploy.backend.deploy.integration.IExternalSystemIntegration; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.*; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.client.HttpClientErrorException; - -@Slf4j -@Service -public class GitIntegration implements IExternalSystemIntegration { - - private final RestTemplate restTemplate = new RestTemplate(); - - @Override - public boolean testConnection(ExternalSystem system) { - try { - String url = system.getUrl() + "/api/v4/version"; - HttpHeaders headers = new HttpHeaders(); - headers.set("PRIVATE-TOKEN", system.getToken()); - - HttpEntity entity = new HttpEntity<>(headers); - ResponseEntity response = restTemplate.exchange( - url, - HttpMethod.GET, - entity, - String.class - ); - - return response.getStatusCode() == HttpStatus.OK; - } catch (HttpClientErrorException.Unauthorized e) { - log.error("GitLab token authentication failed: {}", system.getUrl()); - return false; - } catch (HttpClientErrorException.NotFound e) { - log.error("GitLab API endpoint not found: {}", system.getUrl()); - return false; - } catch (Exception e) { - log.error("Failed to connect to GitLab: {}", system.getUrl(), e); - return false; - } - } - - @Override - public ExternalSystemTypeEnum getSystemType() { - return ExternalSystemTypeEnum.GIT; - } -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/GitServiceIntegrationImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/GitServiceIntegrationImpl.java new file mode 100644 index 00000000..3e06f9aa --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/GitServiceIntegrationImpl.java @@ -0,0 +1,142 @@ +package com.qqchen.deploy.backend.deploy.integration.impl; + +import com.qqchen.deploy.backend.deploy.entity.ExternalSystem; +import com.qqchen.deploy.backend.deploy.integration.IGitServiceIntegration; +import com.qqchen.deploy.backend.deploy.integration.response.GitBranchResponse; +import com.qqchen.deploy.backend.deploy.integration.response.GitGroupResponse; +import com.qqchen.deploy.backend.deploy.integration.response.GitProjectResponse; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.Base64; +import java.util.Collections; +import java.util.List; + +/** + * Git服务集成实现 + * 主要负责与外部Git系统(如GitLab)的API交互 + */ +@Slf4j +@Service +public class GitServiceIntegrationImpl implements IGitServiceIntegration { + + private final RestTemplate restTemplate = new RestTemplate(); + + @Override + public boolean testConnection(ExternalSystem system) { + try { + String url = system.getUrl() + "/api/v4/version"; + HttpHeaders headers = createHeaders(system); + HttpEntity entity = new HttpEntity<>(headers); + + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.GET, + entity, + String.class + ); + + return response.getStatusCode() == HttpStatus.OK; + } catch (Exception e) { + log.error("Git connection test failed for system: {}", system.getName(), e); + return false; + } + } + + @Override + public List groups(ExternalSystem system) { + try { + String url = String.format("%s/api/v4/groups?per_page=100", system.getUrl()); + HttpHeaders headers = createHeaders(system); + HttpEntity entity = new HttpEntity<>(headers); + + ResponseEntity> response = restTemplate.exchange( + url, + HttpMethod.GET, + entity, + new ParameterizedTypeReference<>() {} + ); + + return response.getBody() != null ? response.getBody() : Collections.emptyList(); + } catch (Exception e) { + log.error("Failed to fetch git groups for system: {}", system.getName(), e); + return Collections.emptyList(); + } + } + + @Override + public List projects(ExternalSystem system, Long groupId) { + try { + String url = String.format("%s/api/v4/groups/%d/projects?per_page=100", system.getUrl(), groupId); + HttpHeaders headers = createHeaders(system); + HttpEntity entity = new HttpEntity<>(headers); + + ResponseEntity> response = restTemplate.exchange( + url, + HttpMethod.GET, + entity, + new ParameterizedTypeReference<>() {} + ); + + return response.getBody() != null ? response.getBody() : Collections.emptyList(); + } catch (Exception e) { + log.error("Failed to fetch git projects for system: {} and group: {}", system.getName(), groupId, e); + return Collections.emptyList(); + } + } + + @Override + public List branches(ExternalSystem system, Long projectId) { + try { + String url = String.format("%s/api/v4/projects/%d/repository/branches", system.getUrl(), projectId); + HttpHeaders headers = createHeaders(system); + HttpEntity entity = new HttpEntity<>(headers); + + ResponseEntity> response = restTemplate.exchange( + url, + HttpMethod.GET, + entity, + new ParameterizedTypeReference<>() {} + ); + + return response.getBody() != null ? response.getBody() : Collections.emptyList(); + } catch (Exception e) { + log.error("Failed to fetch git branches for system: {} and project: {}", system.getName(), projectId, e); + return Collections.emptyList(); + } + } + + /** + * 创建HTTP请求头 + */ + private HttpHeaders createHeaders(ExternalSystem system) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + // 根据认证类型设置认证信息 + switch (system.getAuthType()) { + case BASIC -> { + // Basic认证 + String auth = system.getUsername() + ":" + system.getPassword(); + byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes()); + String authHeader = "Basic " + new String(encodedAuth); + headers.set("Authorization", authHeader); + } + case TOKEN -> { + // Token认证 - GitLab使用Private Token + headers.set("PRIVATE-TOKEN", system.getToken()); + } + case OAUTH -> { + // OAuth认证 + headers.set("Authorization", "Bearer " + system.getToken()); + } + default -> throw new RuntimeException("Unsupported authentication type: " + system.getAuthType()); + } + + return headers; + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/JenkinsServiceIntegration.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/JenkinsServiceIntegrationImpl.java similarity index 99% rename from backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/JenkinsServiceIntegration.java rename to backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/JenkinsServiceIntegrationImpl.java index e190b3ea..b8a6120b 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/JenkinsServiceIntegration.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/impl/JenkinsServiceIntegrationImpl.java @@ -33,12 +33,10 @@ import java.util.Base64; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.ArrayList; -import java.util.stream.Collectors; @Slf4j @Service -public class JenkinsServiceIntegration implements IJenkinsServiceIntegration { +public class JenkinsServiceIntegrationImpl implements IJenkinsServiceIntegration { @Resource private IExternalSystemRepository systemRepository; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitBranchResponse.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitBranchResponse.java new file mode 100644 index 00000000..0c5f99d1 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitBranchResponse.java @@ -0,0 +1,37 @@ +package com.qqchen.deploy.backend.deploy.integration.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * Git分支响应对象 + */ +@Data +public class GitBranchResponse { + + private String name; + + private Boolean merged; + + private Boolean protected_; + + private Boolean developersCanPush; + + private Boolean developersCanMerge; + + private Boolean canPush; + + private Boolean isDefaultBranch; + + private String webUrl; + + // 提交信息 + private String commitId; + + private String commitMessage; + + private String commitAuthor; + + private LocalDateTime commitDate; +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitGroupResponse.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitGroupResponse.java new file mode 100644 index 00000000..dabcb02a --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitGroupResponse.java @@ -0,0 +1,26 @@ +package com.qqchen.deploy.backend.deploy.integration.response; + +import lombok.Data; + +/** + * Git组响应对象 + */ +@Data +public class GitGroupResponse { + + private Long id; + + private String name; + + private String path; + + private String description; + + private String visibility; + + private Long parentId; + + private String webUrl; + + private String avatarUrl; +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitProjectResponse.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitProjectResponse.java new file mode 100644 index 00000000..d1078252 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/integration/response/GitProjectResponse.java @@ -0,0 +1,34 @@ +package com.qqchen.deploy.backend.deploy.integration.response; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * Git项目响应对象 + */ +@Data +public class GitProjectResponse { + + private Long id; + + private String name; + + private String path; + + private String description; + + private String visibility; + + private Long groupId; + + private String defaultBranch; + + private String webUrl; + + private String sshUrl; + + private String httpUrl; + + private LocalDateTime lastActivityAt; +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IRepositoryGroupRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IRepositoryGroupRepository.java index ab1713f7..0982a536 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IRepositoryGroupRepository.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IRepositoryGroupRepository.java @@ -1,12 +1,39 @@ package com.qqchen.deploy.backend.deploy.repository; -import com.qqchen.deploy.backend.framework.repository.IBaseRepository; import com.qqchen.deploy.backend.deploy.entity.RepositoryGroup; +import com.qqchen.deploy.backend.framework.repository.IBaseRepository; import org.springframework.stereotype.Repository; +import java.util.List; + /** - * GIT分组 Repository + * Git仓库组Repository */ @Repository public interface IRepositoryGroupRepository extends IBaseRepository { + + /** + * 根据外部系统ID查找仓库组 + * + * @param externalSystemId 外部系统ID + * @return 仓库组列表 + */ + List findByExternalSystemId(Long externalSystemId); + + /** + * 统计外部系统的仓库组数量 + * + * @param externalSystemId 外部系统ID + * @return 仓库组数量 + */ + Long countByExternalSystemId(Long externalSystemId); + + /** + * 根据外部系统ID和组ID查找仓库组 + * + * @param externalSystemId 外部系统ID + * @param groupId 组ID + * @return 仓库组 + */ + RepositoryGroup findByExternalSystemIdAndGroupId(Long externalSystemId, Long groupId); } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryGroupService.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryGroupService.java index 21a13c67..3a511261 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryGroupService.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryGroupService.java @@ -1,12 +1,28 @@ package com.qqchen.deploy.backend.deploy.service; -import com.qqchen.deploy.backend.framework.service.IBaseService; import com.qqchen.deploy.backend.deploy.entity.RepositoryGroup; import com.qqchen.deploy.backend.deploy.dto.RepositoryGroupDTO; import com.qqchen.deploy.backend.deploy.query.RepositoryGroupQuery; +import com.qqchen.deploy.backend.framework.service.IBaseService; /** - * GIT分组 Service接口 + * Git仓库组服务接口 */ public interface IRepositoryGroupService extends IBaseService { + + /** + * 同步指定外部系统的所有仓库组 + * + * @param externalSystemId 外部系统ID + * @return 同步的仓库组数量 + */ + Integer syncGroups(Long externalSystemId); + + /** + * 统计外部系统的仓库组数量 + * + * @param externalSystemId 外部系统ID + * @return 仓库组数量 + */ + Long countByExternalSystemId(Long externalSystemId); } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/JenkinsBuildServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/JenkinsBuildServiceImpl.java index cf569545..27e27a7f 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/JenkinsBuildServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/JenkinsBuildServiceImpl.java @@ -13,7 +13,7 @@ import com.qqchen.deploy.backend.deploy.integration.IJenkinsServiceIntegration; import com.qqchen.deploy.backend.deploy.repository.*; import com.qqchen.deploy.backend.deploy.service.IJenkinsBuildService; import com.qqchen.deploy.backend.deploy.service.IJenkinsSyncHistoryService; -import com.qqchen.deploy.backend.deploy.service.sync.JenkinsSyncContext; +import com.qqchen.deploy.backend.deploy.dto.sync.JenkinsSyncContext; import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.framework.exception.BusinessException; import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryGroupServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryGroupServiceImpl.java index 5fa33b98..6acb6eb9 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryGroupServiceImpl.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryGroupServiceImpl.java @@ -1,18 +1,104 @@ package com.qqchen.deploy.backend.deploy.service.impl; -import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; +import com.qqchen.deploy.backend.deploy.entity.ExternalSystem; import com.qqchen.deploy.backend.deploy.entity.RepositoryGroup; import com.qqchen.deploy.backend.deploy.dto.RepositoryGroupDTO; +import com.qqchen.deploy.backend.deploy.integration.IGitServiceIntegration; +import com.qqchen.deploy.backend.deploy.integration.response.GitGroupResponse; import com.qqchen.deploy.backend.deploy.query.RepositoryGroupQuery; +import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository; +import com.qqchen.deploy.backend.deploy.repository.IRepositoryGroupRepository; import com.qqchen.deploy.backend.deploy.service.IRepositoryGroupService; +import com.qqchen.deploy.backend.framework.enums.ResponseCode; +import com.qqchen.deploy.backend.framework.exception.BusinessException; +import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; /** - * GIT分组 Service实现 + * Git仓库组服务实现 */ @Slf4j @Service public class RepositoryGroupServiceImpl extends BaseServiceImpl implements IRepositoryGroupService { + + @Resource + private IExternalSystemRepository externalSystemRepository; + + @Resource + private IRepositoryGroupRepository repositoryGroupRepository; + + @Resource + private IGitServiceIntegration gitServiceIntegration; + + @Override + @Transactional + public Integer syncGroups(Long externalSystemId) { + try { + // 1. 获取外部系统信息 + ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId) + .orElseThrow(() -> new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND)); + + // 2. 获取远程仓库组信息 + List remoteGroups = gitServiceIntegration.groups(externalSystem); + if (remoteGroups.isEmpty()) { + log.info("No groups found in remote git system: {}", externalSystem.getName()); + return 0; + } + + // 3. 获取本地已存在的仓库组 + List existingGroups = repositoryGroupRepository.findByExternalSystemId(externalSystemId); + Map existingGroupMap = existingGroups.stream() + .collect(Collectors.toMap(RepositoryGroup::getGroupId, Function.identity())); + + // 4. 更新或创建仓库组 + List groupsToSave = remoteGroups.stream() + .map(remoteGroup -> updateOrCreateGroup(externalSystemId, remoteGroup, existingGroupMap)) + .collect(Collectors.toList()); + + // 5. 保存仓库组 + repositoryGroupRepository.saveAll(groupsToSave); + + log.info("Successfully synchronized {} groups for external system: {}", + groupsToSave.size(), externalSystem.getName()); + return groupsToSave.size(); + } catch (Exception e) { + log.error("Failed to sync repository groups for external system: {}", externalSystemId, e); + throw new BusinessException(ResponseCode.REPOSITORY_SYNC_FAILED); + } + } + + private RepositoryGroup updateOrCreateGroup( + Long externalSystemId, + GitGroupResponse remoteGroup, + Map existingGroupMap) { + + RepositoryGroup group = existingGroupMap.getOrDefault(remoteGroup.getId(), new RepositoryGroup()); + + // 更新基本信息 + group.setExternalSystemId(externalSystemId); + group.setGroupId(remoteGroup.getId()); + group.setName(remoteGroup.getName()); + group.setPath(remoteGroup.getPath()); + group.setDescription(remoteGroup.getDescription()); + group.setVisibility(remoteGroup.getVisibility()); + group.setParentId(remoteGroup.getParentId()); + group.setWebUrl(remoteGroup.getWebUrl()); + group.setAvatarUrl(remoteGroup.getAvatarUrl()); + + return group; + } + + @Override + public Long countByExternalSystemId(Long externalSystemId) { + return repositoryGroupRepository.countByExternalSystemId(externalSystemId); + } } \ No newline at end of file diff --git a/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql b/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql index 29b71892..bcf3e9a2 100644 --- a/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql +++ b/backend/src/main/resources/db/migration/V1.0.0__init_schema.sql @@ -289,9 +289,9 @@ CREATE TABLE deploy_repo_group deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除:0-未删除,1-已删除', -- 业务字段 + group_id BIGINT NOT NULL COMMENT 'Git系统中的组ID', name VARCHAR(100) NOT NULL COMMENT '仓库组名', description VARCHAR(500) NULL COMMENT '仓库组描述', - group_id BIGINT NOT NULL COMMENT '外部系统中的组ID', parent_id BIGINT NULL COMMENT '父级仓库组ID', path VARCHAR(200) NOT NULL COMMENT '仓库组路径', external_system_id BIGINT NOT NULL COMMENT '外部系统ID',