From 874c95fa9c333bff944c1cdfb2d8dc618a000dd7 Mon Sep 17 00:00:00 2001 From: shizhendong Date: Mon, 28 Oct 2024 11:01:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20ASW-113=20=E6=96=B0=E5=A2=9E=20applicat?= =?UTF-8?q?ion=20MR=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/app/controller/GitController.java | 31 ++++++ .../module/app/dao/ApplicationMergeDao.java | 16 +++ .../app/entity/ApplicationMergeEntity.java | 36 +++++++ .../app/service/IApplicationMergeService.java | 15 +++ .../asw/module/app/service/IGitService.java | 4 + .../impl/ApplicationMergeServiceImpl.java | 97 +++++++++++++++++++ .../app/service/impl/GitServiceImpl.java | 92 ++++++++++++++++++ .../db/mapper/app/ApplicationMergeMapper.xml | 58 +++++++++++ .../resources/db/migration/R__AZ_sys_menu.sql | 2 + .../db/migration/R__AZ_sys_role_menu.sql | 6 ++ .../db/migration/V1.0.01__INIT_TABLES.sql | 21 ++++ 11 files changed, 378 insertions(+) create mode 100644 src/main/java/net/geedge/asw/module/app/dao/ApplicationMergeDao.java create mode 100644 src/main/java/net/geedge/asw/module/app/entity/ApplicationMergeEntity.java create mode 100644 src/main/java/net/geedge/asw/module/app/service/IApplicationMergeService.java create mode 100644 src/main/java/net/geedge/asw/module/app/service/impl/ApplicationMergeServiceImpl.java create mode 100644 src/main/resources/db/mapper/app/ApplicationMergeMapper.xml diff --git a/src/main/java/net/geedge/asw/module/app/controller/GitController.java b/src/main/java/net/geedge/asw/module/app/controller/GitController.java index 6ae3050..0d0be96 100644 --- a/src/main/java/net/geedge/asw/module/app/controller/GitController.java +++ b/src/main/java/net/geedge/asw/module/app/controller/GitController.java @@ -1,13 +1,17 @@ package net.geedge.asw.module.app.controller; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import net.geedge.asw.common.util.ASWException; import net.geedge.asw.common.util.R; import net.geedge.asw.common.util.RCode; import net.geedge.asw.common.util.T; +import net.geedge.asw.module.app.entity.ApplicationMergeEntity; +import net.geedge.asw.module.app.service.IApplicationMergeService; import net.geedge.asw.module.app.service.IGitService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -18,6 +22,9 @@ public class GitController { @Autowired private IGitService gitService; + @Autowired + private IApplicationMergeService applicationMergeService; + @GetMapping("/{workspaceId}/branch") public R listBranch(@PathVariable("workspaceId") String workspaceId, @RequestParam(value = "search", required = false) String search) { @@ -136,4 +143,28 @@ public class GitController { return R.ok().putData("record", record); } + @GetMapping("/{workspaceId}/mr") + public R listMr(@PathVariable("workspaceId") String workspaceId, @RequestParam Map params) { + // workspaceId + params = T.MapUtil.defaultIfEmpty(params, new HashMap<>()); + params.put("workspaceId", workspaceId); + + Page page = applicationMergeService.queryList(params); + return R.ok(page); + } + + @PostMapping("/{workspaceId}/mr") + public synchronized R newMr(@PathVariable("workspaceId") String workspaceId, @RequestBody ApplicationMergeEntity entity) { + T.VerifyUtil.is(entity).notNull() + .and(entity.getTitle()).notEmpty(RCode.PARAM_CANNOT_EMPTY) + .and(entity.getTargetBranch()).notEmpty(RCode.PARAM_CANNOT_EMPTY) + .and(entity.getTargetBranch()).notEmpty(RCode.PARAM_CANNOT_EMPTY); + + // workspaceId + entity.setWorkspaceId(workspaceId); + + ApplicationMergeEntity record = applicationMergeService.newMr(entity); + return R.ok().putData("record", record); + } + } \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/app/dao/ApplicationMergeDao.java b/src/main/java/net/geedge/asw/module/app/dao/ApplicationMergeDao.java new file mode 100644 index 0000000..3c13267 --- /dev/null +++ b/src/main/java/net/geedge/asw/module/app/dao/ApplicationMergeDao.java @@ -0,0 +1,16 @@ +package net.geedge.asw.module.app.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.geedge.asw.module.app.entity.ApplicationMergeEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + + +@Mapper +public interface ApplicationMergeDao extends BaseMapper { + List queryList(Page page, Map params); + +} diff --git a/src/main/java/net/geedge/asw/module/app/entity/ApplicationMergeEntity.java b/src/main/java/net/geedge/asw/module/app/entity/ApplicationMergeEntity.java new file mode 100644 index 0000000..6b242eb --- /dev/null +++ b/src/main/java/net/geedge/asw/module/app/entity/ApplicationMergeEntity.java @@ -0,0 +1,36 @@ +package net.geedge.asw.module.app.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.geedge.asw.module.sys.entity.SysUserEntity; + +@Data +@TableName(value = "application_merge", autoResultMap = true) +public class ApplicationMergeEntity { + + @TableId(type = IdType.ASSIGN_UUID) + private String id; + private String sourceBranch; + private String targetBranch; + private String commitId; + private String title; + private Integer removeSourceBranch = 0; + private String description; + private String status; + private String message; + + private Long createTimestamp; + private String createUserId; + + private String workspaceId; + + @TableField(exist = false) + private SysUserEntity createUser; + + @TableField(exist = false) + private Object commit; + +} \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/app/service/IApplicationMergeService.java b/src/main/java/net/geedge/asw/module/app/service/IApplicationMergeService.java new file mode 100644 index 0000000..5ce7156 --- /dev/null +++ b/src/main/java/net/geedge/asw/module/app/service/IApplicationMergeService.java @@ -0,0 +1,15 @@ +package net.geedge.asw.module.app.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import net.geedge.asw.module.app.entity.ApplicationMergeEntity; + +import java.util.Map; + +public interface IApplicationMergeService extends IService { + + Page queryList(Map params); + + ApplicationMergeEntity newMr(ApplicationMergeEntity entity); + +} diff --git a/src/main/java/net/geedge/asw/module/app/service/IGitService.java b/src/main/java/net/geedge/asw/module/app/service/IGitService.java index a391418..5579c1e 100644 --- a/src/main/java/net/geedge/asw/module/app/service/IGitService.java +++ b/src/main/java/net/geedge/asw/module/app/service/IGitService.java @@ -9,6 +9,8 @@ public interface IGitService { Repository initRepository(String workspaceId); + Map infoCommit(String workspaceId, String commitId); + List> listBranch(String workspaceId, String search); Map infoBranch(String workspaceId, String branchName); @@ -17,6 +19,8 @@ public interface IGitService { void deleteBranch(String workspaceId, String branchName); + String mergeBranch(String workspaceId, String sourceBranch, String targetBranch, String message) throws RuntimeException; + List> listApplication(String workspaceId, String branch, String q); Map infoApplication(String workspaceId, String branch, String applicationName); diff --git a/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationMergeServiceImpl.java b/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationMergeServiceImpl.java new file mode 100644 index 0000000..a799283 --- /dev/null +++ b/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationMergeServiceImpl.java @@ -0,0 +1,97 @@ +package net.geedge.asw.module.app.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.log.Log; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.geedge.asw.common.config.Query; +import net.geedge.asw.common.util.T; +import net.geedge.asw.module.app.dao.ApplicationMergeDao; +import net.geedge.asw.module.app.entity.ApplicationMergeEntity; +import net.geedge.asw.module.app.service.IApplicationMergeService; +import net.geedge.asw.module.app.service.IGitService; +import net.geedge.asw.module.sys.entity.SysUserEntity; +import net.geedge.asw.module.sys.service.ISysUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +@Service +public class ApplicationMergeServiceImpl extends ServiceImpl implements IApplicationMergeService { + + private final static Log log = Log.get(); + + @Autowired + private IGitService gitService; + + @Autowired + private ISysUserService userService; + + @Override + public Page queryList(Map params) { + Page page = new Query(ApplicationMergeEntity.class).getPage(params); + List list = this.getBaseMapper().queryList(page, params); + + for (ApplicationMergeEntity mergeEntity : list) { + String commitId = mergeEntity.getCommitId(); + if (T.StrUtil.isNotEmpty(commitId)) { + try { + Map infoCommit = gitService.infoCommit(mergeEntity.getWorkspaceId(), commitId); + mergeEntity.setCommit(infoCommit); + } catch (Exception e) { + } + } + } + + page.setRecords(list); + return page; + } + + @Override + public ApplicationMergeEntity newMr(ApplicationMergeEntity entity) { + String srcBranch = entity.getSourceBranch(); + String tgtBranch = entity.getTargetBranch(); + + String message = entity.getTitle(); + String workspaceId = entity.getWorkspaceId(); + + entity.setCreateTimestamp(System.currentTimeMillis()); + entity.setCreateUserId(StpUtil.getLoginIdAsString()); + + // merge + try { + String commitId = gitService.mergeBranch(workspaceId, srcBranch, tgtBranch, message); + entity.setCommitId(commitId); + entity.setStatus("success"); + + Map infoCommit = gitService.infoCommit(workspaceId, commitId); + entity.setCommit(infoCommit); + } catch (Exception e) { + log.error(e, "[newMr] [merge error] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [msg: {}]", workspaceId, srcBranch, tgtBranch, e.getMessage()); + entity.setCommitId(""); + entity.setStatus("failed"); + entity.setMessage(e.getMessage()); + } + + // remove source branch + if (1 == entity.getRemoveSourceBranch()) { + try { + log.info("[newMr] [remove source branch] [workspaceId: {}] [branch: {}]", workspaceId, srcBranch); + gitService.deleteBranch(workspaceId, srcBranch); + } catch (Exception e) { + log.error(e, "[newMr] [remove source branch error] [workspaceId: {}] [branch: {}] [msg: {}]", workspaceId, srcBranch, e.getMessage()); + } + } + + // save + this.save(entity); + + SysUserEntity user = userService.getById(entity.getCreateUserId()); + entity.setCreateUser(user); + + return entity; + } + +} \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/app/service/impl/GitServiceImpl.java b/src/main/java/net/geedge/asw/module/app/service/impl/GitServiceImpl.java index 6297d35..772df5b 100644 --- a/src/main/java/net/geedge/asw/module/app/service/impl/GitServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/app/service/impl/GitServiceImpl.java @@ -12,16 +12,22 @@ import net.geedge.asw.module.sys.service.ISysUserService; import net.geedge.asw.module.workspace.entity.WorkspaceEntity; import net.geedge.asw.module.workspace.service.IWorkspaceService; import org.apache.commons.io.FilenameUtils; +import org.eclipse.jgit.api.CreateBranchCommand; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.MergeCommand; +import org.eclipse.jgit.api.MergeResult; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheBuilder; import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.lib.*; +import org.eclipse.jgit.merge.MergeStrategy; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; +import org.eclipse.jgit.transport.PushResult; +import org.eclipse.jgit.transport.RemoteRefUpdate; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.PathFilter; @@ -156,6 +162,20 @@ public class GitServiceImpl implements IGitService { } } + @Override + public Map infoCommit(String workspaceId, String commitId) { + try (Git git = this.getGitInstance(workspaceId); + Repository repository = git.getRepository(); + RevWalk revCommits = new RevWalk(repository); + ) { + RevCommit commit = revCommits.parseCommit(ObjectId.fromString(commitId)); + return this.buildAswCommitInfo(commit); + } catch (IOException e) { + log.error(e, "[infoCommit] [error] [workspaceId: {}] [commitId: {}]", workspaceId, commitId); + throw new RuntimeException(e); + } + } + @Override public List> listBranch(String workspaceId, String search) { List> resultList = T.ListUtil.list(true); @@ -239,6 +259,78 @@ public class GitServiceImpl implements IGitService { } } + @Override + public String mergeBranch(String workspaceId, String srcBranch, String tgtBranch, String message) throws RuntimeException { + log.info("[mergeBranch] [begin] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}]", workspaceId, srcBranch, tgtBranch); + // prepare a new folder for the cloned repository + File localPath = T.FileUtil.file(net.geedge.asw.common.util.Constants.TEMP_PATH, T.StrUtil.uuid()); + T.FileUtil.del(localPath); + T.FileUtil.mkdir(localPath); + + // bare repository + File repoDir = this.getRepoDirPath(workspaceId); + + // clone + try (Git git = Git.cloneRepository() + .setBare(false) + .setURI(repoDir.getAbsolutePath()) + .setDirectory(localPath) + .setCredentialsProvider(null) + .call()) { + + // git fetch + git.fetch().call(); + + // checout + git.checkout() + .setCreateBranch(true) + .setName(tgtBranch) + .setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK) + .setStartPoint("origin/" + tgtBranch) + .call(); + + // merge + MergeResult mergeResult = git.merge() + .setCommit(true) + .setMessage(message) + .setStrategy(MergeStrategy.RECURSIVE) + .setFastForward(MergeCommand.FastForwardMode.NO_FF) + .include(git.getRepository().findRef("origin/" + srcBranch)) + .call(); + + MergeResult.MergeStatus mergeStatus = mergeResult.getMergeStatus(); + if (mergeStatus.isSuccessful()) { + log.info("[mergeBranch] [merge success]"); + + // push + Iterable pushResultIterable = git.push() + .setRemote("origin") + .add(tgtBranch) + .call(); + for (PushResult pushResult : pushResultIterable) { + for (RemoteRefUpdate update : pushResult.getRemoteUpdates()) { + if (update.getStatus() != RemoteRefUpdate.Status.OK && update.getStatus() != RemoteRefUpdate.Status.UP_TO_DATE) { + log.error("[mergeBranch] [push error] [remote: {}] [status: {}]", update.getRemoteName(), update.getStatus()); + String errorMessage = "Push failed: " + update.getStatus(); + throw new RuntimeException(errorMessage); + } + } + } + return mergeResult.getNewHead().getName(); + } else { + log.error("[mergeBranch] [merge failed] [mergeStatus: {}] [conflict: {}]", mergeStatus, T.JSONUtil.toJsonStr(mergeResult.getConflicts())); + String errorMessage = String.format("Merge failed: %s, Conflicts: %s", mergeStatus, T.JSONUtil.toJsonStr(mergeResult.getConflicts())); + throw new RuntimeException(errorMessage); + } + } catch (Exception e) { + log.error(e, "[mergeBranch] [error] [workspaceId: {}]", workspaceId); + throw new RuntimeException(e.getMessage()); + } finally { + T.FileUtil.del(localPath); + log.info("[mergeBranch] [finshed] [workspaceId: {}]", workspaceId); + } + } + @Override public List> listApplication(String workspaceId, String branch, String q) { List> resultList = T.ListUtil.list(true); diff --git a/src/main/resources/db/mapper/app/ApplicationMergeMapper.xml b/src/main/resources/db/mapper/app/ApplicationMergeMapper.xml new file mode 100644 index 0000000..ca0ef6d --- /dev/null +++ b/src/main/resources/db/mapper/app/ApplicationMergeMapper.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db/migration/R__AZ_sys_menu.sql b/src/main/resources/db/migration/R__AZ_sys_menu.sql index c05829f..cae8944 100644 --- a/src/main/resources/db/migration/R__AZ_sys_menu.sql +++ b/src/main/resources/db/migration/R__AZ_sys_menu.sql @@ -19,6 +19,8 @@ INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, ` INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2009', 'main_branch_edit', 'buttons.edit', '2000', 'button', '', '', '', 9, 1722478572000, 1); INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2010', 'regular_branch_edit', 'buttons.edit', '2000', 'button', '', '', '', 10, 1722478572000, 1); INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2011', 'branch_delete', 'buttons.delete', '2000', 'button', '', '', '', 11, 1722478572000, 1); +INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2012', 'mr_view', 'buttons.view', '2000', 'button', '', '', '', 12, 1722478572000, 1); +INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('2013', 'mr_add', 'buttons.add', '2000', 'button', '', '', '', 13, 1722478572000, 1); INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('3000', 'pcaps', 'overall.pcaps', '0', 'menu', '', '/pcaps', 'asw-icon icon-Pcaps', 2, 1722478572000, 1); INSERT INTO `sys_menu` (`id`, `name`, `i18n`, `pid`, `type`, `perms`, `route`, `icon`, `order`, `create_timestamp`, `state`) VALUES ('3001', 'pacp_view', 'buttons.view', '3000', 'button', '', '', '', 1, 1722478572000, 1); diff --git a/src/main/resources/db/migration/R__AZ_sys_role_menu.sql b/src/main/resources/db/migration/R__AZ_sys_role_menu.sql index 9713cb8..765673b 100644 --- a/src/main/resources/db/migration/R__AZ_sys_role_menu.sql +++ b/src/main/resources/db/migration/R__AZ_sys_role_menu.sql @@ -22,6 +22,8 @@ INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('owner', '2008'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('owner', '2009'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('owner', '2010'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('owner', '2011'); +INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('owner', '2012'); +INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('owner', '2013'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('owner', '3000'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('owner', '3001'); @@ -82,6 +84,8 @@ INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('maintainer', '2008'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('maintainer', '2009'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('maintainer', '2010'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('maintainer', '2011'); +INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('maintainer', '2012'); +INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('maintainer', '2013'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('maintainer', '3000'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('maintainer', '3001'); @@ -135,6 +139,8 @@ INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('developer', '2006'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('developer', '2007'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('developer', '2008'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('developer', '2010'); +INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('developer', '2012'); +INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('developer', '2013'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('developer', '3000'); INSERT INTO `sys_role_menu`(`role_id`, `menu_id`) VALUES ('developer', '3001'); diff --git a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql index b7d9471..357cd58 100644 --- a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql +++ b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql @@ -351,6 +351,27 @@ CREATE TABLE `application_href` ( KEY `idx_application_id` (`application_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +/** + * 新增 application_merge 表 + */ +DROP TABLE IF EXISTS `application_merge`; +CREATE TABLE `application_merge` ( + `id` VARCHAR(64) NOT NULL COMMENT '主键', + `source_branch` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '源分支', + `target_branch` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '目标分支', + `commit_id` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '提交ID', + `title` VARCHAR(4096) NOT NULL DEFAULT '' COMMENT '标题', + `remove_source_branch` int(1) NOT NULL DEFAULT 0 COMMENT '是否删除源分支, 1:删除;0:不删除 默认:0', + `description` text NOT NULL DEFAULT '' COMMENT '描述信息', + `status` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '合并状态,可选值:success,failed', + `message` text NOT NULL DEFAULT '' COMMENT '操作信息', + `create_timestamp` BIGINT(20) NOT NULL COMMENT '创建时间戳', + `create_user_id` VARCHAR(64) NOT NULL COMMENT '创建人id', + `workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_workspace_id` (`workspace_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + /** * 新增 package 表 */