diff --git a/backend/pom.xml b/backend/pom.xml
index 01f25323..09af9f5e 100644
--- a/backend/pom.xml
+++ b/backend/pom.xml
@@ -64,6 +64,18 @@
spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-quartz
+
+
com.mysql
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryBranchApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryBranchApiController.java
index 17dbc5c6..10dd9081 100644
--- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryBranchApiController.java
+++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryBranchApiController.java
@@ -25,6 +25,30 @@ import java.util.List;
@Tag(name = "Git仓库分支管理", description = "Git仓库分支管理相关接口")
public class RepositoryBranchApiController extends BaseController {
+ @Resource
+ private IRepositoryBranchService repositoryBranchService;
+
+ @Operation(summary = "同步Git分支", description = "支持三种同步模式:1)只传externalSystemId-全量同步 2)传externalSystemId+repoGroupId-同步仓库组 3)传externalSystemId+repoGroupId+repoProjectId-同步单个项目")
+ @PostMapping("/sync")
+ public Response sync(
+ @Parameter(description = "外部系统ID", required = true) @RequestParam Long externalSystemId,
+ @Parameter(description = "仓库组ID(可选)", required = false) @RequestParam(required = false) Long repoGroupId,
+ @Parameter(description = "仓库项目ID(可选,传此参数时repoGroupId必传)", required = false) @RequestParam(required = false) Long repoProjectId
+ ) {
+ Integer count;
+ if (repoProjectId != null) {
+ // 同步单个项目
+ count = repositoryBranchService.syncBranches(externalSystemId, repoGroupId, repoProjectId);
+ } else if (repoGroupId != null) {
+ // 同步仓库组
+ count = repositoryBranchService.syncBranches(externalSystemId, repoGroupId);
+ } else {
+ // 全量同步
+ count = repositoryBranchService.syncBranches(externalSystemId);
+ }
+ return Response.success(count);
+ }
+
@Override
protected void exportData(HttpServletResponse response, List data) {
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 3a3ca9e2..b883c468 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
@@ -3,8 +3,13 @@ package com.qqchen.deploy.backend.deploy.api;
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 jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
@@ -20,6 +25,17 @@ import java.util.List;
@Tag(name = "Git仓库组管理", description = "Git仓库组管理相关接口")
public class RepositoryGroupApiController extends BaseController {
+ @Resource
+ private IRepositoryGroupService repositoryGroupService;
+
+ @Operation(summary = "同步Git仓库组", description = "同步指定外部系统的所有仓库组")
+ @PostMapping("/sync")
+ public Response sync(
+ @Parameter(description = "外部系统ID", required = true) @RequestParam Long externalSystemId
+ ) {
+ Integer count = repositoryGroupService.syncGroups(externalSystemId);
+ return Response.success(count);
+ }
@Override
protected void exportData(HttpServletResponse response, List data) {
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryManagerApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryManagerApiController.java
deleted file mode 100644
index dc2b7355..00000000
--- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryManagerApiController.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.qqchen.deploy.backend.deploy.api;
-
-import com.qqchen.deploy.backend.deploy.dto.GitInstanceDTO;
-import com.qqchen.deploy.backend.deploy.service.IRepositoryManagerService;
-import com.qqchen.deploy.backend.framework.api.Response;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import jakarta.annotation.Resource;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.*;
-
-/**
- * Git仓库管理API控制器
- */
-@Slf4j
-@RestController
-@RequestMapping("/api/v1/repository-manager")
-@Tag(name = "Git仓库管理", description = "Git仓库管理相关接口")
-public class RepositoryManagerApiController {
-
- @Resource
- private IRepositoryManagerService repositoryManagerService;
-
- @Operation(summary = "同步Git仓库组", description = "同步指定外部系统的所有仓库组")
- @PostMapping("/{externalSystemId}/sync-groups")
- public Response syncGroups(
- @Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
- ) {
- repositoryManagerService.syncGroups(externalSystemId);
- return Response.success();
- }
-
- @Operation(summary = "同步Git项目", description = "同步指定外部系统下指定仓库组的所有项目")
- @PostMapping("/{externalSystemId}/groups/sync-projects")
- public Response syncProjects(
- @Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
- ) {
- repositoryManagerService.syncProjects(externalSystemId);
- return Response.success();
- }
-
- @Operation(summary = "同步Git分支", description = "同步指定外部系统下指定项目的所有分支")
- @PostMapping("/{externalSystemId}/projects/sync-branches")
- public Response syncBranches(
- @Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
- ) {
- repositoryManagerService.syncBranches(externalSystemId);
- return Response.success();
- }
-
- @Operation(summary = "获取Git实例信息", description = "获取指定外部系统的Git实例信息,包括仓库组、项目和分支的数量及最后同步时间")
- @GetMapping("/{externalSystemId}/instance")
- public Response instance(
- @Parameter(description = "外部系统ID", required = true) @PathVariable Long externalSystemId
- ) {
- return Response.success(repositoryManagerService.instance(externalSystemId));
- }
-}
\ No newline at end of file
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryProjectApiController.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryProjectApiController.java
index 70cd4e15..e223ce0b 100644
--- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryProjectApiController.java
+++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/api/RepositoryProjectApiController.java
@@ -3,8 +3,13 @@ package com.qqchen.deploy.backend.deploy.api;
import com.qqchen.deploy.backend.deploy.entity.RepositoryProject;
import com.qqchen.deploy.backend.deploy.dto.RepositoryProjectDTO;
import com.qqchen.deploy.backend.deploy.query.RepositoryProjectQuery;
+import com.qqchen.deploy.backend.deploy.service.IRepositoryProjectService;
+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 jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
@@ -20,6 +25,26 @@ import java.util.List;
@Tag(name = "Git仓库项目管理", description = "Git仓库项目管理相关接口")
public class RepositoryProjectApiController extends BaseController {
+ @Resource
+ private IRepositoryProjectService repositoryProjectService;
+
+ @Operation(summary = "同步Git项目", description = "支持两种同步模式:1)只传externalSystemId-全量同步 2)传externalSystemId+repoGroupId-同步单个仓库组")
+ @PostMapping("/sync")
+ public Response sync(
+ @Parameter(description = "外部系统ID", required = true) @RequestParam Long externalSystemId,
+ @Parameter(description = "仓库组ID(可选)", required = false) @RequestParam(required = false) Long repoGroupId
+ ) {
+ Integer count;
+ if (repoGroupId != null) {
+ // 同步单个仓库组
+ count = repositoryProjectService.syncProjects(externalSystemId, repoGroupId);
+ } else {
+ // 全量同步
+ count = repositoryProjectService.syncProjects(externalSystemId);
+ }
+ return Response.success(count);
+ }
+
@Override
protected void exportData(HttpServletResponse response, List data) {
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IRepositoryProjectRepository.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IRepositoryProjectRepository.java
index 7f8bde3b..541b244f 100644
--- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IRepositoryProjectRepository.java
+++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/repository/IRepositoryProjectRepository.java
@@ -33,5 +33,14 @@ public interface IRepositoryProjectRepository extends IBaseRepository findByExternalSystemIdAndDeletedFalse(Long externalSystemId);
+ /**
+ * 根据外部系统ID和仓库组ID查找未删除的项目列表
+ *
+ * @param externalSystemId 外部系统ID
+ * @param repoGroupId 仓库组ID
+ * @return 项目列表
+ */
+ List findByExternalSystemIdAndRepoGroupIdAndDeletedFalse(Long externalSystemId, Long repoGroupId);
+
Optional findByRepoProjectId(Long repoProjectId);
}
\ No newline at end of file
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryBranchService.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryBranchService.java
index 42a51ad5..02ad885d 100644
--- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryBranchService.java
+++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryBranchService.java
@@ -11,13 +11,32 @@ import com.qqchen.deploy.backend.framework.service.IBaseService;
public interface IRepositoryBranchService extends IBaseService {
/**
- * 同步指定外部系统下指定项目的分支
+ * 同步指定外部系统下的所有分支(全量同步)
*
* @param externalSystemId 外部系统ID
* @return 同步的分支数量
*/
Integer syncBranches(Long externalSystemId);
+ /**
+ * 同步指定仓库组下所有项目的分支
+ *
+ * @param externalSystemId 外部系统ID
+ * @param repoGroupId 仓库组ID
+ * @return 同步的分支数量
+ */
+ Integer syncBranches(Long externalSystemId, Long repoGroupId);
+
+ /**
+ * 同步指定项目的分支
+ *
+ * @param externalSystemId 外部系统ID
+ * @param repoGroupId 仓库组ID
+ * @param repoProjectId 仓库项目ID
+ * @return 同步的分支数量
+ */
+ Integer syncBranches(Long externalSystemId, Long repoGroupId, Long repoProjectId);
+
/**
* 统计指定外部系统下的分支数量
*
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 82db5cca..88131a94 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
@@ -13,7 +13,7 @@ import java.util.List;
public interface IRepositoryGroupService extends IBaseService {
/**
- * 同步指定外部系统的所有仓库组
+ * 同步指定外部系统的所有仓库组(包含同步历史记录)
*
* @param externalSystemId 外部系统ID
* @return 同步的仓库组数量
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryManagerService.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryManagerService.java
deleted file mode 100644
index 186e78b4..00000000
--- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryManagerService.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.qqchen.deploy.backend.deploy.service;
-
-import com.qqchen.deploy.backend.deploy.dto.GitInstanceDTO;
-
-/**
- * Git管理服务接口
- */
-public interface IRepositoryManagerService {
-
- /**
- * 同步Git组
- *
- * @param externalSystemId 外部系统ID
- */
- void syncGroups(Long externalSystemId);
-
- /**
- * 同步Git项目
- *
- * @param externalSystemId 外部系统ID
- */
- void syncProjects(Long externalSystemId);
-
- /**
- * 同步Git分支
- *
- * @param externalSystemId 外部系统ID
- */
- void syncBranches(Long externalSystemId);
-
- /**
- * 获取Git实例信息
- *
- * @param externalSystemId 外部系统ID
- * @return Git实例信息
- */
- GitInstanceDTO instance(Long externalSystemId);
-}
\ No newline at end of file
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryProjectService.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryProjectService.java
index 9e631f63..80d28f90 100644
--- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryProjectService.java
+++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/IRepositoryProjectService.java
@@ -13,13 +13,22 @@ import java.util.List;
public interface IRepositoryProjectService extends IBaseService {
/**
- * 同步指定外部系统下指定仓库组的项目
+ * 同步指定外部系统下的所有项目(全量同步)
*
* @param externalSystemId 外部系统ID
* @return 同步的项目数量
*/
Integer syncProjects(Long externalSystemId);
+ /**
+ * 同步指定仓库组下的所有项目
+ *
+ * @param externalSystemId 外部系统ID
+ * @param repoGroupId 仓库组ID
+ * @return 同步的项目数量
+ */
+ Integer syncProjects(Long externalSystemId, Long repoGroupId);
+
/**
* 统计指定外部系统下的项目数量
*
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryBranchServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryBranchServiceImpl.java
index b5db4ff9..c32b7153 100644
--- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryBranchServiceImpl.java
+++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryBranchServiceImpl.java
@@ -189,8 +189,32 @@ public class RepositoryBranchServiceImpl extends BaseServiceImpl new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
- log.info("Starting branch sync for external system: {} (ID: {})", externalSystem.getName(), externalSystemId);
+
+ // 记录同步模式
+ if (repoProjectId != null) {
+ log.info("Starting branch sync for project (external system: {}, repoGroupId: {}, repoProjectId: {})",
+ externalSystemId, repoGroupId, repoProjectId);
+ } else if (repoGroupId != null) {
+ log.info("Starting branch sync for group (external system: {}, repoGroupId: {})",
+ externalSystemId, repoGroupId);
+ } else {
+ log.info("Starting full branch sync for external system: {} (ID: {})",
+ externalSystem.getName(), externalSystemId);
+ }
- // 3. 获取所有项目
- List projects = repositoryProjectRepository.findByExternalSystemIdAndDeletedFalse(externalSystemId);
+ // 3. 根据参数获取需要同步的项目列表
+ List projects = getProjectsToSync(externalSystemId, repoGroupId, repoProjectId);
if (projects.isEmpty()) {
- log.info("No projects found for external system: {}", externalSystem.getName());
+ log.info("No projects found to sync");
repositorySyncHistoryService.updateSyncHistory(syncHistory.getId(), ExternalSystemSyncStatus.SUCCESS, null);
return 0;
}
@@ -313,6 +348,38 @@ public class RepositoryBranchServiceImpl extends BaseServiceImpl getProjectsToSync(Long externalSystemId, Long repoGroupId, Long repoProjectId) {
+ if (repoProjectId != null) {
+ // 同步单个项目
+ RepositoryProject project = repositoryProjectRepository.findById(repoProjectId)
+ .orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND));
+
+ // 验证项目属于指定的外部系统和仓库组
+ if (!project.getExternalSystemId().equals(externalSystemId)) {
+ throw new BusinessException(ResponseCode.DATA_NOT_FOUND);
+ }
+ if (repoGroupId != null && !project.getRepoGroupId().equals(repoGroupId)) {
+ throw new BusinessException(ResponseCode.DATA_NOT_FOUND);
+ }
+
+ return List.of(project);
+ } else if (repoGroupId != null) {
+ // 同步仓库组下所有项目
+ return repositoryProjectRepository.findByExternalSystemIdAndRepoGroupIdAndDeletedFalse(externalSystemId, repoGroupId);
+ } else {
+ // 全量同步
+ return repositoryProjectRepository.findByExternalSystemIdAndDeletedFalse(externalSystemId);
+ }
+ }
+
/**
* 检查分支信息是否有更新
*/
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 5a360d45..c58fe232 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,15 +1,19 @@
package com.qqchen.deploy.backend.deploy.service.impl;
import com.qqchen.deploy.backend.deploy.converter.RepositoryGroupConverter;
+import com.qqchen.deploy.backend.deploy.dto.RepositorySyncHistoryDTO;
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.enums.ExternalSystemSyncStatus;
+import com.qqchen.deploy.backend.deploy.enums.RepositorySyncType;
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.deploy.service.IRepositorySyncHistoryService;
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;
@@ -44,27 +48,34 @@ public class RepositoryGroupServiceImpl extends BaseServiceImpl new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
+ @Resource
+ private IRepositorySyncHistoryService repositorySyncHistoryService;
- // 2. 从Git API获取所有仓库组信息
- List remoteGroups = gitServiceIntegration.groups(externalSystem);
- if (remoteGroups.isEmpty()) {
- log.info("No groups found in remote git system: {}", externalSystem.getName());
- return 0;
- }
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Integer syncGroups(Long externalSystemId) {
+ // 1. 创建同步历史记录
+ RepositorySyncHistoryDTO groupHistory = repositorySyncHistoryService.createSyncHistory(externalSystemId, RepositorySyncType.GROUP);
try {
- // 3. 获取本地已存在的仓库组
+ // 2. 获取外部系统信息
+ ExternalSystem externalSystem = externalSystemRepository.findById(externalSystemId)
+ .orElseThrow(() -> new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
+
+ // 3. 从Git API获取所有仓库组信息
+ List remoteGroups = gitServiceIntegration.groups(externalSystem);
+ if (remoteGroups.isEmpty()) {
+ log.info("No groups found in remote git system: {}", externalSystem.getName());
+ repositorySyncHistoryService.updateSyncHistory(groupHistory.getId(), ExternalSystemSyncStatus.SUCCESS, null);
+ return 0;
+ }
+
+ // 4. 获取本地已存在的仓库组
List existingGroups = repositoryGroupRepository.findByExternalSystemIdAndDeletedFalse(externalSystemId);
Map existingGroupMap = existingGroups.stream()
.collect(Collectors.toMap(RepositoryGroup::getRepoGroupId, Function.identity()));
- // 4. 处理每个远程仓库组
+ // 5. 处理每个远程仓库组
List groupsToSave = new ArrayList<>();
for (GitGroupResponse remoteGroup : remoteGroups) {
RepositoryGroup group = existingGroupMap.getOrDefault(remoteGroup.getId(), new RepositoryGroup());
@@ -87,16 +98,21 @@ public class RepositoryGroupServiceImpl extends BaseServiceImpl savedGroups = repositoryGroupRepository.saveAll(groupsToSave);
+ // 7. 更新同步历史记录为成功
+ repositorySyncHistoryService.updateSyncHistory(groupHistory.getId(), ExternalSystemSyncStatus.SUCCESS, null);
+
log.info("Successfully synchronized {} groups for external system: {}",
savedGroups.size(), externalSystem.getName());
return savedGroups.size();
} catch (Exception e) {
+ // 8. 更新同步历史记录为失败
+ repositorySyncHistoryService.updateSyncHistory(groupHistory.getId(), ExternalSystemSyncStatus.FAILED, e.getMessage());
log.error("Failed to sync repository groups for external system: {}", externalSystemId, e);
- throw new BusinessException(ResponseCode.REPOSITORY_SYNC_FAILED);
+ throw new BusinessException(ResponseCode.REPOSITORY_GROUP_SYNC_FAILED);
}
}
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryManagerServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryManagerServiceImpl.java
deleted file mode 100644
index 105bb6b5..00000000
--- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryManagerServiceImpl.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package com.qqchen.deploy.backend.deploy.service.impl;
-
-import com.qqchen.deploy.backend.deploy.dto.GitInstanceDTO;
-import com.qqchen.deploy.backend.deploy.dto.RepositoryGroupDTO;
-import com.qqchen.deploy.backend.deploy.dto.RepositoryProjectDTO;
-import com.qqchen.deploy.backend.deploy.dto.RepositorySyncHistoryDTO;
-import com.qqchen.deploy.backend.deploy.entity.RepositorySyncHistory;
-import com.qqchen.deploy.backend.deploy.enums.ExternalSystemSyncStatus;
-import com.qqchen.deploy.backend.deploy.enums.RepositorySyncType;
-import com.qqchen.deploy.backend.deploy.repository.IRepositorySyncHistoryRepository;
-import com.qqchen.deploy.backend.deploy.service.*;
-import com.qqchen.deploy.backend.framework.enums.ResponseCode;
-import com.qqchen.deploy.backend.framework.exception.BusinessException;
-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 static com.qqchen.deploy.backend.framework.enums.ResponseCode.REPOSITORY_BRANCH_SYNC_FAILED;
-import static com.qqchen.deploy.backend.framework.enums.ResponseCode.REPOSITORY_PROJECT_SYNC_FAILED;
-
-/**
- * Git管理服务实现
- */
-@Slf4j
-@Service
-public class RepositoryManagerServiceImpl implements IRepositoryManagerService {
-
- @Resource
- private IRepositoryGroupService repositoryGroupService;
-
- @Resource
- private IRepositoryProjectService repositoryProjectService;
-
- @Resource
- private IRepositoryBranchService repositoryBranchService;
-
- @Resource
- private IRepositorySyncHistoryService repositorySyncHistoryService;
-
- @Resource
- private IRepositorySyncHistoryRepository repositorySyncHistoryRepository;
-
- @Override
- @Transactional(rollbackFor = Exception.class)
- public void syncGroups(Long externalSystemId) {
- try {
- // 1. 创建同步历史记录
- RepositorySyncHistoryDTO groupHistory = repositorySyncHistoryService.createSyncHistory(externalSystemId, RepositorySyncType.GROUP);
-
- try {
- // 2. 同步组
- Integer groupCount = repositoryGroupService.syncGroups(externalSystemId);
-
- // 3. 更新同步历史记录为成功
- repositorySyncHistoryService.updateSyncHistory(groupHistory.getId(), ExternalSystemSyncStatus.SUCCESS, null);
- log.info("Successfully synchronized {} groups for external system: {}", groupCount, externalSystemId);
- } catch (Exception e) {
- // 4. 更新同步历史记录为失败
- repositorySyncHistoryService.updateSyncHistory(groupHistory.getId(), ExternalSystemSyncStatus.FAILED, e.getMessage());
- log.error("Failed to synchronize groups for external system: {}", externalSystemId, e);
- throw e;
- }
- } catch (Exception e) {
- log.error("Failed to create sync history for external system: {}", externalSystemId, e);
- throw new BusinessException(ResponseCode.REPOSITORY_GROUP_SYNC_FAILED);
- }
- }
-
- @Override
- @Transactional(rollbackFor = Exception.class)
- public void syncProjects(Long externalSystemId) {
- try {
- // 1. 创建同步历史记录
- RepositorySyncHistoryDTO projectHistory = repositorySyncHistoryService.createSyncHistory(externalSystemId, RepositorySyncType.PROJECT);
-
- try {
- // 2. 同步项目
- Integer projectCount = repositoryProjectService.syncProjects(externalSystemId);
-
- // 3. 更新同步历史记录为成功
- repositorySyncHistoryService.updateSyncHistory(projectHistory.getId(), ExternalSystemSyncStatus.SUCCESS, null);
- log.info("Successfully synchronized {} projects in external system: {}", projectCount, externalSystemId);
- } catch (Exception e) {
- // 4. 更新同步历史记录为失败
- repositorySyncHistoryService.updateSyncHistory(projectHistory.getId(), ExternalSystemSyncStatus.FAILED, e.getMessage());
- log.error("Failed to synchronize projects in external system: {}", externalSystemId, e);
- throw e;
- }
- } catch (Exception e) {
- log.error("Failed to create sync history for external system: {}", externalSystemId, e);
- throw new BusinessException(REPOSITORY_PROJECT_SYNC_FAILED);
- }
- }
-
- @Override
- @Transactional(rollbackFor = Exception.class)
- public void syncBranches(Long externalSystemId) {
- try {
- // 1. 创建同步历史记录
- RepositorySyncHistoryDTO branchHistory = repositorySyncHistoryService.createSyncHistory(externalSystemId, RepositorySyncType.BRANCH);
-
- try {
- // 2. 同步分支
- Integer branchCount = repositoryBranchService.syncBranches(externalSystemId);
-
- // 3. 更新同步历史记录为成功
- repositorySyncHistoryService.updateSyncHistory(branchHistory.getId(), ExternalSystemSyncStatus.SUCCESS, null);
- log.info("Successfully synchronized {} branches for external system: {}", branchCount, externalSystemId);
- } catch (Exception e) {
- // 4. 更新同步历史记录为失败
- repositorySyncHistoryService.updateSyncHistory(branchHistory.getId(), ExternalSystemSyncStatus.FAILED, e.getMessage());
- log.error("Failed to synchronize branches for external system: {}", externalSystemId, e);
- throw e;
- }
- } catch (Exception e) {
- log.error("Failed to create sync history for external system: {}", externalSystemId, e);
- throw new BusinessException(REPOSITORY_BRANCH_SYNC_FAILED);
- }
- }
-
- @Override
- public GitInstanceDTO instance(Long externalSystemId) {
- // 1. 创建返回对象
- GitInstanceDTO instanceDTO = new GitInstanceDTO();
-
- // 2. 获取组列表
- List groups = repositoryGroupService.findByExternalSystemId(externalSystemId);
- instanceDTO.setRepositoryGroupList(groups);
- instanceDTO.setTotalGroups(groups.size());
-
- // 3. 获取项目列表
- List projects = repositoryProjectService.findByExternalSystemId(externalSystemId);
- instanceDTO.setRepositoryProjectList(projects);
- instanceDTO.setTotalProjects(projects.size());
-
- // 4. 获取分支总数
- Long totalBranches = repositoryBranchService.countByExternalSystemId(externalSystemId);
- instanceDTO.setTotalBranches(totalBranches.intValue());
-
- // 5. 获取最后同步时间
- RepositorySyncHistory lastGroupSync = repositorySyncHistoryRepository.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
- externalSystemId, RepositorySyncType.GROUP, ExternalSystemSyncStatus.SUCCESS);
- if (lastGroupSync != null) {
- instanceDTO.setLastSyncGroupsTime(lastGroupSync.getEndTime());
- }
-
- RepositorySyncHistory lastProjectSync = repositorySyncHistoryRepository.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
- externalSystemId, RepositorySyncType.PROJECT, ExternalSystemSyncStatus.SUCCESS);
- if (lastProjectSync != null) {
- instanceDTO.setLastSyncProjectsTime(lastProjectSync.getEndTime());
- }
-
- RepositorySyncHistory lastBranchSync = repositorySyncHistoryRepository.findTopByExternalSystemIdAndSyncTypeAndStatusOrderByStartTimeDesc(
- externalSystemId, RepositorySyncType.BRANCH, ExternalSystemSyncStatus.SUCCESS);
- if (lastBranchSync != null) {
- instanceDTO.setLastSyncBranchesTime(lastBranchSync.getEndTime());
- }
-
- return instanceDTO;
- }
-}
\ No newline at end of file
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryProjectServiceImpl.java b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryProjectServiceImpl.java
index fe5afb92..2138cc17 100644
--- a/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryProjectServiceImpl.java
+++ b/backend/src/main/java/com/qqchen/deploy/backend/deploy/service/impl/RepositoryProjectServiceImpl.java
@@ -1,10 +1,13 @@
package com.qqchen.deploy.backend.deploy.service.impl;
import com.qqchen.deploy.backend.deploy.converter.RepositoryProjectConverter;
+import com.qqchen.deploy.backend.deploy.dto.RepositorySyncHistoryDTO;
import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
import com.qqchen.deploy.backend.deploy.entity.RepositoryGroup;
import com.qqchen.deploy.backend.deploy.entity.RepositoryProject;
import com.qqchen.deploy.backend.deploy.dto.RepositoryProjectDTO;
+import com.qqchen.deploy.backend.deploy.enums.ExternalSystemSyncStatus;
+import com.qqchen.deploy.backend.deploy.enums.RepositorySyncType;
import com.qqchen.deploy.backend.deploy.integration.IGitServiceIntegration;
import com.qqchen.deploy.backend.deploy.integration.response.GitProjectResponse;
import com.qqchen.deploy.backend.deploy.query.RepositoryProjectQuery;
@@ -12,6 +15,7 @@ import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository;
import com.qqchen.deploy.backend.deploy.repository.IRepositoryGroupRepository;
import com.qqchen.deploy.backend.deploy.repository.IRepositoryProjectRepository;
import com.qqchen.deploy.backend.deploy.service.IRepositoryProjectService;
+import com.qqchen.deploy.backend.deploy.service.IRepositorySyncHistoryService;
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;
@@ -59,6 +63,9 @@ public class RepositoryProjectServiceImpl extends BaseServiceImpl new BusinessException(ResponseCode.EXTERNAL_SYSTEM_NOT_FOUND));
- log.info("Start syncing projects for external system: {} (ID: {})", externalSystem.getName(), externalSystemId);
+
+ // 记录同步模式
+ if (repoGroupId != null) {
+ log.info("Start syncing projects for external system: {} (ID: {}), repoGroupId: {}",
+ externalSystem.getName(), externalSystemId, repoGroupId);
+ } else {
+ log.info("Start syncing all projects for external system: {} (ID: {})",
+ externalSystem.getName(), externalSystemId);
+ }
- // 2. 获取所有组
- List groups = repositoryGroupRepository.findByExternalSystemIdAndDeletedFalse(externalSystemId);
+ // 3. 获取需要同步的仓库组列表
+ List groups = getGroupsToSync(externalSystemId, repoGroupId);
if (groups.isEmpty()) {
log.info("No groups found for external system: {}", externalSystem.getName());
+ repositorySyncHistoryService.updateSyncHistory(projectHistory.getId(), ExternalSystemSyncStatus.SUCCESS, null);
return 0;
}
log.info("Found {} groups to sync", groups.size());
@@ -210,15 +246,45 @@ public class RepositoryProjectServiceImpl extends BaseServiceImpl getGroupsToSync(Long externalSystemId, Long repoGroupId) {
+ if (repoGroupId != null) {
+ // 同步单个仓库组
+ RepositoryGroup group = repositoryGroupRepository.findById(repoGroupId)
+ .orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND));
+
+ // 验证仓库组属于指定的外部系统
+ if (!group.getExternalSystemId().equals(externalSystemId)) {
+ throw new BusinessException(ResponseCode.DATA_NOT_FOUND);
+ }
+
+ return List.of(group);
+ } else {
+ // 全量同步
+ return repositoryGroupRepository.findByExternalSystemIdAndDeletedFalse(externalSystemId);
+ }
+ }
+
@Override
public Long countByExternalSystemId(Long externalSystemId) {
return repositoryProjectRepository.countByExternalSystemId(externalSystemId);
diff --git a/backend/src/main/java/com/qqchen/deploy/backend/framework/config/RedisConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/framework/config/RedisConfig.java
new file mode 100644
index 00000000..86d6245f
--- /dev/null
+++ b/backend/src/main/java/com/qqchen/deploy/backend/framework/config/RedisConfig.java
@@ -0,0 +1,54 @@
+package com.qqchen.deploy.backend.framework.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * Redis配置类
+ *
+ * @author qichen
+ */
+@Configuration
+public class RedisConfig {
+
+ @Bean
+ public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
+ RedisTemplate template = new RedisTemplate<>();
+ template.setConnectionFactory(factory);
+
+ // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
+ Jackson2JsonRedisSerializer