Sonarqube

一、简介

SonarQube 是一种自动代码审查工具,用于检测代码中的错误、漏洞和代码异味。它可以与您现有的工作流程集成,以实现跨项目分支和拉取请求的持续代码检查

二、组成

Sonar主要由sonar-scanner、sonar-server两个部分组成

sonar-scanner作用主要是负责代码扫描
sonar-server作用是负责sonar web展示工作、数据库交互工作、扫描计算工作、规则存储工作、第三方插件打通等

Sonar scanner cli源码

一、地址

  • GitHub:https://github.com/SonarSource/sonar-scanner-cli

二、底层

  1. 执行org.sonarsource.scanner.cli.Main类下的主函数,并打入对应的环境变量

主要分为三块方法执行:
main():创建初始化部分对象
execute():扫描初始化,初始化properties、初始化sonar版本及下载sonar-scanner-engine-.jar
execute(Stats stats, Properties p):将扫描功能交由sonar-scanner-engine-
.jar,开始代码扫描

public class Main {
  //...

  //主启动函数入口,先创建,初始化部分对象
  public static void main(String[] args) {
    Logs logs = new Logs(System.out, System.err);  //创建一个简单的日志输出对象,还未到初始化配置对象内容  
    Exit exit = new Exit();  //#创建Exit对象,功能是扫描完成后退出jar运行
    Cli cli = new Cli(exit, logs).parse(args);  //#Cli对象负责将启动配置属性args初始化
    // #Main对象为代码扫描执行入口
    Main main = new Main(exit, cli, new Conf(cli, logs, System.getenv()), new ScannerFactory(logs), logs);
    main.execute();  
  }
  
  //扫描执行前的初始化,及执行扫描功能
  void execute() {
    Stats stats = new Stats(logger).start();  //扫描状态量标识
    int status = Exit.INTERNAL_ERROR;
    try {
      Properties p = conf.properties();
      checkSkip(p);  
      configureLogging(p);  //配置日志属性
      init(p); //初始化sonar版本信息
      /**
        * 划重点
        * embeddedScanner.start();扫描前置准备工作,内部调用doStart()
        * doStart()作用:
        * 1.会初始化http clinet对象用于执行http请求(ServerConnection)
        * 2.通过http请求调用/batch/index接口下载sonar-scanner-engine-shaded-9.5-SNAPSHOT-all.jar文件
        * 3.初始化sonar-scanner-engine文件"org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher"类对象
        * 4.初始化BatchIsolatedLauncher对象,主要功能负责代码核心扫描部分
        */
      embeddedScanner.start(); 
      //...
      execute(stats, p); //调用private void execute()方法
      status = Exit.SUCCESS;
    } catch (Throwable e) {
      //...
    } finally {
      exit.exit(status); //扫描完成退出jar运行环境
    }
  }
  
  //执行代码扫描入口
  private void execute(Stats stats, Properties p) {
    embeddedScanner.execute((Map) p); //执行扫描
    displayExecutionResult(stats, "SUCCESS");
  }
}

三、cli执行图

在这里插入图片描述

Sonar scanner engine源码

一、前言

通过sonar-scanner-cli源码,最终会调用BatchIsolatedLauncher.execute()方法来创建Batch对象来执行扫描

二、扫描流程

  1. 首先Batch.exeute()会创建一个GlobalContainer对象去执行扫描
    在这里插入图片描述

  2. GlobalContainer.execute()会先后去执行doBeforeStart() pico.start() doAfterStart()

  1. doBeforeStart()主要作用打入对应的插件【全局配置类、部分工厂类、插件库类等】、及传入的this.components插件类

  2. pico.start()将打入的插件通过picocontainer框架【轻量级IOC容器框架】,进行实例化

  3. doAfterStart()执行new ProjectScanContainer(this).execute();将能力交给ProjectScanContainer.execute()执行

在这里插入图片描述

  1. ProjectScanContainer.execute()同样也会去执行doBeforeStart() pico.start() doAfterStart()
  1. doBeforeStart()主要作用打入对应的插件【扫描组件类:rules、file、issue、metric等】、及传入的this.components插件类

  2. pico.start()将打入的插件通过picocontainer框架【轻量级IOC容器框架】,进行实例化

  3. doAfterStart()执行扫描核心操作包括两块,见下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oQEDwHUx-1655177155816)(study.assets/image-20220614110043854.png)]

核心操作一内容

  1. doAfterStart().scanRecursively(tree, tree.root())核心操作一,遍历被扫描项目下所有模块,然后各自初始化一个ModuleScanContainer对象去执行

1.ModuleScanContainer.doAfterStart() 会执行ModuleSensorsExecutor.execute()将能力交由ModuleSensorsExecutor(模块传感执行器)

2.ModuleSensorsExecutor来记录命中的语言、文件及配置

在这里插入图片描述

核心操作二内容

  1. getComponentByType(ProjectSensorsExecutor.class).execute();通过项目传感执行器ProjectSensorsExecutor分析被扫描项目源文件数据

  2. getComponentByType(CpdExecutor.class).execute();通过CpdExecutor执行器来讲扫描的结果数据进行分析计算(包括聚合)

1.该操作会调用CpdExecutor.runCpdAnalysis()方法将扫描计算结果生成一个reportxxx.zip文件

2.然后调用CpdExecutor.saveDuplications()将生成的报告文件写入ReportPublisher对象中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pHz55sZv-1655260129434)(study.assets/(null)]-20220615095735306.(null))

  1. getComponentByType(ReportPublisher.class).execute();将步骤6写入的报告读取出来,调用api/ce/submit接口叫报告上传ce server中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WDtigdiB-1655260129437)(study.assets/(null)]-20220615095735411.(null))

  1. Ce server收到接口调用会在ce_task_input表插入一条数据,且input_data通过字节流方式存放上传的报告

  2. 而后会在ce_queue中插入一条数据该数据会被ce server队列线程取出分析并将结果存入DB中

Ce server计算是通过线程异步的方式操作的,详情可查看CeWorkerImpl类实现的内容

  1. CeWorkerImpl.class 有个内部类ExecuteTask,主要通过异步执行的方式将结果打入监听器中计算

  2. 报告计算方式是交由ReportTaskProcessor.process()去完成

三、Container能力图

  1. GlobalContainer.execute()内部会去创建 ProjectScanContainer对象,将能力交由ProjectScanContainer
  2. ProjectScanContainer.execute()内部会调用 ModuleScanContainer来分析被扫描项目的结构,文件,配置及命中扫描语言

真正执行扫描分析的是通过ProjectScanContainer.execute()为入口去实现的

在这里插入图片描述

四、整体扫描流程图

在这里插入图片描述

Jenkins sonar scanner

一、安装

Jenkins安装sonar-scanner插件,会在该机器下生成sonar-scanner-${version}-linux目录

目录下分为bin、config、jre、lib四个子目录
bin:存放sonar-runner脚本执行文件
config:存放sonar-project.properties配置文件
Jre:存放sonar-scanner jar包的运行环境
Lib:存放sonar-scanner jar包做扫描执行

在这里插入图片描述

二、执行

  1. Jenkins- job配置需要拉取对应仓库的源码地址
    在这里插入图片描述

  2. Jenkins- job配置,安装sonar-scanner插件可在Jenkins job 构建项选中execute sonarqube scanner配置指定内容
    在这里插入图片描述

  3. 配置完成后,执行Jenkins job查看日志,分析运行流程

先拉取仓库代码到指定目录,在执行sonar-scanner shell脚本来启动代码扫描

在这里插入图片描述

  1. Sonar-scanner shell脚本,Jenkins安装的sonar-scanner目录下${sonar-scanner}/bin/sonar-runnner

该脚本运行内容:
A. 将${sonar-scanner}/config/sonar-scanner.properties配置文件内容打入环境变量

B. 启动sonar-scanner-*/lib/sonar-scanner-cli-${version}.jar 执行扫描
C. 执行org.sonarsource.scanner.cli.Main类下的主函数,并打入对应的环境变量

在这里插入图片描述

Sonar-server源码

一、地址

GitHub:https://github.com/SonarSource/sonarqube

二、安装

  1. 由于9.5版本对应的JDK版本11,所以idea需要绑定JDK11的编译环境

  2. idea 设置build tools对于gradle版本对应的jdk要选择jdk11
    在这里插入图片描述

  3. 项目结构jdk也选择11版本
    在这里插入图片描述

  4. 项目根目录build.gradle文件修改以下配置

  repositories {
    mavenCentral()
    def repository = project.hasProperty('qa') ? 'sonarsource-qa' : 'sonarsource'
    maven {
      url "https://repox.jfrog.io/repox/${repository}"
    }
  }

5… 然后进行gradle项目构建下载依赖包,或者根目录执行./gradlew build命令

三、启动

a.脚本方式
  • 根目录下start.sh,本质是执行/sonar-application/build/distributions/sonarqube-9.5-SNAPSHOT/bin/macosx-universal-64/sonar.sh该脚本文件
  • 根目录下的build.sh,本质是执行根目录start.sh脚本文件
  • sonar-application目录下的sonar.sh,主要内容是启动sonar服务
b.源码启动
  1. 启动入口为sonar-application模块下的App.java类启动
  2. 该启动类指向的homeDir目录为sonar-application/build/classes

1.需要将sonar-application/build/conf 目录拷贝到sonar-application/build/classes
2.需要将sonar-application/build/conf/elasticsearch 目录拷贝到sonar-application/build/classes
3.需要将sonar-application/build/conf/lib 目录拷贝到sonar-application/build/classes
4.需要将sonar-application/build/conf/web 目录拷贝到sonar-application/build/classes
以上目录不移动获取会导致homeDir找不到该目录下的内容而报错,退出执行

  1. 启动成功后jdbc默认使用H2数据库,用户名密码为空,不设置即可
  2. org.sonar.process.ProcessProperties 包含了启动默认配置项
  3. App.java类启动代码解释
//cliArguments启动参数不填任何内容
public void start(String[] cliArguments) { 
  AppSettingsLoader settingsLoader = new AppSettingsLoaderImpl(System2.INSTANCE, cliArguments, new ServiceLoaderWrapper());
  //会加载org.sonar.process.ProcessProperties 属性配置想进行加载
  AppSettings settings = settingsLoader.load();
  
  // ...

  try (AppState appState = new AppStateFactory(settings).create()) {
      //...
      
      //这个方法会启动es、web、ce【重点内容,建议多看】
      scheduler.schedule();

      
      //...
}

四、模块

  • sonar-application sonar启动入口
  • sonar-check-api. sonar校验自定义注解封装
  • sonar-duplications 提供复制副本相关功能代码封装
  • sonar-core sonar一些共享的功能封装
  • sonar-markdown. sonar部分数据格式化成markdown格式
  • sonar-plugin-api、sonar-plugin-api-impl、sonar-testing-sarness、sonar-testing-ldap 提供sonar单元测试及断言器
  • sonar-scanner-engine sonar静态代码扫描引擎
  • sonar-scanner-engin-sharde 提供给sonar-scanner代码扫描是用的jar【执行静态代码扫描sonar-scanner源码会下载这个jar】
  • sonar-shutdowner 关闭所有sonar相关的服务进程
  • sonar-ws 提供sonar 后端所有请求接口的入口类,等同于controller【该请求会执行到sonar-webserver-webapi调用其执行器service层】
  • sonar-ws-generator 调试类
  • ut-monitoring. 提供监控相关aop功能类
  • server. sonar主要核心功能实现的模块
server子模块
  • sonar-alm-clinet 提供ALM集成功能客户端,在web前端配置->通用设置体现
  • sonar-auth-bitbucket 提供是bitbucket授权认证功能【bitbucket源码托管网站类似于gitlab、github】
  • sonar-auth-common 提供oauth2.0客户端身份认证功能【oauth2.0功能类似于jet】
  • sonar-auth-github 提供GitHub客户端身份认证功能
  • sonar-auth-gitlab 提供GitHub客户端身份认证功能
  • sonar-auth-ldap 提供ldap客户端身份认证功能
  • sonar-auth-saml 提供saml客户端身份认证功能【SAML,全称为Security Assertion Markup Language,是一种用于安全性断言的标记预压,作用于单点登录】
  • sonar-ce 计算JVM的模块应用,具备监听与调度功能
  • sonar-ce-common 计算引擎和Web服务器共享的计算引擎相关的代码
  • sonar-ce-task 计算引擎任务和实用工具的“框架”和类编码
  • sonar-ce-task-analysis 计算引擎任务处理项目分析报告的代码
  • sonar-db-core sonar与多种数据库实现代码
  • sonar-db-dao sonar与数据库交互实现层
  • sonar-db-migration 不同版本发布数据迁移类实现
  • sonar-main sonar应用主启动封装的一些主要类【非启动入口】
  • sonar-process sonar启动进程管理实现类【es、java、日志等】
  • sonar-server-common sonar Web服务器和ce(计算引擎)之间共享的代码
  • sonar-web 纯前端【ts、js、html】
  • sonar-webserver sonar后端内置tomcat服务
  • sonar-webserver-api SonarQube WebServer内部api,用于其他WebServer模块或核心扩展
  • sonar-webserver-auth 后端对用户请求身份认证
  • sonar-webserver-core 后端服务一些核心功能的封装
  • sonar-webserver-es 后端对于es查询相关的查询条件封装
  • sonar-webserver-monitor 后端任务监控
  • sonar-webserver-webapi 后端请求代码实现层【等同于spring服务service层】,主要跟dao类交互获取数据返回response
  • sonar-webserber-pushapi 静态代码扫描数据提交的API接口
  • sonar-webserber-ws web服务器请求拦截器、过滤器封装
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐