暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Jenkins和SonarQube实战

小甲鱼杂文 2021-03-19
1791

    本文主要介绍SonarScanner在对不同语言项目进行代码扫描时需要注意的一些事项,以及Sonar与Jenkins集成实现项目代码自动化扫描,重点是介绍一种在Jenkins上配置代码扫描的万能方法,该方法既能扫描不同类型的项目(Maven、Gradle、Python、Go、PHP、前端项目)又能够实现多项目并行代码扫描,这样能给开发代码扫描自动化功能带来极大便利,再也不需要考虑不同业务线到底是什么类型的项目了。


这是官网上一张SonarQube使用流程图:

典型的开发过程中:

1、开发人员可以在IDE中集成SonarLint,开发过程中可以提示编码存在的问题;开发完成后将代码合并到git等代码仓库

2、持续集成CI工具(如Jenkins等)可以拉取代码,然后通过集成SonarQube扫描器进行代码扫描,获取代码扫描结果;

3、扫描器将扫描结果发布到SonarQube服务器上,该服务器可以通过SonarQube接口、email、IDE内通知(通过SonarLint)向开发人员提供反馈。


一、Sonar代码扫描平台的组成

Sonar代码扫描由两部分组成:一个是SonarQube数据展示平台(相当于server端)、一个是SonarScanner扫描器(相当于client端)。每个版本的SonarQube(目前最新版本8.7)都有对应版本的SonarScanner扫描器,大家可以官网下载。

1、官网地址:https://docs.sonarqube.org/8.7/

2、SonarQube平台主要用来

—展示所有项目代码扫描结果的质量数据

—配置质量规则、管理项目、配置通知等

3、SonarScanner扫描器主要用来

—专门用例扫描和分析代码的,目前能扫描20多种语言

—首先得配置SonarQube平台的url地址

—代码扫描和分析完成后,会将扫描结果发送给SonarQube,SonarQube做数据汇总存储在SonarQube的数据库(目前新版本支持postgreSql、Oracle、SqlServer,老版本7.9以下支持mysql


二、SonarScanner代码扫描器

    SonarScanner进行代码扫描时,你的代码必须在本地,扫描器不会访问远程代码仓库进行扫描,你必须使用git、svn或者其他手段将远程代码下载到本地,再通过本地的SonarScanner进行扫描。

不同语言开发的项目的需要配置不同的扫描器,目前有Maven、Gradle、.NET和其他 (比如 Go, Python, PHP, ...)

    下面分别以python项目、maven项目、gradle项目为例,分别介绍不同扫描器的注意事项。

1、扫描python项目(go类似)

 1)首先下载下图所示的SonarScanner扫描器,实际就是一个压缩包,解压即可(如下图所示);

2)再修改conf文件夹下sonar-scanner.properties配置文件



3)下载源码,在源码目录新建sonar-project.properties文件,里面添加如下信息


sonar.projectKey=LearDjango     #唯一标识,不同项目key必须不一样,SonarQube展示平台通过key区分不同项目
sonar.projectName=LearDjango #一般与可以相同
sonar.sources=apps/ #指定扫描源码的目录,使用相对路径
sonar.language=python #指定扫描的语言
soar.sourcesEncoding=UTF-8 #编码格式
#更多参数可以参照官网:https://docs.sonarqube.org/latest/analysis/analysis-parameters

4)在项目源码目录运行命令:sonar-scanner即可。等待扫描完成,就可以在SonarQube展示平台看到扫描结果。

注意:

1)如果无法在项目的根目录中创建sonar-project.properties文件,则有以下几种选择替代sonar-project.properties:

—可以直接通过命令行指定属性

sonar-scanner -Dsonar.projectKey=myproject -Dsonar.sources=src1

2)属性project.settings可用于指定项目配置文件的路径(此选项与sonar.projectBaseDir属性不兼容)

sonar-scanner -Dproject.settings=../myproject.properties


2、扫描Maven项目

1)下载apache-maven-3.6.3,直接解压即可

2)在conf目录下的settings.xml下进行配置:包括sonar插件配置、sonarQube平台的url地址等

<settings>
<pluginGroups>
<pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
</pluginGroups>
<profiles>
<profile>
<id>sonar</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<!-- Optional URL to server. Default value is http://localhost:9000 -->
<sonar.host.url>
http://xxx.xxx.xx.xxx:9000
</sonar.host.url>
</properties>
</profile>
</profiles>
</settings>

3)从git上下载源码到服务器

4)在源码pom.xml文件所在目录新建sonar-project.properties文件,文件里需写好扫描的配置内容,需要指定sonar.java.binaries路径

5)必须在服务器上源码目录执行命令:

mvn clean verify sonar:sonar


6)、也可以不用第四步新建文件,可以在第5步指令中配置属性:

mvn clean verify sonar:sonar 
-Dsonar.host.url=http://xxx.xxx.xx.xxx:9000/
-Dsonar.login=admin
-Dsonar.password=admin
-Dsonar.projectKey=my_project1
-Dsonar.projectName=my_project1
-Dsonar.java.binaries=target/classes


3、扫描Gradle项目

1)下载gradle-6.8.3-all

2)从git上下载源码到服务器

3)修改源码目录下build.gradle文件,添加sonarqube插件配置,指定sonarqube服务器地址等

plugins {
id "org.sonarqube" version "3.1.1"
}
sonarqube {
properties {
property "sonar.host.url", "http://localhost:9000"
property "sonar.login", "admin"
property "sonar.password", "admin"
}

4)、Gradle 默认配置了SonarQube properties,不需要我们配置。如果我们非要自定义配置,可以在执行命令时配置,参考第6步;

5)、源码目录执行命令:

gradel sonarqube

6)、也可以在build.gradle不配置sonarqube的属性url、用户名和密码,直接在执行命令时添加

gradel sonarqube -Dsonar.host.url=http://xx.xxx.xxx.xxx:9000/   
-Dsonar.login=admin
-Dsonar.password=admin
-Dsonar.projectKey=my_project1
......


三、Sonar与Jenkins结合实现自动化

这里介绍一种创建代码扫描的万能方法,该方法

—既可以扫描Maven类型项目,又可以扫描Gradle类型项目,又可以扫描Python、Go等类型项目;
—既可以扫描单模块的项目,又可以扫描多模块的项目;
—既可以单任务扫描,又可以多任务并行扫描;


1)Jenkins上配置安装SonarQube Server、Maven、Gradle、SonarQube Scanner。

    在Jenkins“系统管理-》配置-》SonarQube servers”配置SonarQube平台地址;

    在Jenkins“系统管理-》全局工具配置-》Maven/Gradle/SonarQube Scanner”安装工具。注意:这里安装多个SonarQube Scanner,为多项目并行代码扫描做准备




2)选择“新建任务-》构建一个自由风格的软件项目”。当然你也可以通过构建一个“流水线”pipeline项目来实现,这样你需要熟悉pipeline脚本语法规则,可以从官网直接学习一些pipeline的案例。这里介绍构建一种自由风格Job的方式。

3)、在“源码管理”这里配置好git仓库url、用户名和密码、分支。注意这里的既可以填写分支名称也可以填写commitID

4)、因为这里我们需要能够扫描不同类型的项目,所以我们需要条件构建。这里的条件就是我们需要判断不同的项目类型,然后执行不同的扫描配置。由于Maven和Gradle构建的项目需要进行一些配置才能使用扫描器进行扫描,而Python、Go、PHP等不需要配置就可以直接进行代码扫描。那么这里我们就可以分为三个条件判断:Maven项目、Gradle项目、其他项目。

在构建步骤中添加:Condition steps(multiple)。Condition steps(single)和Condition steps(multiple)的区别是当条件满足时一个只能执行一步动作,而一个可以执行多步动作。



5)、条件一:判断Maven项目。判断条件很简单:只需判断工作目录下是否含有pom.xml文件即可。条件判断成功后,只需将项目先编译就行。

注意:扫描器会同时扫描单元测试的代码,如果有单元测试没有通过,会终止整个扫描任务。通过配置如下命令就可以继续执行扫描任务,忽略失败的测试。

-Dmaven.test.failure.ignore=true

6)、条件二:判断Gradle项目。判断条件同样很简单:只需判断工作目录下是否含有build.gradle文件即可。条件判断成功后,先修改build.gradle配置文件,然后直接构建build即可。

id "org.sonarqube" version "2.7"


7)代码扫描。如果这两个条件都不满足,说明是其他项目,直接进行代码扫描即可。

在构建步骤中添加:Execute SonarQube Scanner。配置SonarQube平台名称,JDK版本、扫描器名称、扫描器属性。

注意:

1、sonar.source和sonar.java.binaries都指定为当前源码目录($WORKSPACE是Jenkins内置环境变量),因为不同项目的代码和编译构建后的class目录都不一致,有的源码在src/main下,有的构建后目录在target/classes,但是不同项目均不一致,故都指定为当前源码目录,这样扫描器就会从当前源码目录自动查找。

2、并行扫描。如果是多个Job并行扫描,这里可以配置不同的扫描器名称,让多个扫描器同时扫描,减少扫描时间。


四、参数化构建

    如果想通过一个Job就可以拉取不同项目的代码,可以把git仓库的地址和分支实现参数化构建,可以添加不同类型的参数,然后使用${参数名}动态获取参数

五、Pipeline示例

    这里列举一个简单的Pipeline的示例,具体语法可以参考Jenkins官网,这里就不作详细解释了。

pipeline{
agent any
stages {
stage('拉取代码') {
steps{
script {
def scmVars = checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'XXXX-XXX-XXX-XX-XXXX', url: 'git@XXXXXXXXX.git']]])
commit="${scmVars.GIT_COMMIT}"
}
}
}
        stage('mvn构建') {
steps{
sh label: '', script: 'mvn clean install -Dmaven.test.failure.ignore=true'
}
}
stage('sonarqube代码扫描') {
steps {
script {
def sonarqube = "true"
                     //这个是安装到sonarscaner插件到名字
scannerHome = tool 'SonarQubeScanner1'
echo "$sonarqube"
                    if (sonarqube == "true") {
//提交到哪个环境分析
withSonarQubeEnv('SonarQube189') {
sh "${scannerHome}/bin/sonar-scanner"
}
} else {
echo "未进行代码扫描"
}
}
}
}
}
}


文章转载自小甲鱼杂文,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论