p3c简介、GitLab集成p3c-pmd

p3c简介、GitLab集成p3c-pmdGitLab集成p3c-pmd简介p3c2017年,阿里公开了第一版的java代码规范手册代码规范检查插件p3c,是根据《阿里巴巴Java开发手册》转化而成的自动化插件PMD-源码分析器PMD(ProgrammingMistakeDetector)是一个开源的静态代码检查工具h

大家好,欢迎来到IT知识分享网。p3c简介、GitLab集成p3c-pmd"

目录
  • GitLab集成p3c-pmd
    • 简介
      • p3c
      • PMD-源码分析器
        • PMD 的工作逻辑
      • p3c-pmd
    • GitLab集成p3c-pmd
      • GitLab hook
      • 一、获取p3c-pmd
      • 二、配置GitLab hook
        • 2.1、项目单独配置
          • 2.1.1、获取项目路径
          • 2.1.2、配置GitLab hook
        • 2.2、GitLab全局配置
    • pre-receive 文件详解

GitLab集成p3c-pmd

简介

p3c

2017年,阿里公开了第一版的java代码规范手册

代码规范检查插件p3c,是根据《阿里巴巴Java开发手册》转化而成的自动化插件

PMD-源码分析器

PMD (Programming Mistake Detector) 是一个开源的静态代码检查工具

https://pmd.github.io/

静态代码检查就是在不运行代码的情况下检查代码中的内容,然后和事先制定的规则进行比对,指出代码中不符合规则的部分

PMD 支持多种语言,比如项目本身的 Java,Salesforce 相关的 Apex、VisualForce,还有 JavaScript、XML 等

PMD 对于各种语言都预设了一套代码规则,也支持开发自定义规则,可以使用 Java 类或者 XPath

PMD 的工作逻辑

PMD 是一款采用 BSD 协议发布的Java 程序静态代码检查工具

当使用PMD规则分析Java源码时,PMD首先利用JavaCC和EBNF文法产生了一个语法分析器,用来分析普通文本形式的Java代码,产生符合特定语法结构的语法,同时又在JavaCC的基础上添加了语义的概念即JJTree,通过JJTree的一次转换,这样就将Java代码转换成了一个AST(抽象语法树),AST是Java符号流之上的语义层,PMD把AST处理成一个符号表。然后编写PMD规则,一个PMD规则可以看成是一个Visitor,通过遍历AST找出多个对象之间的一种特定模式,即代码所存在的问题

抽象语法树是将代码结构通过“树”的形式展现出来,每部分代码(类、变量声明、if-else 语句、变量赋值、数据库查询等)会成为树的各个节点

在代码转化为语法树后,PMD 中制定的规则会检测树的相应节点,分析其属性或结构,从而找出违反规定的部分

p3c-pmd

p3c-pmd 插件是基于 PMD 实现的,更具体的来说是基于 pmd-java 的,因为 PMD 不仅支持 Java 代码分析,还支持其他多种语言

具体自定义规则的方式,通过自定义Java类和XPATH规则实现

GitLab集成p3c-pmd

GitLab hook

GitLab服务端有三个主要的钩子

1、pre-receive:处理客户端push动作时最先被调用的脚本,以非0值退出拒绝Push,可以用来做注释标准化、代码标准化等)

2、update:与pre-receive功能类似,为每个准备更新的分支各运行一次,假如推送者同时向多个分支推送内容,pre-receive 只运行一次,相比之下 update 则会为每一个被推送的分支各运行一次。它不会从标准输入读取内容,而是接受三个参数:引用的名字(分支),推送前的引用指向的内容的 SHA-1 值,以及用户准备推送的内容的 SHA-1 值。 如果 update 脚本以非零值退出,只有相应的那一个引用会被拒绝;其余的依然会被更新

3、post-receive:是在push之后执行的脚本,可以用来调用后续的持续集成、发邮件通知等。它接受与 pre-receive 相同的标准输入数据,该脚本无法终止推送进程,不过客户端在它结束运行之前将保持连接状态, 所以如果你想做其他操作需谨慎使用它,因为它将耗费你很长的一段时间


更多变量详情请参考官方文档

GitLab hook 可用的环境变量(所有hook)

环境变量 描述
GL_ID 发起推送的用户的 GitLab 标识符。例如,user-2234
GL_PROJECT_PATH (GitLab 13.2 及更高版本)GitLab 项目路径
GL_PROTOCOL (GitLab 13.2 and later) Protocol used for this change. One of: http (Git push using HTTP), ssh (Git push using SSH), or web (all other actions)
GL_REPOSITORY project-

,项目的ID
GL_USERNAME 发起推送的用户的 GitLab 用户名

GitLab hook 可用的环境变量(仅限pre-receive、post-receive)

环境变量 描述
GIT_ALTERNATE_OBJECT_DIRECTORIES 隔离环境中的备用对象目录
GIT_OBJECT_DIRECTORY 隔离环境中的 GitLab 项目路径
GIT_PUSH_OPTION_COUNT push的数量
GIT_PUSH_OPTION_ Value of push options where i is from 0 to GIT_PUSH_OPTION_COUNT – 1

一、获取p3c-pmd

下载源码

进入p3c-pmd子项目,执行 mvn clean package 进行打包,获取到jar包

二、配置GitLab hook

2.1、项目单独配置

2.1.1、获取项目路径

登录GitLab页面,在 管理中心 -> 项目 找到相应的项目,获取到项目的Gitaly相对路径(例如:@hashed/fc/09/fc091d39524c9d4b5b11f84f9132996a94ca01c9816d2db3b866bef1b0699d91.git)

2.1.2、配置GitLab hook

登录GitLab服务器,在项目路径下,创建custom_hooks/pre-receive.d目录,并在pre-receive.d目录下创建pre-receive文件

2.2、GitLab全局配置

全局配置路径:/opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d

在路径下创建pre-receive文件

pre-receive 文件详解

思路:

使用pre-receive钩子,确保执行push动作的时候脚本被率先执行

使用 git diff 命令找出两次push之间有差异的 *.java 文件

使用 p3c-pmd 对找出来的文件进行分析,判断是否存在违规现象

根据检测结果,决定是否允许本次push

黑/白名单思路:

(全局模式下)默认所有项目都不启动检测功能,只有检测到项目在黑名单内,才会触发检测动作

检测完成后,如果项目名在项目白名单内、或执行push的用户在用户白名单内,则将检测结果强制改为通过(检测过程中如果检测到违规代码,会显示在标准输出)

黑名单功能与白名单功能可以共存,即检测到push动作,因为在黑名单内,所以会触发检测动作;检测完成之后,因为在白名单内,所以会强制将检测结果改为通过

Git中有个内置变量 GL_REPOSITORY ,可以返回当前项目的项目编号,例如 project-787 ,可以根据这个变量来确定项目,进行黑白名单判断


用户白名单文件示例

xiaoming
xiaohu

项目白名单文件示例

# http://gitlab.com/devops/p3c-test.git
project-787

# http://gitlab.com/devops/p3c.git
project-765

项目黑名单文件示例

# http://gitlab.com/devops/p3c-test.git
project-787

# http://gitlab.com/devops/p3c.git
project-765

pre-receive 文件内容

#!/bin/bash

# oldrev,上次成功提交的push编号
# newrev,本次push的编号
# committer,当前提交代码的用户
# EJECT=0,通过

export JAVA_HOME=/usr/local/jdk-18
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

# 命令结果状态
REJECT=0
# 代码检测库
PMD_LIB=/var/opt/gitlab/gitlab-hooks/p3c-pmd-2.1.0-jar-with-dependencies.jar
# 检测结果国际化语言:en、zh
PMD_LANGUAGE=zh
# 文件字符编码
FILE_ENCODING=utf-8

# 黑名单判断
# git项目黑名单
GIT_BLACK_LIST='/var/opt/gitlab/gitlab-hooks/git-black-list.txt'
# 判断项目是否在黑名单内
IS_GIT_BLACK_LIST=`/usr/bin/grep -nw "${GL_REPOSITORY}" $GIT_BLACK_LIST`

# 白名单判断
# git项目白名单
GIT_WHITE_LIST="/var/opt/gitlab/gitlab-hooks/git-white-list.txt"
# 判断项目是否在白名单内
IS_GIT_WHITE_LIST=`/usr/bin/grep -nw "${GL_REPOSITORY}" $GIT_WHITE_LIST`
# 特权用户名单
USER_WHITE_LIST="/var/opt/gitlab/gitlab-hooks/user-white-list.txt"
# 判断是否属于特权用户
IS_USER_WHITE_LIST=`/usr/bin/grep -nw "${GL_USERNAME}" $USER_WHITE_LIST`

# 判断项目是否在黑名单内
if [ -n "$IS_GIT_BLACK_LIST" ]; then
  # 输出本次push的信息
  echo "开始进行代码质量检测..."
  echo "项目编号:${GL_REPOSITORY}"
  echo "提交用户:${GL_USERNAME}"

  # 获取标准输入
  while read oldrev newrev refname; do
    #echo "oldrev is ${oldrev}"
    #echo "newrev is ${newrev}"
    #echo "refname is ${refname}"

    # 如果没有上次成功的push,则给oldrev赋一个初始值
    if [ "$oldrev" = "0000000000000000000000000000000000000000" ];then
        oldrev="${newrev}^"
    fi
    # 执行git命令,获取两次提交中有差异的*.java文件
    files=`git diff --name-only ${oldrev} ${newrev}  | grep -e ".java$"`
    # 判断是否检测到有差异的*.java文件
    if [ -n "$files" ]; then
      # echo "开始bbb"
      # 定义临时目录
      TEMPDIR="tmp"
      # 将有差异的文件复制到临时目录下
      for file in ${files}; do
        mkdir -p "${TEMPDIR}/`dirname ${file}`" > /dev/null
        git show $newrev:$file > ${TEMPDIR}/${file}
      done;

      # 对临时目录中的文件执行p3c-pmd检测
      java -Dfile.encoding=$FILE_ENCODING -Dpmd.language=$PMD_LANGUAGE -cp $PMD_LIB net.sourceforge.pmd.PMD -d $TEMPDIR -R /var/opt/gitlab/gitlab-hooks/rulesets/java/all-rule.xml,/var/opt/gitlab/gitlab-hooks/rulesets/java/add-rule.xml -f text -shortnames -no-cache
      # 获取检测结果,0代表通过
      REJECT=$?
      echo "reject = "$REJECT
      # 判断检测结果是否通过
      if [ $REJECT = 0 ] ;then
        echo "码出高效!您的代码通过阿里巴巴Java开发规范(黄山版)检测!"
      # 判断用户是否在白名单内,若在,则将检测结果改为通过
      elif [ -n "$IS_USER_WHITE_LIST" ]; then
        echo "特权用户,允许提交!"
        REJECT=0
      # 判断项目是否在白名单内,若在,则将检测结果改为通过
      elif [ -n "$IS_GIT_WHITE_LIST" ]; then
        echo "特殊项目,允许提交!"
        REJECT=0
      else
        echo  "在您的代码中发现了瑕疵,请及时修复,然后再提交!(代码规范请参考:https://github.com/alibaba/p3c)"
      fi
      # 删除临时目录,释放磁盘空间,防止污染下次检测
      rm -rf $TEMPDIR
    else
      echo "本次提交无需检测"
    fi
  done
fi
# 将检测结果作为脚本的返回码
exit $REJECT

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30769.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信