4. 代码质量检查:静态代码分析与格式校验
代码质量检查,说白了就是在代码还没跑起来之前,先把潜在的问题揪出来。我待过好几个团队,有的项目上线后突然崩溃,回头一查——空指针,静态分析早就报过警告,但没人当回事。
这块主要分两件事:静态代码分析和代码格式校验。前者抓逻辑缺陷和坏味道,后者统一风格。两个都是CI流水线的“门神”。
静态代码分析——抓逻辑漏洞与坏味道
静态分析不运行代码,只靠扫描源代码文本就能发现问题。我习惯把这类工具分成两派:通用派(SonarQube、CodeClimate)和语言专精派(ESLint、Pylint、Checkstyle)。
| 工具 | 适用语言 | 核心能力 | CI集成方式 |
|---|---|---|---|
| SonarQube | 多语言 | 漏洞检测、代码异味、重复率 | SonarScanner CLI / Maven / Gradle 插件 |
| ESLint | JavaScript/TypeScript | 规则检查、自动修复 | 直接执行 npx eslint . |
| Checkstyle | Java | 编码规范、Javadoc | Maven checkstyle:check |
| Pylint | Python | 语法错误、命名约定 | pylint *.py |
我在项目中遇到过最典型的例子:一个JavaScript项目,ESLint配置了no-unused-vars规则,但团队一直忽略warning。结果重构时删了一个函数,然而另一个模块还引用了它——但引用方根本没被调用。上线后死循环,花了俩小时才定位到。从那以后,我坚持在CI里把这些warning当作error处理。
.eslintrc 中把关键规则设为 "error",然后在CI脚本中让检查失败直接阻断流水线。
代码格式校验——终结“缩进党争”
代码风格本身没有对错,但团队里不统一就是灾难。你想想看,每次code review都在争论“这里该不该空格”——浪费生命。
Prettier 是我现在几乎每个前端项目必加的工具。它在CI里只做一件事:检查格式是否与预设一致,不一致则失败。配合编辑器保存即格式化,开发体验极其丝滑。
# .prettierrc 示例
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all"
}
prettier --check . 和 eslint --max-warnings 0。前者管格式,后者管质量,各司其职。
CI流水线集成——怎么写Stage?
以GitLab CI为例,我一般会在 .gitlab-ci.yml 里单独开一个stage叫 quality,里面放两个job:
stages:
- quality
sonarqube-check:
stage: quality
image: sonarsource/sonar-scanner-cli:latest
script:
- sonar-scanner -Dsonar.projectKey=myapp -Dsonar.sources=.
only:
- merge_requests
prettier-eslint:
stage: quality
image: node:18
script:
- npm ci
- npx prettier --check "src/**/*.{js,ts,jsx,tsx}"
- npx eslint "src/**/*.{js,ts,jsx,tsx}" --max-warnings 0
only:
- merge_requests
为什么要限制在 merge_requests 上执行?因为主分支的代码应该已经通过检查了,重复扫描浪费资源。
sonar.scm.revision 参数结合Git diff做增量,值得一试。
门禁策略——该拦就要拦
我刚开始做CI时,担心严格门禁影响开发效率,所以只设了warning。结果大家养成了无视警告的习惯。后来痛下决心:质量检查不通过的merge request直接block,由开发自己修复或申请豁免。
| 门禁级别 | 推荐做法 | 适用场景 |
|---|---|---|
| 警告级 | 允许通过,但显示报告 | 早期团队习惯培养期 |
| 软阻断 | 新代码若有新增问题则阻断 | 遗留项目渐进式改进 |
| 硬阻断 | 任何代码质量问题都阻断 | 新项目或严格质量要求的项目 |
这里有个细节:误报怎么办?SonarQube里可以标记“误报” (False Positive),或者添加 // NOSONAR 注释。但滥用注释会破坏规则威信。我在团队里定了规矩:每周评审一次新标记的误报,确实不需要改的再注释。
常见避坑指南
- 扫描时间太长: 增量扫描 + 只扫描
src/目录,排除node_modules、build等。 - 规则过度定制: 初期直接用社区推荐配置(比如 eslint:recommended),等团队成熟后再微调。别一开始就自己造规则。
- 工具版本不一致: 本地用Prettier 2.x,CI里装的是3.x,格式规则可能不同。用
package.json锁定版本。 - 多语言项目: 不同语言用不同工具,但尽量统一到一个SonarQube实例下,方便质量看板。