devops流程中,对接gerrit的设计与实现(一)

一、背景

在devops整个流程中,gerrit把关代码的提交与评审,当某开发人员提交代码后,首先需要通过jenkins的自动化verify(对Verified+1),此时发送消息给gerrit组内的所有人员,告知他们有代码需要评审;其次,当代码评审人员在添加评审人或打分的时候,发送消息给代码提交者。

下面截图,说明下最后提到的两个地方:“添加评审人”、“打分”。
在这里插入图片描述
另外,我们在OA管理后台中,申请新项目的时候,当流程通过后,需要自动创建gitlab和gerrit项目。

最后,再补充一张图,说明代码评审通过后的展示:

图中指出了代码提交者,对应Owner字段,代码评审人。代码评审,分为两步,先jenkins自动化验证,后人工进行评审。

  • 第一次是jenkins,可以从Reviewers列表和Verified中看到,好处是快速诊断是否符合规范、是否通过自动化测试等等。最近比较火的chatgpt,也可以做代码评审;
  • 第二次是同事之间的人工评审。
    在这里插入图片描述

二、目标

  • 1、对接OA管理后台系统,自动创建gerrit项目,包括赋权限。
  • 2、发送消息提醒其他同事来评审你所提交的增量代码。
  • 3、把代码评审的结果及时通知提交代码者。

三、总体设计

注: webhook回调是三个流程都会共用。这里分为三类角色,申请新项目、代码提交者、代码评审者。(他们都属于gerrit组内的用户,我们为了让消息更加精准地发送到不同的人,不是盲目地发送给gerrit组内的所有人)

在这里插入图片描述

四、自动创建gerrit项目

分为三步:第一、创建负责人组;第二、创建开发者组;第三、创建项目;第四、给项目赋权限。

4.1、调用gerrit api创建的示例

#!/bin/bash
#
# 创建gerrit项目
#
# ./create_gerrit_project.sh user-service
#
# 参数说明:
# 
# service-name: 项目名称

project_name=$1

die() {
    echo $1
    exit 1
}

[[ -z "$project_name" ]] && die "请输入项目名称"

group_owner_id="34dd8f718972d73c9a3474b2sfad2d52x2cf596f"
GERRIT_USER_PWD="admin:123456"
GERRIT_ADDR="http://192.168.5.60:8080/a"

# 1、创建负责人分组
owner_group_name="$project_name-owner"

rsp=$(curl -u $GERRIT_USER_PWD -s -X PUT "${GERRIT_ADDR}/groups/${owner_group_name}" -H "content-type: application/json" -d "{  \"description\": \"${owner_group_name}\", \"visible_to_all\": false, \"owner_id\": \"${group_owner_id}\"}")

owner_group_id=$(echo "${rsp:5}" | jq '.id' | sed 's#"##g')

# 2、创建开发者分组
dev_group_name="$project_name-dev"

rsp=$(curl -u $GERRIT_USER_PWD -s -X PUT "${GERRIT_ADDR}/groups/${dev_group_name}" -H "content-type: application/json" -d "{  \"description\": \"${dev_group_name}\", \"visible_to_all\": false, \"owner_id\": \"${owner_group_id}\"} ")

dev_group_id=$(echo "${rsp:5}" | jq '.id' | sed 's#"##g')

# 3、创建项目
real_project_name="root%2F${project_name}"

rsp=$(curl -u $GERRIT_USER_PWD -s -X PUT "${GERRIT_ADDR}/projects/${real_project_name}" -H "content-type: application/json" -d "{  \"description\": \"${project_name}\", \"submit_type\": \"INHERIT\", \"owners\": [ \"${owner_group_name}\" ]} ")

echo $rsp

# 4、设置权限
rsp=$(curl -u $GERRIT_USER_PWD -s -X POST "${GERRIT_ADDR}/projects/${real_project_name}/access" \
    -H "content-type: application/json" \
    -d "{ \"add\": { \
            \"refs/*\": { \
                \"permissions\": { \
                    \"read\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"label-Verified\": { \
                        \"label\": \"Verified\", \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false, \
                                \"min\": -1, \
                                \"max\": 1 \
                            }, \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false, \
                                \"min\": -1, \
                                \"max\": 1 \
                            } \
                        } \
                    }, \
                    \"labelAs-Verified\": { \
                        \"label\": \"Verified\", \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false, \
                                \"min\": -1, \
                                \"max\": 1 \
                            }, \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false, \
                                \"min\": -1, \
                                \"max\": 1 \
                            } \
                        } \
                    }, \
                    \"label-Code-Review\": { \
                        \"label\": \"Code-Review\",
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"min\": -2,
                                \"max\": 2
                            }, \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"min\": -1,
                                \"max\": 1
                            } \
                        } \
                    }, \
                    \"forgeServerAsCommitter\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            }, \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"forgeAuthor\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            }, \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"removeReviewer\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            }, \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"delete\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"viewPrivateChanges\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"createTag\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"createSignedTag\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"editHashtags\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"deleteOwnChanges\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"editTopicName\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"abandon\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"force\": false \
                            } \
                        } \
                    }, \
                    \"push\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"addPatchSet\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"forgeCommitter\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"pushMerge\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"rebase\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"submit\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"submitAs\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    } \
                } \
            }, \
            \"refs/tags/*\": { \
                \"permissions\": { \
                    \"createSignedTag\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"createTag\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    } \
                } \
            }, \
            \"refs/heads/*\": { \
                \"permissions\": { \
                    \"forgeCommitter\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"forgeAuthor\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"editTopicName\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"label-Code-Review\": { \
                        \"label\": \"Code-Review\",
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"min\": -2,
                                \"max\": 2
                            }, \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\", \
                                \"min\": -1,
                                \"max\": 1
                            } \
                        } \
                    }, \
                    \"create\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"push\": { \
                        \"rules\": { \
                            \"${dev_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    }, \
                    \"submit\": { \
                        \"rules\": { \
                            \"${owner_group_id}\": { \
                                \"action\": \"ALLOW\" \
                            } \
                        } \
                    } \
                } \
            } \
          } \
        }")

echo $rsp

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2、java语言实现

  • 引入jar包
        <dependency>
            <groupId>com.urswolfer.gerrit.client.rest</groupId>
            <artifactId>gerrit-rest-java-client</artifactId>
            <version>0.9.3</version>
        </dependency>
  • 配置
project:
  gerrit:
    host: http://192.168.5.60:8080
    login: admin
    password: 123456
    # 负责人
    groupOwnerId: 34dd8f718972d73c9a3474b2sfad2d52x2cf596f
  • 实现类

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

/**
 * sonar配置
 *
 * @author xxx
 */
@RefreshScope
@Data
@Configuration
@ConfigurationProperties(prefix = "project.gerrit")
public class GerritProperties {
    /**
     * 地址
     */
    private String host;

    /**
     * 用户名
     */
    private String login;

    /**
     * 密码
     */
    private String password;

    /**
     * 所属的组ID
     */
    private String groupOwnerId;
}


import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.api.access.AccessSectionInfo;
import com.google.gerrit.extensions.api.access.PermissionInfo;
import com.google.gerrit.extensions.api.access.PermissionRuleInfo;
import com.google.gerrit.extensions.api.access.ProjectAccessInput;
import com.google.gerrit.extensions.api.groups.GroupInput;
import com.google.gerrit.extensions.api.projects.ProjectApi;
import com.google.gerrit.extensions.api.projects.ProjectInput;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.common.GroupBaseInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.common.ProjectInfo;
import com.urswolfer.gerrit.client.rest.GerritAuthData;
import com.urswolfer.gerrit.client.rest.GerritRestApiFactory;
import com.urswolfer.gerrit.client.rest.http.HttpStatusException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * gerrit api
 * <p>
 * 1.创建负责人组
 * 2.创建开发人组
 * 3.创建工程
 * 4.设置权限
 * </p>
 *
 * @author xxx
 */
@Slf4j
@Service
public class GerritService {

    private GerritRestApiFactory gerritRestApiFactory;
    private GerritAuthData.Basic authData;
    private GerritApi gerritApi;

    @Autowired
    private GerritProperties gerritProperties;

    @PostConstruct
    public void init() {
        gerritRestApiFactory = new GerritRestApiFactory();
        authData = new GerritAuthData.Basic(gerritProperties.getHost(), gerritProperties.getLogin(), gerritProperties.getPassword());
        gerritApi = gerritRestApiFactory.create(authData);
    }

    /**
     * 新建gerrit项目及组、权限
     *
     * @param group       项目组
     * @param projectName 项目名称,比如:root/watch-answering-server
     */
    public void create(String group, String projectName) {
        String ownerGroupName = projectName + "-owner";
        String devGroupName = projectName + "-dev";

        try {
            // 创建负责人分组
            GroupBaseInfo ownerGroupBaseInfo = this.createGroup(ownerGroupName, gerritProperties.getGroupOwnerId());
            String ownerGroupId = ownerGroupBaseInfo.id;
            log.info("负责人分组ID:{}", ownerGroupId);

            // 创建开发者分组
            GroupBaseInfo devGroupBaseInfo = this.createGroup(devGroupName, ownerGroupId);
            String devGroupId = devGroupBaseInfo.id;
            log.info("开发者分组ID:{}", devGroupId);

            // 创建工程
            ProjectInfo projectInfo = this.createProject(projectName, ownerGroupName);
            log.info("项目的详情是:{}", JsonUtils.toJsonString(projectInfo));

            // 赋权限项
            if (null != projectInfo) {
                this.setAccess(projectName, ownerGroupId, devGroupId);
            }
        } catch (Exception e) {
            log.error("创建组、工程、赋权出现了异常, projectName={}", projectName, e);
        }
    }

    /**
     * 新建工程.
     *
     * @param projectName    工程名
     * @param ownerGroupName 所属组
     * @return
     * @throws Exception
     */
    private ProjectInfo createProject(String projectName, String ownerGroupName) throws Exception {
        try {
            ProjectApi projectApi = gerritApi.projects().name(projectName);

            ProjectInfo projectInfo = projectApi.get();
            if (null != projectInfo) {
                log.warn("工程{}已存在,请勿重复创建", projectName);
                return projectInfo;
            }
        } catch (Exception e) {
            ProjectInput request = new ProjectInput();
            request.name = projectName;
            request.description = projectName;
            request.submitType = SubmitType.INHERIT;
            request.owners = Lists.newArrayList(ownerGroupName);

            log.info("新建gerrit工程成功, request={}", JsonUtils.toJsonString(request));

            return gerritApi.projects().create(request).get();
        }

        return null;
    }

    /**
     * 创建组.
     *
     * @param groupName 组名
     * @param ownerId   所属组
     * @return
     * @throws Exception
     */
    private GroupBaseInfo createGroup(String groupName, String ownerId) throws Exception {
        GroupBaseInfo groupBaseInfo = new GroupBaseInfo();

        GroupInfo groupInfo;
        try {
            groupInfo = gerritApi.groups().id(groupName).get();
            log.warn("组{}已存在,请勿重复创建", groupName);
        } catch (HttpStatusException e) {
            // 不存在,则重新创建

            GroupInput groupInput = new GroupInput();
            groupInput.name = groupName;
            groupInput.description = groupName;
            groupInput.ownerId = ownerId;
            groupInput.visibleToAll = false;

            groupInfo = gerritApi.groups().create(groupInput).get();
            if (null == groupInfo) {
                throw new IllegalArgumentException("创建组出现异常");
            }

            log.info("组创建成功, groupInput={}", JsonUtils.toJsonString(groupInput));

            groupBaseInfo.id = groupInfo.id;
            groupBaseInfo.name = groupInfo.name;
            return groupBaseInfo;
        }

        groupBaseInfo.id = groupInfo.id;
        groupBaseInfo.name = groupInfo.name;
        return groupBaseInfo;
    }

    /**
     * 赋权限.
     *
     * @param projectName  项目名称
     * @param ownerGroupId 负责人组ID
     * @param devGroupId   开发组ID
     * @throws Exception
     */
    private void setAccess(String projectName, String ownerGroupId, String devGroupId) throws Exception {
        try {
            ProjectApi projectApi = gerritApi.projects().name(projectName);

            ProjectAccessInput projectAccessInput = new ProjectAccessInput();
            Map<String, AccessSectionInfo> addMap = Maps.newHashMap();
            addMap.put("refs/*", buildAccessSectionInfo(ownerGroupId, devGroupId));
            addMap.put("refs/tags/*", buildTagsAccessSectionInfo(devGroupId));
            addMap.put("refs/heads/*", buildHeadsAccessSectionInfo(ownerGroupId, devGroupId));

            log.info("权限列表是:{}", JsonUtils.toJsonString(addMap));

            projectAccessInput.add = addMap;

            projectApi.access(projectAccessInput);
        } catch (HttpStatusException e) {
            log.error("赋权限出现异常, projectName={}, ownerGroupId={}, devGroupId={}", projectName, ownerGroupId, devGroupId, e);
        }
    }


    private AccessSectionInfo buildAccessSectionInfo(String ownerGroupId, String devGroupId) {
        AccessSectionInfo accessSectionInfo = new AccessSectionInfo();

        Map<String, PermissionInfo> permissions = Maps.newHashMap();

        permissions.put("read", buildPermissionInfo("", devGroupId));
        permissions.put("label-Code-Review", buildReviewPermissionInfo("Code-Review", ownerGroupId, devGroupId));
        permissions.put("label-Verified", buildReviewPermissionInfo("Verified", ownerGroupId, devGroupId));
        permissions.put("labelAs-Verified", buildReviewPermissionInfo("Verified", ownerGroupId, devGroupId));
        permissions.put("forgeServerAsCommitter", buildPermissionInfo("", ownerGroupId, devGroupId));
        permissions.put("forgeAuthor", buildPermissionInfo("", ownerGroupId, devGroupId));
        permissions.put("removeReviewer", buildPermissionInfo("", ownerGroupId, devGroupId));
        permissions.put("delete", buildPermissionInfo("", ownerGroupId));
        permissions.put("viewPrivateChanges", buildPermissionInfo("", ownerGroupId));
        permissions.put("createTag", buildPermissionInfo("", ownerGroupId));
        permissions.put("createSignedTag", buildPermissionInfo("", ownerGroupId));
        permissions.put("editHashtags", buildPermissionInfo("", ownerGroupId));
        permissions.put("deleteOwnChanges", buildPermissionInfo("", devGroupId));
        permissions.put("editTopicName", buildPermissionInfo("", devGroupId));
        permissions.put("abandon", buildPermissionInfo("", devGroupId));
        permissions.put("push", buildPermissionInfo("", devGroupId));
        permissions.put("addPatchSet", buildPermissionInfo("", devGroupId));
        permissions.put("forgeCommitter", buildPermissionInfo("", devGroupId));
        permissions.put("pushMerge", buildPermissionInfo("", devGroupId));
        permissions.put("rebase", buildPermissionInfo("", devGroupId));
        permissions.put("submit", buildPermissionInfo("", ownerGroupId));
        permissions.put("submitAs", buildPermissionInfo("", ownerGroupId));

        accessSectionInfo.permissions = permissions;

        return accessSectionInfo;
    }

    private AccessSectionInfo buildTagsAccessSectionInfo(String devGroupId) {
        AccessSectionInfo accessSectionInfo = new AccessSectionInfo();

        Map<String, PermissionInfo> permissions = Maps.newHashMap();

        permissions.put("createSignedTag", buildPermissionInfo("", devGroupId));
        permissions.put("createTag", buildPermissionInfo("", devGroupId));

        accessSectionInfo.permissions = permissions;

        return accessSectionInfo;
    }

    private AccessSectionInfo buildHeadsAccessSectionInfo(String ownerGroupId, String devGroupId) {
        AccessSectionInfo accessSectionInfo = new AccessSectionInfo();

        Map<String, PermissionInfo> permissions = Maps.newHashMap();

        permissions.put("forgeCommitter", buildPermissionInfo("", devGroupId));
        permissions.put("label-Code-Review", buildReviewPermissionInfo("Code-Review", ownerGroupId, devGroupId));
        permissions.put("forgeAuthor", buildPermissionInfo("", devGroupId));
        permissions.put("editTopicName", buildPermissionInfo("", devGroupId));
        permissions.put("create", buildPermissionInfo("", devGroupId));
        permissions.put("push", buildPermissionInfo("", devGroupId));
        permissions.put("submit", buildPermissionInfo("", ownerGroupId));

        accessSectionInfo.permissions = permissions;

        return accessSectionInfo;
    }

    private PermissionInfo buildPermissionInfo(String label, String groupId) {
        PermissionInfo permissionInfo = new PermissionInfo(label, false);

        Map<String, PermissionRuleInfo> rules = buildRules(groupId);
        permissionInfo.rules = rules;

        return permissionInfo;
    }

    private PermissionInfo buildPermissionInfo(String label, String ownerGroupId, String devGroupId) {
        PermissionInfo permissionInfo = new PermissionInfo(label, false);

        Map<String, PermissionRuleInfo> rules = buildRules(ownerGroupId, devGroupId);
        permissionInfo.rules = rules;

        return permissionInfo;
    }

    private PermissionInfo buildReviewPermissionInfo(String label, String ownerGroupId, String devGroupId) {
        PermissionInfo permissionInfo = new PermissionInfo(label, false);

        Map<String, PermissionRuleInfo> rules = buildReviewRules(ownerGroupId, devGroupId);
        permissionInfo.rules = rules;

        return permissionInfo;
    }

    private Map<String, PermissionRuleInfo> buildRules(String groupId) {
        Map<String, PermissionRuleInfo> rules = Maps.newHashMap();

        PermissionRuleInfo permissionRuleInfo = buildPermissionRuleInfo();
        rules.put(groupId, permissionRuleInfo);

        return rules;
    }

    private Map<String, PermissionRuleInfo> buildRules(String ownerGroupId, String devGroupId) {
        Map<String, PermissionRuleInfo> rules = Maps.newHashMap();

        PermissionRuleInfo permissionRuleInfo = buildPermissionRuleInfo();
        rules.put(ownerGroupId, permissionRuleInfo);
        rules.put(devGroupId, permissionRuleInfo);

        return rules;
    }

    private Map<String, PermissionRuleInfo> buildReviewRules(String ownerGroupId, String devGroupId) {
        Map<String, PermissionRuleInfo> rules = Maps.newHashMap();

        PermissionRuleInfo permissionRuleInfo = buildPermissionRuleInfo();
        permissionRuleInfo.max = 2;
        permissionRuleInfo.min = -2;
        rules.put(ownerGroupId, permissionRuleInfo);

        permissionRuleInfo = buildPermissionRuleInfo();
        permissionRuleInfo.max = 1;
        permissionRuleInfo.min = -1;
        rules.put(devGroupId, permissionRuleInfo);

        return rules;
    }

    private PermissionRuleInfo buildPermissionRuleInfo() {
        PermissionRuleInfo permissionRuleInfo = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);

        return permissionRuleInfo;
    }
}

五、测试

    @Autowired
    private GerritService gerritService;

    @ApiOperation(value = "新建gerrit工程")
    @PostMapping(value = "/api/gerrit/create/{projectName}")
    public ResponseEntity<?> createProject(@NotNull @PathVariable String projectName) {

        // 新建gerrit工程
        gerritService.create("", "root/" + projectName);

        return ResponseEntity.ok("SUCCESS");
    }

写在最后的话

本文是对接gerrit的设计与实现的第一篇,由于我把详细的实现都完整贴出,导致篇幅超出预期,故将之拆分为多篇。后续将接着完成后面的设计……

另外,gerrit工程创建后,申请新项目的人,如果不在上面的组34dd8f718972d73c9a3474b2sfad2d52x2cf596f内,你会看不到已创建好的gerrti工程!!不要慌,让34dd8f718972d73c9a3474b2sfad2d52x2cf596f组里的人员给你赋权下哈。

  • 所以,这里就还是有一个前提条件,你得有个管理员组34dd8f718972d73c9a3474b2sfad2d52x2cf596f,需要手动加人到组里。
  • 这么说,本文只实现了自动创建gerrit项目以及权限项,创建了owner组和dev组。因为缺少信息–每个组里应该添加哪些人。
  • 后期再实现给组里加人的操作,这里先列出它的api接口,以供参考。
    在这里插入图片描述
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值