前言

专栏文章 质量保障系统的落地实践 (一) 概览篇
专栏文章 质量保障系统的落地实践 (二) 项目管理设计 - 基础信息与缺陷信息设计
大家好,以上两篇文章,先从大体上介绍了质量保障平台的概况,而后谈了谈项目管理板块如何对接三方缺陷管理平台,里面包含了账户体系的映射设计,从而将缺陷信息沉淀至质量保障平台。
那么本篇文章我们将开始介绍项目管理 - 代码信息设计的内容,相信有了上一篇文章的底子,这篇文章的阅读将更清晰明了。

代码信息数据库设计

现在主流的代码管理平台有很多,大多数管理平台均能提供一定的开放能力,我们可以通过这些开放能力尝试得到一些我们想要的数据,本篇文章以 git 为例,介绍如何收集项目提交的代码信息。
那么我们先来看看 git 平台 api 能够提供的数据:

# 获取代码提交信息
url = f"{CODE_SERVER_HOST}/api/v4/projects/{code_project_id}/repository/commits"  # git获取一定时间范围内的提交记录
params = {
                "ref_name": branch_name,      # 分支名
                "since": since,      # 统计开始时间
                "until": until,      # 统计结束时间
                "page": page,
                "per_page": page_size,
                "order": "default"
            }
# 接口响应
[{
    'id': 'a4a18684d2f35ceb*****2fe360cbaad0285888',
    'short_id': 'a4a1****',
    'created_at': '2024-04-15T17:26:26.000+08:00',
    'parent_ids': ['e4f3afb3b3cf28eff****28436dc5f1463654'],
    'title': '提交title',
    'message': '提交内容',
    'author_name': 'author_name',
    'author_email': 'author_email',
    'authored_date': '2024-04-15T17:26:26.000+08:00',
    'committer_name': 'committer_name',
    'committer_email': 'committer_email',
    'committed_date': '2024-04-15T17:26:26.000+08:00'
},
{....}
]

从上述 git 接口可以看出,想要获取一段时间内的代码提交情况,需要几个参数:code_project_id,ref_name、since、until,那么结合到质量保障平台中,该如何设计呢?在实际项目迭代中,往往存在项目 1 涉及代码应用 1、代码应用 2,项目 2 设计代码应用 2、代码应用 3 的情况。而代码应用可以归属到某一组织节点,所以我们可以得出项目、代码应用、组织结构之间的关系:

结合 git 接口请求的必要参数,那么数据表的设计自然而然可以得到:

# 服务应用管理-服务应用信息
class ApplicationInfo(BaseModel):
    department_id = models.IntegerField(verbose_name=u"归属组织节点")
    app_code = models.CharField(max_length=150, verbose_name=u"服务code")
    code_project_id = models.IntegerField(null=True, blank=True, verbose_name=u"应用项目id")
    is_available = models.BooleanField(default=True, verbose_name=u"是否有效")

    class Meta:
        db_table = 'Application_Info'
        verbose_name = "服务应用管理-服务应用信息"
        verbose_name_plural = verbose_name

# 服务应用管理-项目服务管理
class ProjectApplicationInfo(BaseModel):
    department_id = models.IntegerField(verbose_name=u"归属组织节点")
    project_id = models.IntegerField(verbose_name=u"项目id")
    app_code = models.CharField(max_length=150, verbose_name=u"服务code")
    code_project_id = models.IntegerField(verbose_name=u"应用项目id")
    branch = models.CharField(max_length=50, verbose_name=u"代码分支")
    since_time = models.CharField(max_length=30, verbose_name=u"开始统计时间")
    until_time = models.CharField(max_length=30, verbose_name=u"结束统计时间")
    is_available = models.BooleanField(default=True, verbose_name=u"是否有效")

    class Meta:
        db_table = "Project_Application_Info"
        verbose_name = "服务应用管理-项目服务管理"
        verbose_name_plural = verbose_name

接下来我们来看接口的返回值,里面有几个关键字段:short_id、committer_name、committer_email,通过 short_id 可以访问 git 的查看详情:

url = f"{CODE_SERVER_HOST}/api/v4/projects/{code_project_id}/repository/commits/{commit_short_id}"

# 接口响应
{
    'id': '993b76f0c97031195****51f04a5025fb8d',
    'short_id': '993****6f0',
    'created_at': '2024-04-07T14:54:10.000+08:00',
    'parent_ids': ['dee5f****a13c31d1651cbcc995ce2e882f'],
    'title': 'title',
    'message': 'message',
    'author_name': 'author_name',
    'author_email': 'author_email',
    'authored_date': '2024-04-07T14:54:10.000+08:00',
    'committer_name': 'committer_name',
    'committer_email': 'committer_email',
    'committed_date': '2024-04-07T14:54:10.000+08:00',
    'stats': {      # 代码变更信息
        'additions': 34,
        'deletions': 0,
        'total': 34
    },
    'status': None,
    'project_id': 20**4,      # project_id即传参中的code_project_id
    'last_pipeline': None
}

以上关于代码提交信息的详情,特别是变更代码的数量就是我们需要采集的重点数据,那么设计数据表:

class ProjectCodeCommitInfo(BaseModel):
    department_id = models.IntegerField(verbose_name=u"归属组织节点")
    project_id = models.IntegerField(verbose_name=u"项目id")
    app_code = models.CharField(max_length=150, verbose_name=u"服务code")
    code_project_id = models.IntegerField(verbose_name=u"应用项目id")
    branch = models.CharField(max_length=80, verbose_name=u"代码分支")
    title = models.TextField(verbose_name=u"commit提交标题")
    committer_name = models.CharField(max_length=80, verbose_name=u"提交人姓名")
    committer_email = models.CharField(max_length=100, verbose_name=u"提交人邮箱")
    committed_time = models.CharField(max_length=30, verbose_name=u"提交时间")
    additions = models.IntegerField(verbose_name=u"新增代码")
    deletions = models.IntegerField(verbose_name=u"移除代码")
    total = models.IntegerField(verbose_name=u"变更代码总数")

    class Meta:
        db_table = "Project_Code_Commit_Info"
        verbose_name = "服务应用管理-项目应用分支代码提交记录"
        verbose_name_plural = verbose_name

代码信息与账户体系关联

到目前为止,我们已经设计了存储项目代码提交信息的数据表,接下来只需要依据接口需要的传参,访问对应 open api 获取到对应的代码提交信息即可,这样我们就将三方平台的原始数据进行了采集。那么到了这一步,又碰到了和缺陷管理板块类似的问题 - 账户体系的关联,我们可以看到代码提交列表、代码提交详情中均有一个 committer_email 字段,这个字段为研发本地提交代码至 git 服务时,本地设置的邮箱,所以说这个邮箱和质量保障平台的账户体系中的邮箱是没有直接关联的,那么该怎么做,才能将二者关联起来?答案也如同缺陷管理板块的一样,通过映射表进行转换,同样的我司大部分人的提交邮箱如果没有自定义设置过的话也是有统一后缀的,那么处理逻辑与缺陷映射处理逻辑类似:


# 依据代码提交邮箱获取映射后的用户邮箱
def fetchCodeTargetEmail(department_id, committer_email):
    email_mapping_record = CodeEmailMappingInfo.objects.filter(
        department_id=department_id, source_email=committer_email, date_delete=None
    )
    target_email = None
    if email_mapping_record:
        email_mapping_info = email_mapping_record[0]
        target_email = email_mapping_info.target_email

    return target_email

# 提交邮箱进行数据映射,关联到对应用户邮箱,存储时进行替换
target_email = fetchCodeTargetEmail(department_id, committer_email)
if target_email:
    committer_email = target_email

千行代码缺陷率

通过第二篇文章的实现思路,我们已经能够获取到项目提交的缺陷信息,而通过这篇文章的实现思路,又可以得到项目的变更代码信息,那么就可以得到一个侧面反馈研发质量的一个指标:千行代码缺陷率,统计归于 A 研发的缺陷数量,归于 A 研发的变更代码数量,计算可得。除此之外,变更代码数量也可以从侧面反馈出每个研发开发工作量的大小:

总结

本篇文章的处理思路与第二篇文章类似,故此只提如何依据代码管理平台 open api 返回值设计数据库以及账户体系关联逻辑,希望大家多留言交流,谢谢。


↙↙↙阅读原文可查看相关链接,并与作者交流