SonarQube 多语言项目扫描实践

笔记/CICD/SonarQube代码扫描/SonarQube 多语言项目扫描实践

背景与动机#

不同语言项目接入 SonarQube 时,核心链路一致:

生成代码和测试产物 -> 运行 Scanner -> 上传报告到 SonarQube Server

但不同语言的扫描入口、覆盖率报告格式和构建顺序不一样。多语言项目最常见的问题不是 SonarQube 不支持,而是扫描配置和项目构建方式没有对齐。

通用原则#

1. 优先使用构建工具对应的 Scanner#

如果项目是标准构建体系,优先选择对应 Scanner:

  • Maven 项目:SonarScanner for Maven。
  • Gradle 项目:SonarScanner for Gradle。
  • .NET 项目:SonarScanner for .NET。
  • 普通脚本、前端、Go、小型项目:可以使用 SonarScanner CLI。

构建工具 Scanner 通常能自动读取更多项目信息,手工配置更少。

2. 覆盖率要先由测试工具生成#

SonarQube 不负责执行测试,也不凭空生成覆盖率。一般流程是:

运行测试 -> 生成覆盖率报告 -> Scanner 读取报告 -> Server 展示覆盖率

如果覆盖率一直是 0,优先检查测试命令和报告路径。

3. 不要扫描依赖目录和构建产物#

常见不该扫描的目录:

node_modules/
dist/
build/
target/
vendor/
.next/
coverage/

扫描范围越不清晰,结果越容易混入无关文件,也会拖慢 CI。

Java / Maven 项目#

1. 推荐入口#

Maven 项目通常使用 Maven 插件运行分析:

Terminal window
mvn clean verify sonar:sonar \
-Dsonar.projectKey=my-java-app \
-Dsonar.host.url=http://sonarqube.example.com:9000

认证 token 用环境变量:

Terminal window
export SONAR_TOKEN="your-project-token"

2. 覆盖率思路#

Java 项目常用 JaCoCo 生成覆盖率报告,再让 SonarQube 读取。

典型流程:

mvn test / mvn verify
生成 JaCoCo XML 报告
mvn sonar:sonar 上传分析

关键点是测试和报告生成要发生在扫描前。

3. 常见坑#

  • 只执行 sonar:sonar,没有先跑测试。
  • 覆盖率报告路径和实际生成路径不一致。
  • 多模块项目只在根模块配置了一部分路径。

Node / 前端项目#

1. 推荐入口#

普通前端项目可以使用 SonarScanner CLI:

sonar.projectKey=my-web-app
sonar.projectName=my-web-app
sonar.sources=src
sonar.tests=src
sonar.exclusions=node_modules/**,dist/**,build/**
sonar.host.url=http://sonarqube.example.com:9000

运行:

Terminal window
npm ci
npm test
sonar-scanner

2. 覆盖率思路#

前端项目通常先用测试框架生成 LCOV 报告,例如:

coverage/lcov.info

然后在 SonarQube 配置里指定对应路径。具体参数会随语言分析器和项目类型不同而变化,落地时要以当前 SonarQube 文档和项目测试工具为准。

3. 常见坑#

  • node_modules 扫进去。
  • dist.next 当源码扫。
  • 测试报告路径在本地存在,CI 里不存在。

Go 项目#

1. 推荐入口#

Go 项目通常可以使用 SonarScanner CLI:

sonar.projectKey=my-go-app
sonar.projectName=my-go-app
sonar.sources=.
sonar.exclusions=vendor/**,bin/**,dist/**
sonar.host.url=http://sonarqube.example.com:9000

运行测试和扫描:

Terminal window
go test ./...
sonar-scanner

2. 覆盖率思路#

Go 覆盖率通常先由 go test 生成:

Terminal window
go test ./... -coverprofile=coverage.out

然后配置 SonarQube 读取对应覆盖率文件。具体参数要和当前 SonarQube Go 分析器文档保持一致。

3. 常见坑#

  • sonar.sources=. 时没有排除 vendor 或生成目录。
  • 测试命令失败,但流水线仍继续扫描。
  • 覆盖率文件在 CI 工作目录里路径不一致。

多语言单仓库#

单仓库里可能同时有后端、前端、脚本和基础设施代码,例如:

repo/
├─ backend/
├─ frontend/
├─ scripts/
└─ deploy/

有两种思路:

  • 一个 SonarQube 项目扫描整个仓库。
  • 按后端、前端拆成多个 SonarQube 项目。

如果团队希望统一看一个质量门禁,可以先用一个项目。如果后端和前端由不同团队维护、发布节奏不同,拆成多个项目更清晰。

常见陷阱#

1. 所有语言都强行用同一套配置#

不同语言的测试报告、构建产物、依赖目录都不一样。可以统一流程,但不要强行统一所有参数。

2. 先扫描再测试#

覆盖率报告通常来自测试工具。先扫描再测试,SonarQube 读不到覆盖率。

3. 扫描范围过大#

把依赖、构建产物、生成代码都扫进去,会拖慢扫描,也会污染结果。

4. 多语言项目门禁过于粗暴#

如果一个项目里后端覆盖率很好、前端覆盖率很低,统一门禁可能导致团队争议。需要按项目实际情况配置。

配图建议#

建议插入在 ## 通用原则 后面。

文件名建议:image/06-sonarqube-multi-language-practice-01.png

生图提示词:

画一张 SonarQube 多语言项目扫描实践图,技术教学风格,浅色背景,横向 16:9 构图。左侧展示一个 monorepo:backend Java、frontend Node、service Go、scripts;中间展示各语言先运行测试并生成覆盖率报告:JaCoCo XML、LCOV、Go coverage.out;右侧展示 SonarScanner 或构建工具 Scanner 汇总分析结果并上传到 SonarQube Server。用中文标签,突出“先测试生成报告,再扫描上传结果”,不要画真实物理地址或真实项目名。

一句话总结#

多语言扫描的核心不是写一份万能配置,而是按语言和构建工具生成正确产物,再让 Scanner 读取正确源码范围和报告路径。

文章目录

文章目录