@ifrankwang/openspec-agents 0.118.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -0
- package/assets/agents/openspec-architect.md +61 -0
- package/assets/agents/openspec-developer.md +21 -0
- package/assets/agents/openspec-main.md +35 -0
- package/assets/agents/openspec-reviewer-architecture.md +60 -0
- package/assets/agents/openspec-reviewer-maintainability.md +59 -0
- package/assets/agents/openspec-reviewer-performance.md +49 -0
- package/assets/agents/openspec-reviewer-security.md +51 -0
- package/assets/agents/openspec-reviewer-style.md +50 -0
- package/assets/agents/openspec-reviewer-task.md +40 -0
- package/assets/agents/openspec-reviewer-tool.md +30 -0
- package/assets/dashboard/index.html +295 -0
- package/assets/skills/api-conventions/SKILL.md +60 -0
- package/assets/skills/api-test/SKILL.md +175 -0
- package/assets/skills/architecture-evolution/SKILL.md +60 -0
- package/assets/skills/db-conventions/SKILL.md +62 -0
- package/assets/skills/ddd-architecture/SKILL.md +261 -0
- package/assets/skills/environment-cleanup/SKILL.md +44 -0
- package/assets/skills/java-api-conventions/SKILL.md +30 -0
- package/assets/skills/java-code-maintainability/SKILL.md +62 -0
- package/assets/skills/java-code-performance/SKILL.md +49 -0
- package/assets/skills/java-code-style/SKILL.md +54 -0
- package/assets/skills/java-db-conventions/SKILL.md +44 -0
- package/assets/skills/java-ddd-architecture/SKILL.md +533 -0
- package/assets/skills/java-dev-practices/SKILL.md +110 -0
- package/assets/skills/java-quality-gate/SKILL.md +455 -0
- package/assets/skills/java-quality-gate/reference/pmd-rules.md +16 -0
- package/assets/skills/java-quality-tool-improve/SKILL.md +142 -0
- package/assets/skills/java-security/SKILL.md +59 -0
- package/assets/skills/java-technical-debt/SKILL.md +36 -0
- package/assets/skills/orchestrator/SKILL.md +65 -0
- package/assets/skills/quality-gate/SKILL.md +84 -0
- package/assets/skills/security-baseline/SKILL.md +101 -0
- package/assets/skills/technical-debt/SKILL.md +78 -0
- package/assets/workflows/task.yaml +177 -0
- package/package.json +79 -0
- package/src/adapters/agent-md.ts +37 -0
- package/src/adapters/claude-code/index.ts +35 -0
- package/src/adapters/codex/index.ts +161 -0
- package/src/adapters/mcp-common/cli.ts +64 -0
- package/src/adapters/mcp-common/index.ts +137 -0
- package/src/adapters/mcp-common/json-schema.ts +53 -0
- package/src/adapters/mcp-common/server.ts +157 -0
- package/src/adapters/opencode/agents.ts +80 -0
- package/src/adapters/opencode/dashboard.ts +64 -0
- package/src/adapters/opencode/index.ts +34 -0
- package/src/adapters/opencode/json-schema.ts +60 -0
- package/src/adapters/opencode/skills.ts +19 -0
- package/src/adapters/opencode/tools.ts +78 -0
- package/src/adapters/plugin-common/index.ts +173 -0
- package/src/adapters/zcode/index.ts +32 -0
- package/src/core/constants.ts +46 -0
- package/src/core/dashboard.ts +101 -0
- package/src/core/derive.ts +146 -0
- package/src/core/exemptions.ts +168 -0
- package/src/core/git.ts +373 -0
- package/src/core/index.ts +76 -0
- package/src/core/namespace.ts +12 -0
- package/src/core/paths.ts +23 -0
- package/src/core/provider.ts +74 -0
- package/src/core/state.ts +357 -0
- package/src/core/task-children.ts +59 -0
- package/src/core/tasks-md.ts +89 -0
- package/src/core/tools/gate.ts +165 -0
- package/src/core/tools/lifecycle.ts +645 -0
- package/src/core/tools/schemas.ts +363 -0
- package/src/core/tools/submit.ts +863 -0
- package/src/core/tools/types.ts +129 -0
- package/src/core/types.ts +135 -0
- package/src/core/views.ts +195 -0
- package/src/core/workflow/collector.ts +150 -0
- package/src/core/workflow/engine.ts +576 -0
- package/src/core/workflow/index.ts +56 -0
- package/src/core/workflow/loader.ts +277 -0
- package/src/core/workflow/poller.ts +159 -0
- package/src/core/workflow/reset.ts +93 -0
- package/src/core/workflow/status.ts +1010 -0
- package/src/core/workflow/submit.ts +331 -0
- package/src/core/workflow/types.ts +100 -0
- package/src/core/workflow/writeback.ts +48 -0
- package/src/dashboard/page.ts +19 -0
- package/src/index.ts +2 -0
- package/src/skills/resolve.ts +95 -0
- package/src/skills/scan.ts +29 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: java-quality-gate
|
|
3
|
+
description: 仅限 Java 后端开发场景。Java 项目质量门工具集——Maven/Spotless/PMD/ArchUnit/JaCoCo/SonarQube。通用质量门流程见 quality-gate。
|
|
4
|
+
capabilities: ["quality-gate", "tech-stack-java"]
|
|
5
|
+
# 机器可读必做清单:与下方「必做检查清单」表格逐项一一对应(汇总与产出属流程元项,不作为必做申报项)。
|
|
6
|
+
# 第 2-6 行「全量生命周期」拆分为 compile/format/architecture/static_analysis/unit_test/coverage;
|
|
7
|
+
# 第 7 行「SonarQube 深度扫描」对应 deep_scan(quality-gate 第 6 类深度扫描的 Java 具体实现)。
|
|
8
|
+
must_do: ["env", "compile", "format", "architecture", "static_analysis", "unit_test", "coverage", "deep_scan", "config_check"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
> **项目规范优先**:本 skill 所列约定为推荐标准。若项目已有明确规范且与本 skill 不一致,以项目规范为准。
|
|
12
|
+
> 本 skill 是 quality-gate 的 Java 实现配套,仅含 Java 技术栈特有工具命令与输出解析。通用质量门流程见 quality-gate。调用本 skill 须同时加载 quality-gate。
|
|
13
|
+
|
|
14
|
+
## 通用步骤
|
|
15
|
+
|
|
16
|
+
### 必做检查清单
|
|
17
|
+
|
|
18
|
+
以下清单枚举所有检查项。每项不可跳跃——要么执行并报告结果,要么在提交报告中注明跳过理由及对应 issue:
|
|
19
|
+
|
|
20
|
+
| 序号 | 检查项 | skill 章节 | 报告要求 |
|
|
21
|
+
|------|--------|-----------|---------|
|
|
22
|
+
| 1 | 工具环境检查 | 第 0 节 | 逐项报告可用性,不可用须注明降级理由 |
|
|
23
|
+
| 2-6 | 全量生命周期:编译 + 格式 + 架构 + PMD + UT + 覆盖率 | 第 1~5 节 — `mvn verify -q` | 报告 BUILD SUCCESS/FAILURE、格式违规数、架构违规数、PMD 违规数和严重级别、测试通过率与覆盖率 |
|
|
24
|
+
| 7 | SonarQube 深度扫描 | 第 6 节 | 报告执行结果或降级理由 |
|
|
25
|
+
| 8 | 质量工具配置检查 | 第 7 节 | 报告通过或配置削弱清单 |
|
|
26
|
+
| 9 | 汇总与产出 | 第 9 节 | 产出检查结果与 issue 清单 |
|
|
27
|
+
|
|
28
|
+
## 0. 工具环境检查
|
|
29
|
+
|
|
30
|
+
在执行工具检查前,先确保工具运行环境就绪。环境检查失败时先按自愈性步骤尝试恢复;不可自愈或自愈失败后,用 `question` 提请用户处理或裁定。用户裁定降级跳过时,在报告中注明降级理由,不阻塞其他检查。
|
|
31
|
+
|
|
32
|
+
使用编排会话提供的隔离标识 `<namespace>`(来自编排会话上下文)为 SonarQube 容器指定独立的 docker compose 项目名,避免多个并发 change 的容器互相冲突。
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
docker info
|
|
36
|
+
docker compose version
|
|
37
|
+
curl -sf http://localhost:9000/api/system/status | grep -q UP
|
|
38
|
+
sonar-scanner --version
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
| 检查项 | 命令 | 自愈性 | 失败后处理 |
|
|
42
|
+
|--------|------|-------|-----------|
|
|
43
|
+
| Docker daemon | `docker info` | 不可自愈 | `question` 用户(需宿主介入)→ 用户处理后重试或裁定降级跳过 |
|
|
44
|
+
| docker-compose | `docker compose version` | 不可自愈 | `question` 用户 → 用户处理后重试或裁定降级跳过 |
|
|
45
|
+
| SonarQube 服务 | `curl -sf http://localhost:9000/api/system/status \| grep -q UP` | 可自愈 | 先 `docker compose -p <namespace> -f <docker-compose-file> up -d sonarqube` 自愈;失败则 `question` 用户 → 裁定降级 |
|
|
46
|
+
| sonar-scanner CLI | `sonar-scanner --version` | 不可自愈 | `question` 用户(需安装 CLI)→ 用户处理后重试或裁定降级 |
|
|
47
|
+
|
|
48
|
+
`<docker-compose-file>` 优先取项目根目录下含 sonarqube 服务的 `docker-compose*.yaml`。
|
|
49
|
+
|
|
50
|
+
## 1. 编译检查
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
mvn verify -q; echo "BUILD_STATUS=$?"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
说明:`mvn verify` 包含 compile + test + spotless:check + pmd:check 等阶段。
|
|
57
|
+
|
|
58
|
+
- 通过:`BUILD_STATUS=0`
|
|
59
|
+
- 不通过:`BUILD_STATUS≠0` → 工具层 issue,severity=Critical,须修复
|
|
60
|
+
|
|
61
|
+
## 2. 代码格式检查
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
mvn spotless:check
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- 通过:无格式违规,输出 "[INFO] Spotless check passed"
|
|
68
|
+
- 不通过:→ tool 类 issue,severity=Low,每条违规映射为一个 issue
|
|
69
|
+
- 从 `spotless:check` 输出中提取违规文件路径
|
|
70
|
+
- 修复方式:运行 `mvn spotless:apply`
|
|
71
|
+
|
|
72
|
+
## 3. 架构约束检查
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
mvn test -Dtest="*Architecture*,*ArchRule*"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- 通过:所有 ArchUnit 测试通过
|
|
79
|
+
- 不通过:→ tool 类 issue,severity=Medium,每条 ArchUnit 违规映射为一个 issue
|
|
80
|
+
- expression: 从测试失败信息中提取违规类名和描述
|
|
81
|
+
- 示例:"Domain 层引入 org.springframework.stereotype.Service"
|
|
82
|
+
|
|
83
|
+
## 4. 代码质量检查
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
mvn pmd:check
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 阻塞级
|
|
90
|
+
|
|
91
|
+
PMD 检查返回非 0(有违规)即阻塞 task 完成。以下 PMD 规则集启用:
|
|
92
|
+
|
|
93
|
+
- `category/java/errorprone.xml`(错误模式:空 catch、compareToEquals 等)
|
|
94
|
+
- `category/java/bestpractices.xml`(最佳实践:unused imports、System.out、AvoidReassigningParameters、JUnitTestsShouldIncludeAssert 等)
|
|
95
|
+
- `category/java/design.xml`(设计:方法长度、圈复杂度、God class 等)
|
|
96
|
+
- `category/java/performance.xml`(性能:String 拼接、冗余对象创建等)
|
|
97
|
+
|
|
98
|
+
### 违规项 → issue 映射
|
|
99
|
+
|
|
100
|
+
| PMD 规则 | 优先级 | issue severity | 典型场景 |
|
|
101
|
+
|----------|--------|---------------|---------|
|
|
102
|
+
| System.out/err | 2 | Medium | `System.out.println(...)` |
|
|
103
|
+
| 空 catch 块 | 3 | High | `catch(Exception e) {}` |
|
|
104
|
+
| 方法过长 | 3 | Medium | 方法超过 100 行 |
|
|
105
|
+
| 圈复杂度过高 | 3 | Medium | CC > 15(方法级)、CC > 20(类级) |
|
|
106
|
+
| 未使用变量/import | 3 | Low | import 引用但未使用 |
|
|
107
|
+
| String 拼接 | 3 | Low | 循环内 `s += ...` |
|
|
108
|
+
| 未关闭资源 | 3 | High | 未使用 try-with-resources |
|
|
109
|
+
| 类级 @SuppressWarnings | 2 | Medium | 在类级别添加 @SuppressWarnings 抑制特定规则 |
|
|
110
|
+
|
|
111
|
+
> 本表为高频示例(非穷举),规则为常见俗名;官方全名与分类见 `reference/pmd-rules.md`,未收录规则按「PMD 规则语义定位」方法论直拉官方源。
|
|
112
|
+
|
|
113
|
+
### 输出解析
|
|
114
|
+
|
|
115
|
+
PMD 违规输出格式:
|
|
116
|
+
```
|
|
117
|
+
[WARNING] PMD Failure: <file>:<line> Rule:<rule> Priority:<N> <message>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
从输出中逐行解析,提取 file / line / rule / message 字段。
|
|
121
|
+
|
|
122
|
+
机器检索违规清单首选 `target/pmd.xml`(结构化、`<violation>` 一行一元素、rule 属性可直接 grep)。若 pom 未配置 `format=xml` 导致该文件不存在,先执行 `mvn pmd:pmd -Dpmd.format=xml` 生成。多模块项目到各模块 `target/` 目录查找。
|
|
123
|
+
|
|
124
|
+
不解析 HTML 报告(`target/reports/pmd.html` 体积大、格式脆弱,仅适合人工阅读)。
|
|
125
|
+
|
|
126
|
+
`target/pmd.xml` 被 `<suppressedviolation>` 污染(全量规则集 + 抑制配置时)时,改用自定义 ruleset 生成的干净报告,或读取 `mvn pmd:check` 非 -q 形态 console 输出中的 `[WARNING] PMD Failure` 行。
|
|
127
|
+
|
|
128
|
+
### 测量与复现
|
|
129
|
+
|
|
130
|
+
pom 中 maven-pmd-plugin 显式配置的 `<rulesets>` 会覆盖命令行 `-Dpmd.rulesets`,修改生效规则集须改 pom 配置,勿用命令行参数覆盖。
|
|
131
|
+
|
|
132
|
+
生成干净报告:自定义 ruleset 运行 `mvn pmd:pmd`,生成的 `target/pmd.xml` 不含全量规则集 + 抑制配置产生的 `<suppressedviolation>` 污染,可直接 grep 按 rule 过滤。
|
|
133
|
+
|
|
134
|
+
PMD CLI 手动运行需完整 classpath:用 `mvn dependency:build-classpath` 自动生成,禁止手工枚举 jar(classpath 缺 jar 是高频失败源)。
|
|
135
|
+
|
|
136
|
+
改动规则/阈值前先在最小项目实测规则效果再落地。
|
|
137
|
+
|
|
138
|
+
### PMD 规则语义定位(检索方法论)
|
|
139
|
+
|
|
140
|
+
以工具输出为入口:`mvn pmd:check` 违规清单按 `rule` 字段去重,仅对命中规则做语义定位,不预置全量规则内容。
|
|
141
|
+
|
|
142
|
+
确定项目实际 PMD 版本:读 `mvn dependency:tree -Dincludes=net.sourceforge.pmd` 实际解析的 pmd-core/pmd-java 版本,或 pom 显式配置的 PMD 版本;不得仅凭 maven-pmd-plugin 版本号推断(3.22.0 起默认 PMD 7,且 pom 可覆盖插件默认版本)。
|
|
143
|
+
|
|
144
|
+
直拉官方规则定义(首选):`https://raw.githubusercontent.com/pmd/pmd/pmd_releases/<实际版本>/pmd-java/src/main/resources/category/java/<分类>.xml`,从 `<rule name="...">` 节点读取默认阈值 property、判定逻辑(xpath 或规则类)、externalInfoUrl;版本无法确定时降级用 `main` 分支(注意 main 为开发分支,内容代表未来版本)。
|
|
145
|
+
|
|
146
|
+
文档锚点核对:`https://docs.pmd-code.org/pmd-doc-<实际版本>/pmd_rules_java_<分类>.html#<规则全名小写>`(锚点即规则全名小写)。
|
|
147
|
+
|
|
148
|
+
兜底:经文档检索渠道(定义见 README「文档检索渠道」)语义定位规则所属分类,结果与上述官方源交叉核对;注意区分同族易混规则(如 TooManyMethods / NcssCount / ExcessiveMethodLength)。
|
|
149
|
+
|
|
150
|
+
外查结果(规则全名/默认阈值/语义)写入 issue 描述;需要规则索引时读取 `reference/pmd-rules.md`。
|
|
151
|
+
|
|
152
|
+
### CPD 重复代码检查
|
|
153
|
+
|
|
154
|
+
若项目 `maven-pmd-plugin` 配置了 `cpd-check` goal,则随 `mvn verify` 一并执行;未启用则本检查项跳过,不强制项目启用。
|
|
155
|
+
|
|
156
|
+
重复块明细以 `target/cpd.xml` 为主解析来源。`cpd-check` 执行时在该文件生成报告,`<duplication>` 元素下逐 `<file>` 属性列出重复块的文件与起止行列(PMD 7 的 file 元素含 line/endline/column/endcolumn 属性)。重复块跨文件时,同一块对应的全部位置均须记录。
|
|
157
|
+
|
|
158
|
+
控制台输出默认只有汇总行,逐位置明细行仅开启 `pmd.verbose=true` 或 `pmd.printFailingErrors=true` 时输出:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
CPD Failure: Found 14 lines of duplicated code at locations:
|
|
162
|
+
<绝对路径> line 42
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
`CPD Failure` 行单独成行,下一行以 4 空格缩进列出重复位置、每文件一行;日志级别随版本而异(旧版 `[INFO]`、新版 `[WARNING]`)。汇总行表述随 maven-pmd-plugin 版本变化:3.26+ 为 `CPD <版本> has found N duplications`(以 `[WARNING]` 或失败时随异常 `[ERROR]` 呈现),3.22 及以前为 `You have N CPD duplications. For more details see: <path>`。位置明细以 `cpd.xml` 为准,不受版本差异影响。
|
|
166
|
+
|
|
167
|
+
映射口径:每处重复块映射为一条 issue,description 列出该块全部文件位置,不按位置拆分多条。严重级别沿用上方逐条映射惯例——逻辑重复方法 → Medium、纯数据字段 → Low,不走「mvn verify 失败 → Critical」路径。
|
|
168
|
+
|
|
169
|
+
## 5. 单元测试 + 覆盖率
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
mvn test
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
说明:`mvn verify` 已包含本阶段(生命周期内自动调用 `mvn test` + JaCoCo 覆盖率检查)。
|
|
176
|
+
|
|
177
|
+
`mvn test` 实际全量运行全部测试,其中 `ArchitectureTest` 已在第 3 节单独执行,本节不重复计数、不重复报告其执行结果。
|
|
178
|
+
|
|
179
|
+
- 通过:所有测试通过
|
|
180
|
+
- 不通过:→ 工具层 issue,severity 按测试类型区分
|
|
181
|
+
- 业务逻辑测试失败 → High(功能回归)
|
|
182
|
+
- 新增功能测试失败 → Medium(新代码 Bug)
|
|
183
|
+
- 测试基础设施问题 → Critical(环境问题)
|
|
184
|
+
|
|
185
|
+
### 覆盖率(JaCoCo)
|
|
186
|
+
|
|
187
|
+
JaCoCo 已在 `pom.xml` 中配置,`mvn verify` 后自动在 `target/site/jacoco/` 下生成报告。解析 `jacoco.csv` 获取覆盖率数据:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
cat target/site/jacoco/jacoco.csv
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
| 字段 | 含义 |
|
|
194
|
+
|------|------|
|
|
195
|
+
| INSTRUCTION_MISSED/COVERED | 字节码指令覆盖率 |
|
|
196
|
+
| BRANCH_MISSED/COVERED | 分支覆盖率 |
|
|
197
|
+
| LINE_MISSED/COVERED | 行覆盖率 |
|
|
198
|
+
|
|
199
|
+
`jacoco.csv` 的完整列序为 `GROUP,PACKAGE,CLASS,INSTRUCTION_MISSED,INSTRUCTION_COVERED,BRANCH_MISSED,BRANCH_COVERED,LINE_MISSED,LINE_COVERED,COMPLEXITY_MISSED,COMPLEXITY_COVERED,METHOD_MISSED,METHOD_COVERED`,每个计数器按 MISSED 在前、COVERED 在后排列。
|
|
200
|
+
|
|
201
|
+
覆盖率聚合按计数器列求和后计算:`LINE 覆盖率 = ΣLINE_COVERED / (ΣLINE_MISSED + ΣLINE_COVERED)`,INSTRUCTION、BRANCH 同理。
|
|
202
|
+
|
|
203
|
+
`jacoco.csv` 每行对应一个含代码的 class,不包含汇总行,对所有数据行按计数器列求和即为总体统计;若数据中出现 `CLASS=Total` 行(由部分工具导出),跳过该行避免双计数。
|
|
204
|
+
|
|
205
|
+
核心包过滤:核心包范围以 `<project-specific:jacoco-core-packages>` 占位符表示,由项目填充具体包路径;项目未填充该占位符时仅报告整体覆盖率。
|
|
206
|
+
|
|
207
|
+
覆盖率检查以 pom.xml 中 JaCoCo `<check>` 配置为准。可按包路径定义多层策略(如整体保底 + 核心包高要求),各层阈值从 pom.xml 中读取。
|
|
208
|
+
双层检查均在 `mvn verify` 中自动执行,任何一层不达标即 build 失败。
|
|
209
|
+
|
|
210
|
+
## 6. SonarQube 深度扫描
|
|
211
|
+
|
|
212
|
+
### 前置条件
|
|
213
|
+
|
|
214
|
+
本地 SonarQube Server 通过 `docker compose -p <namespace> -f <docker-compose-file> up -d sonarqube` 启动。
|
|
215
|
+
|
|
216
|
+
### 扫描前准备
|
|
217
|
+
|
|
218
|
+
以 `<项目原key>-<namespace>` 作为 project key,经 SonarQube Web API 完成 project 预创建、new code 定义设置与一次性认证 token 生成。
|
|
219
|
+
|
|
220
|
+
#### admin 凭据来源
|
|
221
|
+
|
|
222
|
+
Web API 管理操作(project 预创建、new code 定义设置、token 生成与回收)所用的 admin 凭据按以下回退链取得:
|
|
223
|
+
|
|
224
|
+
1. 项目 `sonar-project.properties` 的 `sonar.login` / `sonar.password`
|
|
225
|
+
2. docker-compose 中 SonarQube 服务环境变量(如 `SONAR_SECURITY_LOCALSTARTUPPASSWORD`)
|
|
226
|
+
3. 社区版本地部署默认 `admin/admin`
|
|
227
|
+
|
|
228
|
+
这些凭据仅用于本地 dev 部署的 project 预创建与一次性 token 生命周期。禁止把 admin 凭据写进扫描参数(扫描本身走 token 注入);`sonar.login` 语义是 scanner 侧认证,Web API 管理操作须以用户名+密码形态使用。
|
|
229
|
+
|
|
230
|
+
#### 判断 project 存在性并预创建
|
|
231
|
+
|
|
232
|
+
先经 Web API 查询 project 是否已存在,不存在才创建:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
curl -sf -u admin:<admin密码> "http://localhost:9000/api/projects/search?project=<项目原key>-<namespace>"
|
|
236
|
+
curl -sf -X POST -u admin:<admin密码> "http://localhost:9000/api/projects/create?key=<项目原key>-<namespace>&name=<项目原key>-<namespace>"
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
MUST 先 search 再 create:create 对已存在的 key 返回 HTTP 400,必须以 search 结果判断存在性,禁止直接 create。project key 即 `<项目原key>-<namespace>`。
|
|
240
|
+
|
|
241
|
+
#### 设置 new code 定义
|
|
242
|
+
|
|
243
|
+
将 project 的 new code 定义设置为 `NUMBER_OF_DAYS`,天数固定 30:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
curl -sf -X POST -u admin:<admin密码> "http://localhost:9000/api/new_code_periods/set?project=<项目原key>-<namespace>&type=NUMBER_OF_DAYS&value=30"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
set 后须验证定义生效:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
curl -sf -u admin:<admin密码> "http://localhost:9000/api/new_code_periods/show?project=<项目原key>-<namespace>&branch=main"
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
验证命令返回 `type=NUMBER_OF_DAYS` 且 `value=30` 即生效。Community Edition 下 new code 定义为 branch 级存储,set 时未指定 branch 即落 main branch 级;`show` 不带 `branch` 参数只读取 project 级定义(branch_uuid 为空),恒返回全局继承的 `PREVIOUS_VERSION`,属正常现象,不作为设置失败判据。扫描 main branch 时读取 main branch 级定义,new code 期判定不受影响。
|
|
256
|
+
|
|
257
|
+
#### 生成一次性认证 token
|
|
258
|
+
|
|
259
|
+
扫描前用 admin 凭据生成一次性 token,token 值仅本次响应返回一次,扫描结束后回收:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
curl -sf -X POST -u admin:<admin密码> "http://localhost:9000/api/user_tokens/generate?name=<唯一token名>"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
MUST token 名唯一(如附时间戳或随机后缀),token 值只在生成响应中返回一次,须在后续扫描命令中引用。admin 凭据按上方 `admin 凭据来源` 回退链取得。
|
|
266
|
+
|
|
267
|
+
### 配置
|
|
268
|
+
|
|
269
|
+
`sonar-project.properties` 文件位于项目根目录。
|
|
270
|
+
|
|
271
|
+
### 执行
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
SONAR_TOKEN=<token> sonar-scanner \
|
|
275
|
+
-Dsonar.projectKey=<项目原key>-<namespace> \
|
|
276
|
+
-Dsonar.scm.enabled=true \
|
|
277
|
+
-Dsonar.scm.provider=git
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
MUST 使用 `-Dsonar.projectKey` 指定含隔离标识 `<namespace>` 的项目 key(原始 key 从 `sonar-project.properties` 读取后追加 `-<namespace>`),禁止不加 `-Dsonar.projectKey` 覆盖直接执行 `sonar-scanner`。隔离标识来自编排会话上下文。
|
|
281
|
+
|
|
282
|
+
非 worktree 场景下,MUST 追加 SCM 集成参数 `-Dsonar.scm.enabled=true -Dsonar.scm.provider=git`,git blame 提供代码行修改时间戳,是 new code 期判定的数据基础。SCM 参数经命令行显式传入,禁止改动 `sonar-project.properties`,避免影响质量门配置检查。若因 SCM 集成故障导致扫描失败或 new code 期数据异常,按下方降级判据降级。
|
|
283
|
+
|
|
284
|
+
非 worktree 场景下,当项目 `sonar-project.properties` 含 `sonar.scm.disabled=true` 时,需在上方命令显式追加 `-Dsonar.scm.disabled=false` 覆盖(`sonar.scm.disabled` 是 SCM 集成总开关,`-Dsonar.scm.enabled=true` 会被其压制);覆盖失败按下方降级判据降级。
|
|
285
|
+
|
|
286
|
+
token 经 `SONAR_TOKEN` 环境变量注入(等价写法:`-Dsonar.token=<token>`)。
|
|
287
|
+
|
|
288
|
+
### 取 new code 期间 issue
|
|
289
|
+
|
|
290
|
+
经 Web API 查询 new code 期 issue:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
curl -sf -u <token>: "http://localhost:9000/api/issues/search?inNewCodePeriod=true&statuses=OPEN,CONFIRMED,REOPENED&componentKeys=<项目原key>-<namespace>"
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
该端点不返回安全热点,热点经下方独立端点获取。
|
|
297
|
+
|
|
298
|
+
MUST 使用 `inNewCodePeriod=true` 限定 new code 期,`componentKeys` 传单个 project key。new code 期过滤仅 `inNewCodePeriod` 参数可用(SonarQube 10.0 已移除旧的 leak period 过滤参数)。查询须携带认证,token 复用本流程生成的一次性 token,以 Basic auth 形式经 `-u <token>:` 传入(token 作用户名、密码留空),否则默认开启 forceAuthentication 时返回 401。`inNewCodePeriod` 仅限定 new code 期,不含状态过滤,会返回期内所有状态的 issue(含已关闭 CLOSED FIXED)。MUST 追加 `statuses=OPEN,CONFIRMED,REOPENED` 限定未解决 issue;已关闭 issue 不属本轮待处理项,不得据此误判排除/抑制配置未生效或触发重扫。
|
|
299
|
+
|
|
300
|
+
### 规则语义定位
|
|
301
|
+
|
|
302
|
+
issue 的 `rule` 字段(如 `java:S106`)即 SonarSource 官方全名,作为反查入口。
|
|
303
|
+
|
|
304
|
+
Web API 精确反查:`curl -u <token>:` 调 `/api/rules/search?rule_key=<rule 字段>`(可按需 `&f=` 限定字段),从响应的 `name` 取规则标题、`descriptionSections[].content`(HTML,9.5+ 标准字段)取语义、`severity`/`type` 取分类。
|
|
305
|
+
|
|
306
|
+
认证与时序:复用「取 new code 期间 issue」生成的一次性 token(Basic auth,token 作用户名密码留空),反查须在 token 回收前完成(取 issue → 反查规则语义 → 回收 token);匿名不可靠(实例默认强制认证,且 2026.2 起匿名用户拿到的描述字段被混淆)。
|
|
307
|
+
|
|
308
|
+
外查结果(规则全名/语义/severity)写入 issue 描述。
|
|
309
|
+
|
|
310
|
+
### 安全热点(独立端点)
|
|
311
|
+
|
|
312
|
+
`/api/issues/search` 不返回安全热点,热点属独立类别,须经专用端点获取。
|
|
313
|
+
|
|
314
|
+
先查 `new_security_hotspots` 指标判断 new code 期热点存量:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
curl -sf -u <token>: "http://localhost:9000/api/measures/component?component=<项目原key>-<namespace>&metricKeys=new_security_hotspots"
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
存量 > 0 时经热点专用端点拉取:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
curl -sf -u <token>: "http://localhost:9000/api/hotspots/search?projectKey=<项目原key>-<namespace>&inNewCodePeriod=true&status=TO_REVIEW"
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
MUST 携带 `inNewCodePeriod=true` 限定 new code 期、`status=TO_REVIEW` 限定待评审热点,否则返回全项目历史存量热点。仅报告待评审热点,已审 SAFE/FIXED 不纳入。
|
|
327
|
+
|
|
328
|
+
Security Hotspot 不可用 NOSONAR 注释抑制。平台状态标注(SAFE/FIXED 等)仅作用于当前 SonarQube 项目的 issue 实例;本编排下每次 change 使用独立项目 key(`<项目原key>-<namespace>`,namespace 按变更隔离),平台状态不随代码跨 change 继承,同一代码问题在新项目的全量扫描中以 OPEN 状态重新出现;跨 change 持续豁免的结论承载位置由编排层定义。命中项目级豁免清单的存量热点按 Info 提报,不重新豁免。
|
|
329
|
+
|
|
330
|
+
热点无 BLOCKER/CRITICAL 分级体系,按 `vulnerabilityProbability` 映射 issue severity:HIGH → High、MEDIUM → Medium、LOW → Low;TO_REVIEW 表示待评审而非已确认缺陷。违规映射沿用第 8 节映射表 `SECURITY_HOTSPOT → security`。
|
|
331
|
+
|
|
332
|
+
### 质量门禁与代码规模指标
|
|
333
|
+
|
|
334
|
+
扫描后一次调用获取质量门禁结果与代码规模指标:
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
curl -sf -u <token>: "http://localhost:9000/api/measures/component?component=<项目原key>-<namespace>&metricKeys=alert_status,ncloc,new_lines"
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
- `alert_status`:质量门禁结果(OK/ERROR)。ERROR 时经 `/api/qualitygates/project_status?projectKey=<项目原key>-<namespace>` 解析 `conditions` 字段,定位失败的具体 metric 以产出可定位 issue;亦可读 `sonar-scanner` 输出尾部的 `QUALITY GATE STATUS` 行(PASSED/FAILED)快速判断,失败时仍须以 conditions 定位具体 metric
|
|
341
|
+
- `ncloc` / `new_lines`:代码规模指标,供降级判据使用;`new_lines=0` 表示 new code 期无新增行,按下方降级判据触发全量口径
|
|
342
|
+
|
|
343
|
+
### 回收一次性认证 token
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
curl -sf -X POST -u admin:<admin密码> "http://localhost:9000/api/user_tokens/revoke?name=<唯一token名>"
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
MUST 扫描结束即回收 token,禁止遗留长期有效的未回收凭证。
|
|
350
|
+
|
|
351
|
+
### 违规项 → issue 映射
|
|
352
|
+
|
|
353
|
+
| SonarQube severity | issue severity | 处理方式 |
|
|
354
|
+
|-------------------|---------------|---------|
|
|
355
|
+
| blocker | Critical | 阻塞,必须修复 |
|
|
356
|
+
| critical | High | 阻塞,必须修复 |
|
|
357
|
+
| major | Medium | 阻塞,必须修复 |
|
|
358
|
+
| minor | Low | 阻塞,建议修复 |
|
|
359
|
+
| info | Info | 不阻塞 |
|
|
360
|
+
|
|
361
|
+
SonarQube 规则 6,500+,覆盖 PMD 无法检测的安全漏洞、代码异味、Bug 模式和安全热点。
|
|
362
|
+
|
|
363
|
+
### 输出解析
|
|
364
|
+
|
|
365
|
+
从 `sonar-scanner` 输出或 SonarQube API 获取 `issues`,提取:
|
|
366
|
+
- `rule`(如 `java:S106`)
|
|
367
|
+
- `component`(文件路径)
|
|
368
|
+
- `line`(行号)
|
|
369
|
+
- `message`(描述)
|
|
370
|
+
- `severity`(BLOCKER/CRITICAL/MAJOR/MINOR/INFO)
|
|
371
|
+
|
|
372
|
+
### 降级条件
|
|
373
|
+
|
|
374
|
+
判定条件(扫描前预判):`[ -f .git ]`(`.git` 为 gitdir 文件,指向 worktree 关联的仓库)或 `git rev-parse --git-dir` 返回含 `/worktrees/` 的路径时,判定当前部署形态为 git worktree。命中 worktree 时跳过 SCM-enabled 扫描尝试,直接进入降级全量扫描;预跳过后的首次扫描即本次全量扫描结果,按第 8 节 dimension 映射统一提交,并在报告注明 SCM 因 worktree 跳过、按降级口径处理。
|
|
375
|
+
|
|
376
|
+
当 SCM 时间戳不可靠导致 new code 期无法正确识别时,降级为全量 issue 口径。
|
|
377
|
+
|
|
378
|
+
降级判据(满足其一即触发):
|
|
379
|
+
- scanner 日志出现 git blame 相关警告(如 SCM 信息获取失败、blame 执行失败)
|
|
380
|
+
- SCM 集成运行时不可用——scanner 报告无法打开 git 仓库(典型于 git worktree 部署形态,worktree 的 `.git` 为 gitdir 文件,内嵌 JGit 无法解析),或项目 `sonar-project.properties` 存在 `sonar.scm.disabled=true`(已显式 `-Dsonar.scm.disabled=false` 覆盖后仍失败)
|
|
381
|
+
- `.git/shallow` 文件存在(shallow clone 历史不完整)
|
|
382
|
+
- 全新仓库或 squash 导入,无历史可溯源
|
|
383
|
+
- `new_lines` 与 `ncloc` 指标对比异常(new code 期行数明显偏离预期,`new_lines=0` 即触发降级)
|
|
384
|
+
|
|
385
|
+
降级处理:
|
|
386
|
+
- 优先复用本次已 ANALYSIS SUCCESSFUL 的全量扫描结果,禁止为修复 SCM 无限重扫(SCM 覆盖尝试最多 1 次)
|
|
387
|
+
- 全量扫描结果按第 8 节 dimension 映射表统一提交,按原始严重级别,不区分是否本轮引入;命中项目级豁免清单的存量问题除外(按 Info 提报,不重新豁免,清单命中由视图标注,无需在此探测)
|
|
388
|
+
- 状态过滤独立于期界过滤,new code 查询与降级全量查询两条路径均须带 `statuses=OPEN,CONFIRMED,REOPENED`
|
|
389
|
+
|
|
390
|
+
## 7. 质量工具配置检查
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
git diff --name-only <baseRef>..HEAD | grep -E "(pmd-rules\.xml|sonar-project\.properties|pom\.xml)"
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
检查本轮 diff 中是否包含质量工具规则/配置文件的改动。若包含,逐一检查以下维度:
|
|
397
|
+
|
|
398
|
+
- 规则是否被删除或降级(如 PMD priority 从 1 改为 5,或规则项被整条移除)
|
|
399
|
+
- 是否新增了过宽的 exclude/include 配置(如排除整个命名空间、跳过核心架构检查)
|
|
400
|
+
- `pom.xml` 中 `spotless-maven-plugin` / `pmd-maven-plugin` 等质量插件配置是否被弱化(跳过执行、降低阻塞等级)
|
|
401
|
+
- `pmd-maven-plugin` 的 CPD 配置是否被弱化(`cpd-check` goal 被移除、`<minimumTokens>` 被过度调高、`<excludes>` 或 `excludeFromFailureFile` 过宽排除——均属弱化形态)
|
|
402
|
+
|
|
403
|
+
检查结果:
|
|
404
|
+
|
|
405
|
+
- 配置无削弱 → 通过
|
|
406
|
+
- 配置存在削弱 → 工具层 issue,severity=Medium,每条削弱映射为一个 issue
|
|
407
|
+
|
|
408
|
+
## 8. 工具输出 → 统一 issue dimension 映射表
|
|
409
|
+
|
|
410
|
+
每个工具的输出必须翻译为统一 issue 结构,并携带 `dimension` 字段归属于 5 维之一:
|
|
411
|
+
|
|
412
|
+
### 统一 issue 结构
|
|
413
|
+
|
|
414
|
+
```json
|
|
415
|
+
{
|
|
416
|
+
"file": "<相对路径>",
|
|
417
|
+
"line": <行号>,
|
|
418
|
+
"dimension": "style|architecture|performance|security|maintainability",
|
|
419
|
+
"severity": "Critical|High|Medium|Low|Info",
|
|
420
|
+
"description": "<问题描述>",
|
|
421
|
+
"suggestion": "<修改建议>"
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### 映射规则
|
|
426
|
+
|
|
427
|
+
| 工具 | 原始分类/规则 | 映射 dimension |
|
|
428
|
+
|------|--------------|---------------|
|
|
429
|
+
| **PMD** | `category/java/design.xml` 规则 | `architecture` |
|
|
430
|
+
| **PMD** | `category/java/codestyle.xml` 规则 | `style` |
|
|
431
|
+
| **PMD** | `category/java/errorprone.xml` 规则 | `maintainability` |
|
|
432
|
+
| **PMD** | `category/java/bestpractices.xml` 规则 | `maintainability` |
|
|
433
|
+
| **PMD** | `category/java/performance.xml` 规则 | `performance` |
|
|
434
|
+
| **PMD** | CPD 重复代码 | `maintainability` |
|
|
435
|
+
| **SonarQube** | `VULNERABILITY` / `SECURITY_HOTSPOT` | `security` |
|
|
436
|
+
| **SonarQube** | `CODE_SMELL`(与可维护性相关) | `maintainability` |
|
|
437
|
+
| **SonarQube** | `CODE_SMELL`(与格式/命名相关) | `style` |
|
|
438
|
+
| **SonarQube** | `BUG` | `maintainability` |
|
|
439
|
+
| **Spotless** | 所有格式违规 | `style` |
|
|
440
|
+
| **ArchUnit** | 所有架构约束违规 | `architecture` |
|
|
441
|
+
| **UT 编译/运行失败** | 测试失败 | `maintainability` |
|
|
442
|
+
|
|
443
|
+
## 9. 汇总与产出
|
|
444
|
+
|
|
445
|
+
所有工具检查完成后,汇总检查结果并产出检查结果与 issue 清单:
|
|
446
|
+
- 通过/不通过结论:不通过须有至少一个 Low 及以上 issue 作为理由
|
|
447
|
+
- issues:统一 issue 结构列表(每条携带 dimension)
|
|
448
|
+
- 修复/豁免归属:已修复条目与申请豁免条目按需列出对应 issue id
|
|
449
|
+
|
|
450
|
+
完成后清理隔离环境:
|
|
451
|
+
|
|
452
|
+
1. **删除本 change 隔离项目**:先经 Web API 查询确认项目存在(`/api/projects/search?project=<项目原key>-<namespace>`),确认存在后调用 `/api/projects/delete?project=<项目原key>-<namespace>` 删除;delete 返回 404(项目不存在)视为已删除(幂等)。admin 凭据按第 6 节「admin 凭据来源」回退链取得。项目删除后如需重扫,由「判断 project 存在性并预创建」节的 search-then-create 逻辑自动重建,无需人工干预。
|
|
453
|
+
2. `docker compose -p <namespace> down`(不影响其他 change 的容器)。
|
|
454
|
+
|
|
455
|
+
清理后自检:无残留服务进程、无残留隔离容器、无残留隔离扫描分析项目(按隔离标识查询不存在),全部无残留即通过。
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# PMD 规则索引
|
|
2
|
+
|
|
3
|
+
规则定义以官方源为准,本索引不记录阈值数值——阈值随 PMD 版本与项目 ruleset 配置变化,仅作导航。未收录规则按 SKILL.md「PMD 规则语义定位」方法论直拉官方源。
|
|
4
|
+
|
|
5
|
+
> 说明:ExcessiveMethodLength(design.xml)、UnusedImports(bestpractices.xml)为 PMD 6 规则,PMD 7 已移除(UnusedImports 由 codestyle 的 UnnecessaryImport 承接);AvoidCatchingGenericException 在 PMD ≤7.17 属 design,7.18 起迁往 errorprone(design 留 deprecated 引用);引用官方文档锚点时按项目实际 PMD 版本核对,命中此类历史规则名时以当前版本官方源反查为准。
|
|
6
|
+
|
|
7
|
+
| 规则全名 | 分类 | 判定逻辑类型 | 官方源 |
|
|
8
|
+
|----------|------|-------------|--------|
|
|
9
|
+
| `category/java/design.xml/TooManyMethods` | java/design | XPath | https://docs.pmd-code.org/pmd-doc-<版本>/pmd_rules_java_design.html#toomanymethods |
|
|
10
|
+
| `category/java/design.xml/NcssCount` | java/design | 规则类 | https://docs.pmd-code.org/pmd-doc-<版本>/pmd_rules_java_design.html#ncsscount |
|
|
11
|
+
| `category/java/design.xml/ExcessiveMethodLength` | java/design | 规则类 | https://docs.pmd-code.org/pmd-doc-<版本>/pmd_rules_java_design.html#excessivemethodlength |
|
|
12
|
+
| `category/java/design.xml/CyclomaticComplexity` | java/design | 规则类 | https://docs.pmd-code.org/pmd-doc-<版本>/pmd_rules_java_design.html#cyclomaticcomplexity |
|
|
13
|
+
| `category/java/errorprone.xml/AvoidCatchingGenericException` | java/errorprone | XPath | https://docs.pmd-code.org/pmd-doc-<版本>/pmd_rules_java_errorprone.html#avoidcatchinggenericexception |
|
|
14
|
+
| `category/java/bestpractices.xml/UnusedImports` | java/bestpractices | 规则类 | https://docs.pmd-code.org/pmd-doc-<版本>/pmd_rules_java_bestpractices.html#unusedimports |
|
|
15
|
+
| `category/java/bestpractices.xml/SystemPrintln` | java/bestpractices | XPath | https://docs.pmd-code.org/pmd-doc-<版本>/pmd_rules_java_bestpractices.html#systemprintln |
|
|
16
|
+
| `category/java/errorprone.xml/CloseResource` | java/errorprone | 规则类 | https://docs.pmd-code.org/pmd-doc-<版本>/pmd_rules_java_errorprone.html#closeresource |
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: java-quality-tool-improve
|
|
3
|
+
description: 仅限 Java 后端开发场景。工具规则改进指南。Quality reviewer(architecture/maintainability/style/performance/security)加载,用于将 Java 项目中可工具化的 pattern 转化为具体的 ArchUnit / PMD / Spotless / SonarQube 规则草案。skill 提供各场景下工具配置改动的信号表与规则模板。
|
|
4
|
+
capabilities: ["tool-improvement", "tech-stack-java"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
> **项目规范优先**:本 skill 所列约定为推荐标准。若项目已有明确规范且与本 skill 不一致,以项目规范为准。
|
|
8
|
+
|
|
9
|
+
## 识别可工具化 pattern
|
|
10
|
+
|
|
11
|
+
以下信号表明一个问题可能可以工具化:
|
|
12
|
+
|
|
13
|
+
| 信号 | 示例 | 对应工具 |
|
|
14
|
+
|------|------|---------|
|
|
15
|
+
| 包/层依赖违规 | domain 层 import Spring 注解;interfaces 层直连 infrastructure 层 | ArchUnit |
|
|
16
|
+
| 特定注解/命名模式违规 | 类级别 @SuppressWarnings | ArchUnit 或 PMD |
|
|
17
|
+
| 特定方法签名模式违规 | domain 实体暴露 public setter | ArchUnit |
|
|
18
|
+
| 代码结构/复杂度违规 | 方法超 100 行 | PMD |
|
|
19
|
+
| 格式化违规 | 缩进/换行不符合团队约定 | Spotless |
|
|
20
|
+
| 安全漏洞模式 | SQL 拼接、硬编码凭证 | SonarQube |
|
|
21
|
+
| 覆盖率误报 | DTO/POJO/Lombok/配置类被覆盖率检查标记为未覆盖 | JaCoCo/SonarQube |
|
|
22
|
+
|
|
23
|
+
## 规则草案模板
|
|
24
|
+
|
|
25
|
+
### ArchUnit 规则
|
|
26
|
+
|
|
27
|
+
规则建议须附规则代码正文与验证命令。agent 必须按以下顺序自行推断规则文件路径,**禁止预设固定路径**:
|
|
28
|
+
|
|
29
|
+
1. **查现有测试**:扫描项目已有 ArchUnit 测试文件(grep `ArchUnit`、`archunit`),沿用其所在包路径和目录结构
|
|
30
|
+
2. **查构建配置**:如无现有 ArchUnit 测试,读取 `pom.xml` / `build.gradle` / `build.gradle.kts` 确定测试源目录(默认 `src/test/java`)和项目组/包前缀
|
|
31
|
+
3. **兜底**:以上均无可用信息时,从项目源码文件推断基础包 + 测试源目录 `src/test/java`
|
|
32
|
+
|
|
33
|
+
规则内容按检测到的项目分层/模块约定编写 ArchUnit 断言:
|
|
34
|
+
|
|
35
|
+
```java
|
|
36
|
+
@Test
|
|
37
|
+
void {testMethodName}() {
|
|
38
|
+
classes()
|
|
39
|
+
.that().{条件}
|
|
40
|
+
.should().{约束}
|
|
41
|
+
.check(importedClasses());
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- **验证命令**:agent 按实际创建的文件名(含包路径)拼接,格式 `mvn test -Dtest="{全限定类名}"`——禁止预设通配模式,因各项目测试类命名规则不同
|
|
46
|
+
|
|
47
|
+
### PMD 规则
|
|
48
|
+
|
|
49
|
+
规则建议须附待追加 XML 块与验证命令:
|
|
50
|
+
|
|
51
|
+
```xml
|
|
52
|
+
<!-- 规则文件位置:src/main/resources/pmd-rules.xml -->
|
|
53
|
+
<!-- 在 <ruleset> 中追加以下规则 -->
|
|
54
|
+
|
|
55
|
+
<rule name="{规则名}"
|
|
56
|
+
language="java"
|
|
57
|
+
message="{违规信息}"
|
|
58
|
+
class="{PMD 规则类名}"
|
|
59
|
+
priority="{1-5,1=最高}">
|
|
60
|
+
<description>{规则描述}</description>
|
|
61
|
+
<priority>{1-5}</priority>
|
|
62
|
+
<properties>
|
|
63
|
+
<property name="xpath" value="{XPath 表达式}" />
|
|
64
|
+
</properties>
|
|
65
|
+
</rule>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- PMD 规则文件位置:`src/main/resources/pmd-rules.xml`
|
|
69
|
+
- 新增规则追加在 `<ruleset>` 元素内
|
|
70
|
+
- 验证命令:`mvn pmd:check`
|
|
71
|
+
|
|
72
|
+
对于简单模式,推荐使用 XPath 规则;复杂逻辑使用 Java 规则类(需放在独立模块中)。
|
|
73
|
+
|
|
74
|
+
### Spotless 规则
|
|
75
|
+
|
|
76
|
+
Spotless 使用 Palantir Java Format,自定义空间有限。多数格式问题通过更新 pom.xml 中的 `spotless-maven-plugin` 配置实现:
|
|
77
|
+
|
|
78
|
+
- 规则位置:`pom.xml` → `spotless-maven-plugin` 配置块
|
|
79
|
+
- 验证命令:`mvn spotless:check`
|
|
80
|
+
- 自动修复:`mvn spotless:apply`
|
|
81
|
+
|
|
82
|
+
### SonarQube 规则
|
|
83
|
+
|
|
84
|
+
SonarQube 使用内置规则库(6,500+),一般无需自定义规则。工具改进集中在**抑制误报**:
|
|
85
|
+
|
|
86
|
+
- **框架误报**:POJO 类使用 MapStruct、MyBatis、Lombok 时私有字段被误判为未使用 → 在 `sonar-project.properties` 加 exclusion 排除特定目录/文件
|
|
87
|
+
- **精准抑制**:某规则对特定文件模式产生误报 → 用 `sonar.issue.ignore.multicriteria` 按规则 ID + 文件模式抑制
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
# 完全排除扫描(该目录不参与任何规则检查);覆盖率误报请用 sonar.coverage.exclusions,见下
|
|
91
|
+
sonar.exclusions=**/generated/**,**/model/*.java
|
|
92
|
+
|
|
93
|
+
# 按规则+模式精准抑制
|
|
94
|
+
sonar.issue.ignore.multicriteria=e1
|
|
95
|
+
sonar.issue.ignore.multicriteria.e1.ruleKey=java:S1068
|
|
96
|
+
sonar.issue.ignore.multicriteria.e1.resourceKey=**/model/*.java
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- **覆盖率排除**:POJO/DTO/Lombok/配置类/生成代码等不需单元测试的类被覆盖率检查误报为"未覆盖"时,用 `sonar.coverage.exclusions` 按通配模式跳过覆盖率计算:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
# 按通配模式跳过覆盖率计算(仍参与其他规则扫描)
|
|
103
|
+
sonar.coverage.exclusions=**/model/*.java,**/dto/*.java,**/generated/**
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- `sonar.exclusions` 是完全排除扫描(该目录不参与任何规则检查),`sonar.coverage.exclusions` 仅跳过覆盖率计算、仍参与其他规则扫描。对 POJO/DTO 等应优先用 `sonar.coverage.exclusions`,避免完全排除导致漏检安全规则。
|
|
107
|
+
- **误报抑制与门禁**:项目须通过质量门禁。门禁不通过时先分析是否为误报导致,参照本节排除/抑制方式处理,不得为凑覆盖率扩大排除范围。排除范围仅限确实不需要单元测试的类,过度排除属质量配置削弱。
|
|
108
|
+
|
|
109
|
+
- 配置文件位置:`sonar-project.properties`
|
|
110
|
+
- 验证命令:`sonar-scanner -X`
|
|
111
|
+
|
|
112
|
+
### JaCoCo 排除规则
|
|
113
|
+
|
|
114
|
+
不需单元测试的类(包括但不限于:POJO / DTO / Lombok 注解类、`@Configuration` / `@ConfigurationProperties` 配置类、常量 / 枚举类、`@SpringBootApplication` 启动类、纯接口(无 default 方法)、生成代码)被覆盖率检查误报为"未覆盖"时,在 `jacoco-maven-plugin` 的 `<configuration><excludes>` 中追加 `<exclude>` 条目,排除范围与 SonarQube 覆盖率排除口径一一对应:
|
|
115
|
+
|
|
116
|
+
```xml
|
|
117
|
+
<!-- 规则文件位置:pom.xml → jacoco-maven-plugin <configuration><excludes> 中追加 -->
|
|
118
|
+
<excludes>
|
|
119
|
+
<exclude>**/model/*.class</exclude>
|
|
120
|
+
<exclude>**/dto/*.class</exclude>
|
|
121
|
+
<exclude>**/generated/**</exclude>
|
|
122
|
+
</excludes>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
- 排除范围仅限确实不需要单元测试的类,不得为凑覆盖率扩大排除范围——过度排除属质量配置削弱。
|
|
126
|
+
- 验证命令:`mvn verify -q; echo "BUILD_STATUS=$?"`(含 JaCoCo check 阶段)或 `mvn jacoco:check`,构建成败以退出码为判据
|
|
127
|
+
|
|
128
|
+
## 规则与 severity 映射
|
|
129
|
+
|
|
130
|
+
| 来源 | 级别 | 严重级别 |
|
|
131
|
+
|------|------|---------------|
|
|
132
|
+
| ArchUnit 违规 | — | Medium |
|
|
133
|
+
| PMD priority 1 | — | High |
|
|
134
|
+
| PMD priority 2 | — | Medium |
|
|
135
|
+
| PMD priority 3 | — | Low |
|
|
136
|
+
| SonarQube blocker | — | Critical |
|
|
137
|
+
| SonarQube critical | — | High |
|
|
138
|
+
| SonarQube major | — | Medium |
|
|
139
|
+
| SonarQube minor | — | Low |
|
|
140
|
+
| Spotless 违规 | — | Low |
|
|
141
|
+
|
|
142
|
+
|