Gitlab+checkstyle检查客户端推送代码是否规范
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Gitlab+checkstyle检查客户端推送代码是否规范本⽂讲述如何在gitlab 服务器上,拒绝⽤户推送不合规范的 java 代码
1、⼀般在仓库的/var/opt/gitlab/git-data/repositories/<group>/<project>.git⽬录下创建⽬录:custom_hooks
2、新增可执⾏⽂件:pre-receive (脚本可以是任何ruby python shell可执⾏脚本,没有后缀名)输⼊内容如下:
#!/usr/bin/python
#coding=utf-8
import os
import sys
import subprocess
import tempfile
import shutil
from shutil import copyfile
__author__ = "lance"
class Trigger(object):
def__init__(self):
'''
初始化⽂件列表信息,提交者信息,提交时间,当前操作的分⽀
'''
self.pushAuthor = ""
self.pushTime = ""
self.fileList = []
self.ref = ""
def__getGitInfo(self):
value = sys.stdin.readline().strip()
self.oldObject, self.newObject,self.ref = value.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')
#循环获取每次提交的⽂件列表i
diff_file_list = []
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
print(pipe)
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 handler_checkstyle(self, file):
try:
#print(file)
cmd = r'java -jar /data/gitlab.checkstyle/lib/checkstyle-8.20-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()
stuerr_message = result.stderr.readlines()
#print(stuerr_message)
for index in range(0,len(rpipe)):
# print('\n')
print(rpipe[index])
if len(rpipe) > 2:
exit(1)
except Exception as e:
print('error message:'+e.message)
exit(1)
finally:
#shutil.rmtree(file)
pass
def getGitPushInfo(self):
self.__getGitInfo()
self.__getPushInfo()
if__name__ == "__main__":
#print("argv: ", sys.argv)
t = Trigger()
t.getGitPushInfo()
print('success')
exit(0)
注:如果这些脚本在window中编辑后上传到服务器;vim编辑时:set ff=unix 来重新编辑⽂件格式
3、使⽤的jar包的位置:
4、使⽤的xml的位置:/data/gitlab.checkstyle/style/checkstyle.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"/dtds/configuration_1_3.dtd">
<!-- This is a checkstyle configuration file. For descriptions of
what the following rules do, please see the checkstyle configuration
page at /config.html -->
<module name="Checker">
<!-- 重复代码的检查,超过20⾏就认为重复,UTF-8格式-->
<module name="TreeWalker">
<!-- 命名⽅⾯的检查,它们都使⽤了Sun官⽅定的规则。
-->
<!-- 局部的final变量,包括catch中的参数的检查 -->
<module name="LocalFinalVariableName"/>
<!-- 局部的⾮final型的变量,包括catch中的参数的检查 -->
<!--<module name="LocalVariableName" />-->
<!-- 包名的检查(只允许⼩写字母) -->
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
</module>
<!-- 仅仅是static型的变量(不包括static final型)的检查 -->
<module name="StaticVariableName"/>
<!-- 类型(Class或Interface)名的检查 -->
<module name="TypeName"/>
<!-- ⾮static型变量的检查 -->
<module name="MemberName"/>
<!-- ⽅法名的检查 -->
<module name="MethodName"/>
<!-- ⽅法的参数名 -->
<!--<module name="ParameterName " />-->
<!-- 常量名的检查 -->
<module name="ConstantName"/>
<!-- 对区域的检查 -->
<!-- 不能出现空⽩区域 -->
<module name="EmptyBlock"/>
<!-- 所有区域都要使⽤⼤括号。
-->
<module name="NeedBraces"/>
<!-- 多余的括号 -->
<module name="AvoidNestedBlocks">
<property name="allowInSwitchCase" value="true"/>
</module>
<!-- String的⽐较不能⽤!= 和 == -->
<module name="StringLiteralEquality"/>
<!-- 同⼀⾏不能有多个声明 -->
<module name="MultipleVariableDeclarations"/>
<!-- 不必要的圆括号 -->
<module name="UnnecessaryParentheses"/>
<module name="UncommentedMain"/>
<!-- 检查并确保所有的常量中的L都是⼤写的。
因为⼩写的字母l跟数字1太象了 -->
<module name="UpperEll"/>
<!-- 检查数组类型的定义是String[] args,⽽不是String args[] -->
<module name="ArrayTypeStyle"/>
<module name="MagicNumber">
<property name="tokens" value="NUM_DOUBLE, NUM_FLOAT"/>
<property name="ignoreNumbers" value="0,1"/>
<property name="ignoreAnnotation" value="true"/>
</module>
</module>
</module>
开始测试:
1.包名必须匹配正则:(反例中包含⼤写)
^[a-z]+(\.[a-z][a-z0-9]*)*$
2.变量名必须匹配正则:(反例中以$开头)
^[a-z]+(\.[a-z][a-z0-9]*)*$
3.字符串数字匹配 Sring[] args ⽽不是 String args[]
4.字符串的⽐较⽤ equals 不能⽤ ==
5.空的main ⽅法检查
执⾏结果如图。