静态代码检测配置及集成应用说明

2025/4/24 sonarqubegitlabgitlab-runner

# SonarQube 与 GitLab 集成使用说明

以下为开发环境提交检查(Dev 分支)与目标分支合并检测(Test 分支/MR)的配置说明,涵盖前后端项目。


# 一、前置条件

  1. SonarQube 服务

    • 确保已生成项目对应的 PROJECTKEYPROJECTNAME,在 SonarQube 界面中创建同名项目。
    • 在 GitLab 的 Settings > CI/CD > Variables 中添加以下变量:
      SONAR_HOST_URL = http://192.168.0.184:9000/  # SonarQube 服务地址
      SONAR_TOKEN = fd366e29270da8873b9d4477a781e7ee982aa2ba         # SonarQube 用户令牌
      # 已在公司gitlab上全局配置,不用管
      
  2. GitLab Runner 环境

    • 确保 Runner 标签(如 build)与任务匹配,且已激活。
    • Java/Node 镜像需包含 gitmvn/npmsonar-scanner 命令行工具。
    • 已配置,不用管!
  3. GitLab Runner 环境

    • 找到需要检测的代码仓库->设置->runner 点击在此项目启动

      image-20250424上午115925595

      image-20250424上午115948621


# 二、配置说明

# 1. 后端(Java)项目配置(.gitlab-ci.yml)

# 开发环境检查(Dev 分支)

  • 关键字段说明

    # 项目变量(需修改)
    variables:
      PROJECTKEY: "srm:service-auth"        # 替换为实际 SonarQube 项目 Key 前缀换成以项目简称命名例如:bdscm-service-auth
      PROJECTNAME: "产品SRM:service-auth"   # 替换为 SonarQube 显示名称 前缀换成以项目简称命名例如:白帝-service-auth
    only:
      - dev                                 # 仅 dev 分支提交触发 这个需要换成触发的分支
    before_script 中分支操作:
         - |
          if [ -d ".git" ]; then
            echo ".git 目录存在,跳过初始化,直接克隆仓库"
            git clone -b dev --depth=0 --progress "${CI_REPOSITORY_URL}" . # 强制克隆 dev 分支 这个需要换成触发的分支
          else
            echo ".git 目录不存在,初始化仓库"
            git init
            git remote add origin "${CI_REPOSITORY_URL}"
            git fetch
            git checkout -b dev origin/dev                     # 强制克隆 dev 分支 这个需要换成触发的分支
    
  • 完整配置示例: 使用文中提供的后端 .gitlab-ci.yml,确保镜像、缓存路径与仓库结构匹配。

    stages:
      - sonarqube-check
    # SonarQube 检查
    variables:
      PROJECTKEY: "srm:service-auth"
      PROJECTNAME: "产品SRM:service-auth"
    sonarqube-check:
      stage: sonarqube-check
      image: registry.thsrm.com/public/maven:3.6.3-jdk-11
      variables:
        GIT_STRATEGY: none  # 禁用 Runner 的自动克隆
        SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
        GIT_DEPTH: 0
        MAVEN_OPTS: "-Xmx512m"
      cache:
        key: "${CI_JOB_NAME}"
        paths:
          - ~/.m2/repository
      before_script:
        - echo "=== 清理缓存 ==="
        - rm -rf "${CI_PROJECT_DIR}" || true
        - mkdir -p "${CI_PROJECT_DIR}"
        - cd "${CI_PROJECT_DIR}"
        - |
          if [ -d ".git" ]; then
            echo ".git 目录存在,跳过初始化,直接克隆仓库"
            git clone -b dev --depth=0 --progress "${CI_REPOSITORY_URL}" .
          else
            echo ".git 目录不存在,初始化仓库"
            git init
            git remote add origin "${CI_REPOSITORY_URL}"
            git fetch
            git checkout -b dev origin/dev
          fi
        - git log --oneline -n 5 # 打印最近5个提交确认完整历史
        - git branch -v
        # 可选:确保子模块存在(如需)
        - git submodule update --init --recursive
        - git checkout -qf "${CI_COMMIT_SHA}"  # 精确切换到当前 commit
        - git branch -v
        - git rev-parse HEAD   # 强制校验当前提交有效性
        - git log --oneline -n 5 # 打印最近5个提交确认完整历史
      script:
        - pwd
        - mvn -v
        - mvn clean install -Dmaven.test.failure.ignore=true org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184:sonar -Dsonar.java.binaries=target/classes -Dsonar.projectKey=$PROJECTKEY -Dsonar.scm.disabled=true -Dsonar.projectName=$PROJECTNAME
      allow_failure: true
      only:
        - dev
    

    image-20250424下午20336470

    image-20250424下午20247306

    image-20250424下午20551562

    1,在对应分支下仓库下,新建.gitlab-ci.yml 文件 将上述示例配置示例copy进行并对关键字段修订后提交
    2,.gitignore文件增加gitlab-ci.yml忽略,防止误操作
    3,以上操作完成后,在对应分支提交后会触发扫描,可观察扫描结果,扫描结束后登录SonarQube网站查看扫描结果


# 目标分支合并检测(Test 分支/MR)

  • 关键变更点

    variables:
      PROJECTKEY: "srm:service-ai"          # 按合并目标服务名修改
      PROJECTNAME: "产品SRM:service-ai"     # 同步更新名称
    only:
      refs:
        - merge_requests                    # MR 触发
        - test                              # 直接推送到 test 分支触发
    before_script 中分支操作:
      git clone -b test                     # 拉取 test 分支
    
  • 完整示例

    stages:
      - sonarqube-check
    # SonarQube 检查
    variables:
      PROJECTKEY: "srm:service-ai"
      PROJECTNAME: "产品SRM:service-ai"
      SONAR_SCAN_ENABLED: "true"  # 默认开启扫描
    sonarqube-check:
      stage: sonarqube-check
      image: registry.thsrm.com/public/maven:3.6.3-jdk-11
      variables:
        GIT_STRATEGY: none  # 禁用 Runner 的自动克隆
        SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
        GIT_DEPTH: 0
        MAVEN_OPTS: "-Xmx512m"
      cache:
        key: "${CI_JOB_NAME}"
        paths:
          - ~/.m2/repository
      before_script:
        - echo "=== 清理缓存 ==="
        - rm -rf "${CI_PROJECT_DIR}" || true
        - mkdir -p "${CI_PROJECT_DIR}"
        - cd "${CI_PROJECT_DIR}"
        - |
          if [ -d ".git" ]; then
            echo ".git 目录存在,跳过初始化,直接克隆仓库"
            git clone -b test --depth=0 --progress "${CI_REPOSITORY_URL}" .
          else
            echo ".git 目录不存在,初始化仓库"
            git init
            git remote add origin "${CI_REPOSITORY_URL}"
            git fetch
            git checkout -b test origin/dev
          fi
        - git log --oneline -n 5 # 打印最近5个提交确认完整历史
        - git branch -v
        # 可选:确保子模块存在(如需)
        - git submodule update --init --recursive
        - git checkout -qf "${CI_COMMIT_SHA}"  # 精确切换到当前 commit
        - git branch -v
        - git rev-parse HEAD   # 强制校验当前提交有效性
        - git log --oneline -n 5 # 打印最近5个提交确认完整历史
      script:
        - pwd
        - mvn -v
        - mvn clean install -Dmaven.test.failure.ignore=true org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184:sonar -Dsonar.java.binaries=target/classes -Dsonar.projectKey=$PROJECTKEY -Dsonar.scm.disabled=true -Dsonar.projectName=$PROJECTNAME
      allow_failure: true
      only:
       refs:
        - merge_requests
        - test  # 也允许直接推送到test分支触发
       		
    

    在test分支配置后,再合并后或者直接提交目标分支,触发扫描机制!


# 2. 前端(Node.js)项目配置(ci.yaml

# 开发环境检查(Dev 分支)

  • 关键字段说明

    variables:
      PROJECTKEY: "srm:admin-view"          # 替换为前端项目 Key
      PROJECTNAME: "产品SRM:admin-view"     # 同步更新名称
    only:
      - dev                                 # 仅 dev 分支触发
    before_script 中分支操作:
      git clone -b dev                      # 拉取 dev 分支
    
  • 关键字段说明

    stages:
      - sonar
    sonarqube-scan:
      stage: sonar
      image: node:14
      variables:
        GIT_STRATEGY: none
        SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
        GIT_DEPTH: 0
        # 显式继承全局变量
        PROJECTKEY: "srm:admin-view"
        PROJECTNAME: "产品SRM:admin-view"
      tags:
        - build
      before_script:
        - echo "=== 清理缓存 ==="
        - echo "正在设置项目名称:" $PROJECTNAME
        - echo "正在设置项目密钥:" $PROJECTKEY
        - rm -rf "${CI_PROJECT_DIR}" || true
        - mkdir -p "${CI_PROJECT_DIR}"
        - cd "${CI_PROJECT_DIR}"
        - |
          if [ -d ".git" ]; then
            echo ".git 目录存在,跳过初始化,直接克隆仓库"
            git clone -b dev --depth=0 --progress "${CI_REPOSITORY_URL}" .
          else
            echo ".git 目录不存在,初始化仓库"
            git init
            git remote add origin "${CI_REPOSITORY_URL}"
            git fetch
            git checkout -b dev origin/dev
          fi
        - git log --oneline -n 5
        - git branch -v
        - git submodule update --init --recursive
        - git checkout -qf "${CI_COMMIT_SHA}"
        - git branch -v
        - git rev-parse HEAD
        - git log --oneline -n 5
        - npm install
      script:
        - >
          sonar-scanner
          -Dsonar.projectKey=${PROJECTKEY}
          -Dsonar.projectName=${PROJECTNAME}
          -Dsonar.host.url=$SONAR_HOST_URL
          -Dsonar.login=$SONAR_TOKEN
          -Dsonar.sources=src
          -Dsonar.exclusions=node_modules/**,dist/**
          -Dsonar.qualitygate.wait=true
          -Dsonar.scm.provider=git
          -Dsonar.sourceEncoding=UTF-8  # 确保中文支持
      cache:
        paths:
          - node_modules/
      only:
        - dev
    

    在dev分支下配置后,提交目标分支,会触发前端扫描机制!


# 目标分支合并检测(Test 分支/MR)

  • 关键变更点

    variables:
      # 保持 PROJECTKEY/PROJECTNAME 与合并后目标分支对应
    only:
      - merge_requests                      # MR 触发
      - test                                # 直接推送到 test 分支触发
    before_script 中分支操作:
      git clone -b test                     # 拉取 test 分支
    # 注意分支一致性:origin/test 对应目标分支
    
  • 完整示例

    stages:
      - sonar
    sonarqube-scan:
      stage: sonar
      image: node:14
      variables:
        GIT_STRATEGY: none
        SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
        GIT_DEPTH: 0
        # 显式继承全局变量
        PROJECTKEY: "srm:admin-view"
        PROJECTNAME: "产品SRM:admin-view"
      tags:
        - build
      before_script:
        - echo "=== 清理缓存 ==="
        - echo "正在设置项目名称:" $PROJECTNAME
        - echo "正在设置项目密钥:" $PROJECTKEY
        - rm -rf "${CI_PROJECT_DIR}" || true
        - mkdir -p "${CI_PROJECT_DIR}"
        - cd "${CI_PROJECT_DIR}"
        - |
          if [ -d ".git" ]; then
            echo ".git 目录存在,跳过初始化,直接克隆仓库"
            git clone -b test --depth=0 --progress "${CI_REPOSITORY_URL}" .
          else
            echo ".git 目录不存在,初始化仓库"
            git init
            git remote add origin "${CI_REPOSITORY_URL}"
            git fetch
            git checkout -b test origin/test
          fi
        - git log --oneline -n 5
        - git branch -v
        - git submodule update --init --recursive
        - git checkout -qf "${CI_COMMIT_SHA}"
        - git branch -v
        - git rev-parse HEAD
        - git log --oneline -n 5
        - npm install
      script:
        - >
          sonar-scanner
          -Dsonar.projectKey=${PROJECTKEY}
          -Dsonar.projectName=${PROJECTNAME}
          -Dsonar.host.url=$SONAR_HOST_URL
          -Dsonar.login=$SONAR_TOKEN
          -Dsonar.sources=src
          -Dsonar.exclusions=node_modules/**,dist/**
          -Dsonar.qualitygate.wait=true
          -Dsonar.scm.provider=git
          -Dsonar.sourceEncoding=UTF-8  # 确保中文支持
      cache:
        paths:
          - node_modules/
      only:
          - merge_requests                      # MR 触发
      		- test  		
    

    在test的分支下配置后,提交test分支或者合并test分支,会触发前端扫描机制!


# 三、操作流程

# 扫描策略定义

根据项目情况是开启提交检查 还是合并检查。集中开发型项目建议开启合并检查,项目后期或改动点不多的项目开启提交检查

# 开发环境提交检查(Dev 分支)

  1. 推送代码到 Dev 分支
    git push origin dev
    
  2. 流水线自动触发
    • 执行 SonarQube 扫描,结果同步至 SonarQube 仪表盘。
    • allow_failure: true,允许扫描失败但不阻断流水线。

# 合并请求(MR)或 Test 分支提交

  1. 创建 Merge Request 或推送至 Test 分支
    • MR 目标分支需为 test(根据实际分支策略调整)。
  2. 触发合并检测流水线
    • SonarQube 检查结果将影响 MR 合并权限(需结合 Quality Gate 配置)暂无配置,不需要注意!。

# 四、注意事项

  1. 分支一致性
    • before_scriptgit clone -b <分支名> 必须与 only 规则中的目标分支匹配(如 test)。
    • 错误示例:拉取 origin/dev 但检测 test 分支,将导致代码版本不一致。
  2. 项目变量更新
    • 每次新增服务或模块时,务必更新 PROJECTKEYPROJECTNAME,避免 Key 重复冲突。
  3. 缓存清理
    • before_script 中的 rm -rf "${CI_PROJECT_DIR}" 用于强制清理残留文件,确保检出最新代码。

# 五、常见问题排查

问题现象 解决步骤
fatal: git fetch-pack: expected shallow list GIT_DEPTH: 0 设为完整克隆,
SonarQube 分析超时 调增 MAVEN_OPTS 内存(如 -Xmx1024m)或优化扫描范围
No files or directories found 检查 -Dsonar.sources 路径是否包含有效代码(如 src
Quality Gate 未生效 确认 -Dsonar.qualitygate.wait=true 参数是否传递

# 六、SonarQube修复流程

  1. 查看扫描信息

    • 目前给开发部组长开通了相关账号,信息如下:
      地址:http://192.168.0.184:9000/
      账号:姓名拼音
      密码:itonghui

    • 登录后,需要开启提醒通知。项目负责人搜索自己的项目

      image-20250424下午22335527

    • 各项目组长查看扫描情况后,可将需要修复的问题,分配给对应的组员,若无账号 联系技术经理创建。

    • 分配后,组员会收到相应通知

      企业微信截图_17454759468587

  2. 修复标准

    • 目前集成阿里的P3C规约,包含51条代码静态规范要求,需要将bug,漏洞,异味中的阻断,严重性问题进行修复。

      image-20250424下午22856990