参考链接:

PS:

  • Sonarqube自带了轻量级的H2数据库,测试和跑少量项目是没有问题的。基于后期的性能、运维、扩展等考虑,我们选择使用Mysql数据库。
  • Sonarqube自带了web server,也可以使用Tomcat来进行加载。基于以往的使用经验默认的web server足够使用,我们选择默认。

搭建环境

  • OS: Windows Server 2012 R2
  • JDK: 1.8.0_71
  • DB: Mysql 5.6.26
  • Sonar: 6.3.1

搭建步骤

  1. 安装JDK

    1
    2
    3
    4
    C:\Users\Administrator>java -version
    java version "1.8.0_71"
    Java(TM) SE Runtime Environment (build 1.8.0_71-b15)
    Java HotSpot(TM) 64-Bit Server VM (build 25.71-b15, mixed mode)
  2. 安装Mysql

    1
    2
    C:\Users\Administrator>mysql -V
    mysql Ver 14.14 Distrib 5.6.26, for Win64 (x86_64)
  3. 创建数据库和用户

    1
    2
    3
    4
    5
    6
    7
    8
    # 创建sonar数据库
    CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci;
    # 创建sonar用户
    CREATE USER 'sonar' IDENTIFIED BY 'passwd';
    # 赋予sonar用户对sonar数据库权限
    GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'passwd';
    GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'passwd';
    FLUSH PRIVILEGES;
  4. 安装Sonarqube

    • 解压缩sonarqube-6.3.1.zip到D:\scm\sonarqube-6.3.1

    • 修改配置D:\scm\sonarqube-6.3.1\conf\sonar.properties

      • sonar.jdbc.username=sonar
      • sonar.jdbc.password=passwd
      • sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance
      • sonar.web.host=本机IP
      • sonar.web.context=
      • sonar.web.port=9000
      • sonar.web.http.maxThreads=500
    • 配置Sonarqube windows服务

      1. 以管理员身份运行D:\scm\sonarqube-6.3.1\bin\windows-x86-64\InstallNTService.bat创建服务
        logo
      2. 配置Administrator账户运行Sonarqube服务
        logo
      3. 启动Sonarqube服务
        • 建议使用上面配置的windows service启动
        • 也可以直接运行D:\scm\sonarqube-6.3.1\bin\windows-x86-64\StartSonar.bat
  5. 网页端登陆配置Sonarqube

    • http://搭建机器ip:9000
    • 用户名/密码:admin

PS1:

在安装的过程中遇到问题:

  • 运行InstallNTService.bat生成系统服务的时候没有使用管理员身份;
  • Sonarqube服务创建成功,但是启动的时候失败;
    1
    2
    3
    4
    2017.06.20 14:34:50 ERROR web[][o.a.c.c.C.[.[.[/]] Exception sending context initialized event to listener instance of class org.sonar.server.platform.web.PlatformServletContextListener
    org.sonar.api.utils.MessageException: Current version is too old. Please upgrade to Long Term Support version firstly.
    2017.06.20 14:34:50 ERROR web[][o.a.c.c.StandardContext] One or more listeners failed to start. Full details will be found in the appropriate container log file
    2017.06.20 14:34:50 ERROR web[][o.a.c.c.StandardContext] Context [] startup failed due to previous errors
  • 查看发现mysql数据库sonar已经有了很多表;

解决方法:

  1. 删除sonar数据库里面的表,删除Sonarqube服务
  2. 安装上面过程:先以管理员身份运行InstallNTService.bat,然后配置Administrator账户运行Sonarqube服务
  3. 重新启动Sonarqube服务即可。

PS2:

如果Mysql数据库启用了binarylog的话,请设置为row格式。否则在启动Sonarqube的时候创建数据库表会报下面错误:

1
2
Error updating database.  Cause: java.sql.SQLException: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.

Comment and share

参考链接:


静态代码分析:

  • 定义:不运行计算机程序的条件下,进行程序分析的方法。
  • 目的:验证代码是否满足规范性、安全性、可靠性、可维护性等指标,发现代码缺陷并提高代码的质量。
  • 范围:源代码(主要)、编译产生的字节码。
  • 常用技术:
    • 词法分析:通过正则表达式匹配将源代码转换成标记序列。
    • 语法分析:判断源程序结构上是否正确,通过使用上下文无关语法将相关符号整理为语法树。
    • 语义分析:对结构上正确的源程序进行上下文有关性质的审查。
    • 抽象语法树:将程序组织成树形结构,树中相关节点代表了程序中的相关代码。
    • 控制流分析:生成有向控制流图,用节点表示基本代码块,节点间的有向边代表控制流路径,反向边表示可能存在的循环;还可生成函数调用关系图,表示函数间的嵌套关系。
    • 无效代码分析:根据控制流图可分析孤立的节点部分为无效代码。
      数据流分析:对控制流图进行遍历,记录变量的初始化点和引用点,保存切片相关数据信息。
    • 污点分析:基于数据流图判断源代码中哪些变量可能受到攻击,是验证程序输入、识别代码表达缺陷的关键。
    • 缺陷模式匹配:缺陷模式匹配事先从代码分析经验中收集足够多的共性缺陷模式,将待分析代码与已有的共性缺陷模式进行模式匹配,从而完成软件的安全分析。

Java开源静态代码分析工具对比:

工具 源代码分析 字节码分析 定位 官网地址 版本 其它语言支持
Checkstyle Y 验证符合编码规则 http://checkstyle.sourceforge.net 7.8.2(2017.6.18)
FindBugs Y 发现Bugs http://findbugs.sourceforge.net 3.0.1(2015.3.6)
PMD Y 发现缺陷 https://pmd.github.io 5.8.0(2017.6.24) Y
Sonarqube Y Y 持续质量平台 https://www.sonarqube.org 6.3.1(2017.4.12) Y

PS:

1
2
3
4
5
6
7
最初Sonarqube只是做静态代码分析结果聚类展示。
后来随项目的发展,考虑到静态代码分析工具发展的不可控性(毕竟不属于自身项目),Sonarqube开始也涉及静态代码分析。
在此过程中,Sonarqube借鉴了Checkstyle、FindBugs、PMD的规则方法。
所以,本篇所指的Sonarqube既包含静态代码分析SonarJava(主要)又包含结果展示。
以上参考下面链接:
https://groups.google.com/forum/#!topic/sonarqube/9M0iZ4OILVM
https://blog.sonarsource.com/sonarqube-java-analyzer-the-only-rule-engine-you-need/

Checkstyle:

官网:检查规则

主要涉及以下几个方面:

  • 注解
  • javadoc注释
  • 命名规范
  • 文件头
  • 导入包规范
  • 尺寸设置
  • 空格
  • 正则表达式
  • 修饰符
  • 代码块
  • 编码问题
  • 类设计问题
  • 重复、度量以及一些杂项

FindBugs:

官网:检查规则

主要涉及以下几个方面:

  • Multithreaded correctness - 如多线程编程时常见的同步、线程调度问题。
  • Performance - 如由变量定义、方法调用导致的代码低效问题。
  • Internationalization - 如错误的字符串转换带来的国际化问题。
  • code vulnerabilities - 可能受到的恶意攻击,如访问权限修饰符的定义等。
  • possible bugs - 可能导致错误的代码,如空指针引用,常见代码错误,序列化错误。
  • Bad practice - 如命名不规范(类名应以大写字母开头),没有finally来关闭IO流,不检查方法返回值等。
  • Correctness - 正确性问题,如instanceof永远返回false。

PMD:

官网:Java检查规则

主要涉及以下几个方面:

  • Possible bugs - empty try/catch/finally/switch statements
  • Dead code - unused local variables, parameters and private methods
  • Suboptimal code - wasteful String/StringBuffer usage
  • Overcomplicated expressions - unnecessary if statements, for loops that could be while loops
  • Duplicate code - copied/pasted code means copied/pasted bugs

Sonarqube

官网:Java检查规则

主要涉及以下几个方面:

  • Bugs
  • Vulnerability
  • Code Smell

VS:

规则覆盖:

  • 目前Sonarqube自带的SonarJava插件检查规则几乎包含了Checkstyle、FindBugs、PMD的规则。
  • 在具体的一些问题上面,几款工具各有千秋。
  • 存在同一个问题几款工具分别对其进行不同标注情况。

结果输出展示:

  • Checkstyle、FindBugs、PMD 运行结果输出支持Xml和Html格式。
  • Sonarqube 运行结果存入数据库,web端展示。支持和上次结果对比。可视化做的很赞!

工具更新:

  • FindBugs已经很久不更新了。
  • Checkstyle、PMD、Sonarqube更新频率都挺高的。

检查范围:

  • FindBugs 只对编译产生的class文件进行检查
  • Checkstyle、PMD 只对源代码进行插件
  • Sonarqube:
    • 对于所有支持的编程语言,SonarQube 都提供源了代码的静态分析功能;
    • 对于某些特定的编程语言,SonarQube 提供了对编译后代码的静态分析功能,比如 java 中的 class file 和 jar 和 C# 中的 dll file 等;
    • 对于某些特定的编程语言,SonarQube 还可以提供对于代码的动态分析功能,比如 java 和 C# 中的单元测试的执行等。

结论:

  • 推荐使用Sonarqube来进行Java代码静态扫描。
  • 自带的SonarJava插件规则已经够用,建议直接上手使用。
  • 在使用过程中可以补充Checkstyle、FindBugs、PMD相应规则到Sonar检查。

Comment and share

分支策略

in SCM

背景:

为了更好的支持产品研发过程,我们需要设计符合公司研发的分支策略。
无论多复杂或者简单的策略都可以归类为以下两种:

1.主干开发,分支发布
2.分支开发,主干发布

PS:我们约定:

主干(master/git trunk/svn)
分支(branch)
标签(tag)
如果从版本控制工具实现上来看:
svn: trunk、branch、tag 没有差别
git: master、branch、轻量级tag 没有差别
为了更好的区分和管理,人为的从逻辑上进行区分
tag的作用:里程碑记录,方便回溯(发布回滚等)

主干开发,分支发布:

logo

  • 优点:
    1. 较少的分支存在,大家专注在主干开发
  • 适用于:
    1. 敏捷开发模式,每个迭代都很快
    2. 维护型项目,较少需求变更,基本没有并行开发的需要
    3. 个人项目
  • 常用方式:
    1. 所有dev在主干上面进行开发
    2. 需要发布的时候从指定版本拉出发布分支,进行测试
      • 如果成功:那么打出tag,进行发布
      • 如果不成功:那么继续在发布分支上面进行修改,然后测试;
        测试成功后,打tag,合并发布分支修改到主干;

分支开发,主干发布:

logo

  • 优点:
    1. 对并行开发支持很好
  • 适用于:
    1. 并行开发很频繁的项目
  • 常用方式:
    1. 根据项目发布排期拉出并行开发分支
    2. 不同or相同的dev分别在分支上面进行开发
    3. 测试通过后,打tag进行发布,合并分支修改到主干
    4. 后发布的分支需要合并最新的主干代码
  • 注意点:
    1. 所有分支都从主干拉出;
    2. 发布时候要检查 tag是否包含最新的主干代码;
    3. 后发布的分支在合并最新主干代码后,注意测试范围扩大(除了测试本分支功能外,合并过来的功能也需要覆盖到!!!)

PS:

本文只是简单介绍下基础的分支策略,各位需根据自身团队、业务来综合定制适合的分支策略。

Comment and share

Gerrit code review

in SCM

背景

公司使用Gerrit作为代码托管平台。
Gerrit除了设置项目权限外,还提供了很好的code review功能。
下面分别简单介绍普通Git用法和code review用法

普通Git使用方法:

logo

如上图所示:

Git仓库主要分为:本地仓库(各位clone到本机)和远端仓库(scm负责维护的,搭建在一台服务器上面);

绝大多数的命令都不需要和远端的git仓库打交道,本地执行即可;

1
2
3
4
git clone :克隆一个远端git仓库到本地
git fetch:获取远端git仓库变化到本地仓库,并不会更改当前工作区文件
git pull:这个命令相当于:先执行git fetch 然后执行git merge变化到当前工作区
git push:将本地仓库的变化推送到远端git服务器

Code Review使用方法:

logo

如上图所示:
使用Gerrit进行code review一言蔽之就是Gerrit加了个中间层;
本地仓库的变更执行git push提交到Gerrit;code reviewer可以在gerrit上面对本次提交进行review并给出评价;
logo
管理员在review评估ok(至少有一个+2)后,在gerrit上面点击submit,会把本次变更推送到远端仓库。

PS:+1 +2 -1 -2 0不是数字意义!!!(两个reviewer都给了+1评论并不代表已经+2了)

原理解析:

为了实现上面所说的功能,gerrit引入了change_id和for空间;

我们执行git push到for空间;
如果大家的本地git config没有做过配置,那么咱们执行git push的完整命令是:
git push origin HEAD:refs/heads/master
推送当前本地最新代码到远端(origin)master分支


使用code review的话执行git push完整命令是:
git push origin HEAD:refs/for/master
推送当前本地最新代码到for空间的master分支供gerrit识别

PS:以上写的都是git原始命令供大家更好的理解,实际使用中可以简写!!!


Gerrit根据change-Id识别你的patch;

我们需要引入commit-msg钩子文件到本地代码库:
(这个是gerrit原生提供的通过scp命令实现)
在本地代码库下运行(将weilong.wang改成自己的用户名),执行一次即可
gitdir=$(git rev-parse –git-dir); scp -p -P 29418 weilong.wang@Gerrit_Server_Ip:hooks/commit-msg ${gitdir}/hooks/


commit-msg钩子的作用和使用:
1.Dev正常本地修改代码,git add,git commit 会自动在message后面增加算出一个唯一的change-id
例如: Change-Id: I45088f6b73bf53b62b2ee3b09c005952e9838548
2.如果本次patch提交到gerrit后,review不通过:本地修改代码, git add, git commit –amend
(更新新的修改到当前commit;同时可以修改commit message;不要对message的最后一行change-id做修改!!!)
接着push到gerrit:因为change-id并没有改变,所以还是同一个地方,patch set增长1

PS:建议合并最新版本代码到本地:使用git pull –rebase
如果使用git pull: merge点不自动产生change-id!!!

logo

喜闻乐见简化配置:

根据上面的解释大家应该发现想使用gerrit进行code review还得手工做些事情:

  1. git clone远端代码库到本地
  2. 从远端服务器下载commit-msg钩子到本地仓库.git/hooks/目录
  3. 每次都要本地git commit后执行git push origin HEAD:refs/for/master
  4. 去gerrit上面添加code reviewers
    这并不是我想要的生活。。。

一劳永逸方法:

  1. git clone远端代码库到本地
  2. 从远端服务器下载commit-msg钩子到本地仓库.git/hooks/目录
  3. 修改本地代码库config vi .git/config增加下面内容
    [remote “review_master”]
    url = 代码库地址
    push = HEAD:refs/for/master%r=weilong.wang@memblaze.com,r=dev1@memblaze.com
  4. 本地git commit后执行git push review_master即可
    会自动提交到refs/for/master并增加weilong和dev1作为code reviewers;

PS: remote “review_master” 这个可以换成你喜欢的其他字符串;假如改成remote “haha” 那么最终push的时候执行 git push haha
PS: pushurl这个请自行替换成各位执行git clone的地址
PS: 自动添加code reviewers请自行替换成各位项目的同事

Comment and share

Git tips one

in SCM

软件版本:

1
git version 2.10.1

Git克隆单个分支:

1
2
3
4
5
6
7
8
9
$ git clone 地址 —branch br1 —single-branch dir
只能看到单独的br1,不能checkout到其他分支。空间占用比较小,适合长期分支开发。
原理:
$ git remote -v
remote.origin.fetch=+refs/heads/br1:refs/remotes/origin/br1
恢复完整代码库:
$ git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
然后执行
$ git pull

Git对.gitignore文件处理:

1
2
3
4
5
6
已经增加到.gitignore文件里面的目录or文件会被git忽略。
如果本次需要修改一个忽略文件:
$ git status --ignored
--ignored -- show ignored files as well
$ git add -f
--force -f -- allow adding otherwise ignored files

Git commit相关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 空提交,只在特殊情况下使用(产生一个新的commit点)
$ git commit
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
# 解决方法
$ git commit -m "empty commit" --allow-empty


# 不带message提交(慎用,message很重要)
$ git commit
Aborting commit due to empty commit message.
# 解决方法
$ git commit --allow-empty-message


把暂存区的变更合并到最新的版本里面,不会产生新的版本(同时可以更新log message);
$ git commit --amend
PS:已经进远端代码库的版本不允许使用--amend进行修改!!!

Git merge相关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
conflict处理:
# 使用自己/他人的文件替换冲突文件
$ git checkout --ours conflict.file
$ git checkout --theirs conflict.file
# 增加冲突文件到版本库
$ git add conflict.file
$ git commit


查看merge commit点已经解决的冲突文件:
$ git log --cc
--cc -- combined diff format for merge commits


分支直接合并建议使用:git merge
同一分支dev合并 or Temp分支合并建议使用:git rebase 或者 git cherry-pick
PS:以上两种都可以合并代码workspace最终文件一样,但是对git来说有不同:merge是环形,rebase和cherry-pick是直线
PS:需要注意的是rebase会是自己和他人角色发生反转,解决conflict file的时候需要留心。

Git rm相关:

1
2
3
4
5
$ git rm weilong.txt
删除workspace和index里面的weilong.txt文件

$ git rm --cached weilong.txt
删除index里面的weilong.txt文件,workspace里面的文件保留

Git log相关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ git log -5
查看最新的5次版本

$ git log --author=weilong.wang
查看weilong.wang提交的版本

$ git log --oneline
一行显示一个版本信息(简化显示版本信息)

$ git log -p
显示每个版本的具体修改

$ git log --numstat
显示每个版本 修改文件的行数(5 1 weilong.txt 这个文件本次增加了5行同时也删除了1行)

$ git log --since="1 month ago"
显示最近一个月的日志
$ git log --after="2016-07-01"
显示7月1号至今的日志
$ git log --before="2 days"
显示2天之前的日志
$ git log --until="2016-07-10T14:30"
显示7月10号14:30之前的日志


$ git log --graph
图状显示版本 (正常提交时线形的,merge是环形的)

可用于判断分支是否合并:
$ git log br1 ^master
显示只在分支br1不在master上的commit点
$ git log master ^br1
显示只在分支master不在br1分支上的commit点

logo

Comment and share

背景:

公司目前使用Gerrit作为代码库托管和Code review平台。 使用Jenkins作为自动化构建和持续集成平台。

流程设计:

logo

  1. Dev本地开发,然后上传patch到gerrit:
  • 同时触发Jenkins CR_Job来做build
  • 增加Code reviewers来做review
  1. 再上述都成功的基础上,reviewer点击+2:
  • 同时触发Jenkins Submit_Job来做build和test:
    • 如果成功,自动合并本次patch到代码库
    • 如果失败,返回-1
  1. Nightly test Job:
  • 每晚20:00触发,获取当前最新的代码进行build和test

测试分级:

  • CR_Job:
    • 获取触发patch的代码,合并最新分支代码,进行build
    • 快速反馈,主要检查patch合并是否有冲突和build是否能跑通
  • Submit_Job:
    • 获取触发patch的代码,合并最新的分支代码,进行build和测试
    • 根据每天代码提交次数来确定时间和test cases
  • Nightly_Job:
    • 获取当前最新代码进行build和test
    • 一般跑12h,第二天早上出测试报告邮件

软件环境:

软件 版本
Jenkins 1.567
Gerrit 2.8.6
  • Jenkins插件:
插件名 版本 作用
Multijob plugin 2.11.1 定义pipeline
Gerrit Trigger 1.13 监控Gerrit event

搭建步骤:

  1. 安装配置Jenkins Gerrit Trigger插件:官方wiki
    logo
  2. 安装Jenkins Multijob plugin:官方wiki
    logo
  3. 配置CR_Job:
    logo
  4. 配置Submit_job:
    logo
  5. 配置Nightly_Job:
    logo

PS

  1. 以上内容都是基于公司研发现状定制的,建议各位根据自己的情况进行定制。
  2. 因为历史遗留原因,当前使用的版本比较旧。 例如如果升级到jenkins2.x版本的话pipeline就不需要借助插件来实现了。

Comment and share

Jenkins常用插件

in SCM

软件版本:

1
jenkins 1.567

Comment and share

Author's picture

Weilong

    Write something about work-life:

PM


Shenzhen