1. 概述

对于Git通过Hook实现静态代码检测,大致分为两个方向:

1>借助Client-Side-Hook来实现。

此方法对应于研发人员工作机上的${PROJECT_ROOT}/.git/hooks/pre-commit脚本实现。

2>借助Server-Side-Hook来实现。

此方法分为2个方面,一个是全局性配置(下面会详细介绍),一个是对应对单独项目进行配置,此方法对应于Git服务端的
/var/opt/gitlab/git-data/repositories/<group>/<project>.git/custom_hooks/pre-receive脚本。

相比较之下,两种实现方式之中,第二种方式有点更明显,其无需研发人员进行任何的本地操作,这里详细讲解gitlab的全局配置。

3>使用关键组件包括:

checkstyle8.17+python2.7.5+jdk1.8

python 的版本不能超过3.0

Jdk 版本最低为1.8

2.操作步骤

2.1:上传文件

登录Gitlab服务

1.创建文件路径,执行命令:

mkdir -p /data/gitlab.checkstyle

2.进入文件中

cd /data/gitlab.checkstyle

3.将checkstyle.xml和checkstyle-8.17-all.jar 文件上传到gitlab.checkstyle

4.验证是否正确

可执行命令:

java -jar /data/gitlab.checkstyle/checkstyle-8.17-all.jar -c/data/gitlab.checkstyle/checkstyle.xml /data/gitlab.checkstyle/TestController.java

如有些类似输出内容即表示环境正确。

TestController.java文件可自行上传。

checkstyle.xml文件可自行网上查找,可使用谷歌或阿里的都可以。

gitlab集成docker gitlab集成代码审批_jar

2.1.配置gitlab全局钩子

1.创建自定义全局钩子目录

cd /opt/gitlab/embedded/service/gitlab-shell/

mkdir custom_hooks

2.指定全局自定义钩子目录

修改 /etc/gitlab/gitlab.rb 配置文件中的配置项:gitlab_shell['custom_hooks_dir']内容为:

/opt/gitlab/embedded/service/gitlab-shell/custom_hooks

原内容为:

gitlab集成docker gitlab集成代码审批_java_02

修改内容为:
/opt/gitlab/embedded/service/gitlab-shell/custom_hooks

vi /etc/gitlab/gitlab.rb

gitlab集成docker gitlab集成代码审批_jar_03

3.使自定义内容生效

操作完成后,执行命令使配置生效:

sudo gitlab-ctl reconfigure

gitlab集成docker gitlab集成代码审批_gitlab集成docker_04

2.3上传代码规范检查脚本

1.进入全局自定义钩子目录下:

cd /opt/gitlab/embedded/service/gitlab-shell/custom_hooks

2.创建pre-receive.d文件夹

mkdir pre-receive.d

cd pre-receive.d

3.上传附件中的pre-receive文件到pre-receive.d文件目录下并赋予可执行权限

chmod +777 pre-receive

4.pre-receive脚本内容为:

#!/usr/bin/python
#coding=utf-8
import os
import sys
import subprocess
import tempfile
import shutil
__author__ = "lance"
class Trigger(object):
   def __init__(self):
       '''
       初始化文件列表信息,提交者信息,提交时间,当前操作的分支
       '''
       self.pushAuthor = ""
       self.pushTime = ""
       self.fileList = []
       self.ref = ""
   def __getGitInfo(self):
       '''
       '''
       self.oldObject, self.newObject, self.ref = sys.stdin.readline().strip().split(' ')
   def __getPushInfo(self):
       '''
       git show命令获取push作者,时间,以及文件列表
       文件的路径为相对于版本库根目录的一个相对路径
       '''
       rev = subprocess.Popen('git rev-list '+self.newObject,shell=True,stdout=subprocess.PIPE)
       revList = rev.stdout.readlines()
       revList = [x.strip() for x in revList]
       #查找从上次提交self.oldObject之后还有多少次提交,即本次push提交的object列表
       indexOld = revList.index(self.oldObject)
       pushList = revList[:indexOld]
       pushList.reverse()
       # temp file
       tempdir = tempfile.mkdtemp('git_hook')
       #循环获取每次提交的文件列表
       for pObject in pushList:
           p = subprocess.Popen('git show '+pObject,shell=True,stdout=subprocess.PIPE)
           pipe = p.stdout.readlines()
           pipe = [x.strip() for x in pipe]
           #print("===>",pipe)   
           #验证是否java文件
           file = pipe[6].strip("diff").strip()
           if not file.lower().endswith('.java'):
              continue
       filename = file.split('/')[-1]
       #git get Tree
       content_hash = pipe[7].strip("index").strip()[9:16]
       content_p = subprocess.Popen('git cat-file -p '+content_hash,shell=True,stdout=subprocess.PIPE)
       cpipe = content_p.stdout.readlines()
       #print(cpipe)
       with open(os.path.join(tempdir, filename), 'w+') as fp:
            fp.writelines(cpipe)
       #self.handler_checkstyle(tempdir+"/"+content_hash+'.java')      
       # checkstyle    
       self.handler_checkstyle(tempdir)
   def getGitPushInfo(self):
       self.__getGitInfo()
       self.__getPushInfo()

 # 处理java文件 
   def handler_checkstyle(self, file):
    try:
       cmd = r'java -jar /data/gitlab.checkstyle/lib/checkstyle-8.17-all.jar -c /data/gitlab.checkstyle/style/checkstyle.xml '+file+'/'
       #print(cmd)
       result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
       rpipe = result.stdout.readlines()
       if len(rpipe)>2:
           print(rpipe)
       exit(1)
    finally:
       shutil.rmtree(file)
       #pass          

if __name__ == "__main__":
   #print("argv: ", sys.argv)
   t = Trigger()
   t.getGitPushInfo()    
   exit(0)

3.验证

对于不合规的内容输出异常提示:

gitlab集成docker gitlab集成代码审批_jar_05

如果想了解单独配置和全局配置下想单独排查某项目的步骤,欢迎联系。

以上为全部内容。

 


星光不问赶路人,时光不负有心人