-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathquality-gate.yml
More file actions
212 lines (193 loc) · 6.89 KB
/
Copy pathquality-gate.yml
File metadata and controls
212 lines (193 loc) · 6.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# Quality Gate — versioned configuration
#
# All thresholds the Quality Gate workflow honors live here so they can be
# tuned without touching workflow YAML or shell scripts. Read by
# scripts/qg/lib.sh via yq.
#
# Phase rollout: every floor below is enforced (blocking) by default.
# Setting `enforcement: warn` on a floor flips it to advisory-only — useful
# while introducing a new check without surprising contributors.
version: 1
# Branches the Quality Gate runs against (mirrors workflow `on.pull_request.branches`).
target_branches:
- main
- develop
# Bot actors whose PRs skip the gate entirely. Release-please reshuffles
# changelogs and version bumps; running coverage ratchet against those is noise.
skip_actors:
- release-please[bot]
- github-actions[bot]
- dependabot[bot]
# Floor 1 — Build / static analysis. Already covered by 1-ci.yml; the
# Quality Gate re-runs them so the single required check is self-contained
# (a future cleanup of 1-ci.yml does not silently widen the gate).
build:
enforcement: blocking
go_vet: true
gofmt: true
golangci_lint:
version: v1.64.8
timeout: 5m
# Floor 2 — Total coverage ratchet vs. main. Baseline is stored as a commit
# status `quality-gate/coverage` on every push to main by
# quality-gate-baseline.yml. First run (no baseline) bootstraps and passes.
coverage_total:
enforcement: blocking
# Floor below which we never go even if main regressed.
hard_floor_pct: 27.0
# Tolerance to absorb flake (line-count drift on retries, etc.).
tolerance_pct: 0.1
# Step-change protection — drops larger than this against the baseline
# are treated as a one-off re-bootstrap (methodology change, package
# reshuffle). The hard floor still applies. After the PR merges, the
# baseline workflow re-publishes from the new tree.
step_change_pp: 5.0
# Floor 3 — Patch coverage on the diff. Computed by tools/qg/cmd/qg-diffcover
# (Go-native, no Python dep) comparing to origin/<base>. Excludes generated
# and test files.
#
# per_path applies stricter thresholds to security- and quality-critical
# paths. Hot or fragile areas (LLM clients, auth, the gate tooling itself)
# carry higher floors than the global default. Any file in the diff that
# matches one of these patterns counts toward both the global and the
# per-path metric; the gate fails if EITHER is breached.
coverage_patch:
enforcement: blocking
threshold_pct: 60
# PRs labelled `refactor-only` use a relaxed threshold (move-don't-add).
refactor_threshold_pct: 30
exclude:
- "**/*_test.go"
- "**/*.pb.go"
- "proto/**"
- "tools/docgen/**"
# CLI mains under tools/qg/cmd are thin flag-parsing glue; the
# tested logic lives in the sibling packages (diffcover, i18nparity,
# providerparity, ...) which the per-path bar below holds at 75 percent.
# Excluding the mains keeps the gate from punishing CLI wrappers that
# do not have a meaningful coverage target.
- "tools/qg/cmd/**"
per_path:
- path: "auth/**"
threshold_pct: 80
- path: "llm/**"
threshold_pct: 70
- path: "tools/qg/**"
threshold_pct: 75
- path: "operator/controllers/**"
threshold_pct: 70
# Floor 4 — AI / hand-rolled code smells scanned in the diff (Go non-test only).
ai_smells:
enforcement: blocking
checks:
todo_fixme_xxx: true
panic_in_new_code: true
interface_any_in_public_api: true
hardcoded_user_strings: true # heuristic, runs on cli/ handlers only
obvious_secrets: true
new_dependency_without_label: true # bypass: deps:approved
removed_exports_without_label: true # bypass: breaking-change
# Paths excluded from smells scan (noise reduction).
exclude:
- "**/*_test.go"
- "**/*.pb.go"
- "proto/**"
- "vendor/**"
- "scripts/qg/**"
# Floor 5 — Scope discipline. Bypassed via labels for legitimate large PRs.
scope_budget:
enforcement: blocking
loc:
warn: 800
block: 2000
bypass_label: large-pr-approved
files:
warn: 25
block: 50
bypass_label: wide-pr-approved
# Paths counted as "tooling" — they still count toward LOC, but the warning
# explicitly notes the tooling share so reviewers see signal vs. noise.
tooling_paths:
- ".github/**"
- "scripts/**"
- "Makefile"
- "**/*.md"
# Floor 6 — E2E + race. Runs the e2e/ package which builds the binary itself.
e2e:
enforcement: blocking
timeout_minutes: 15
# Floor 7 — Commit hygiene. Catches the two release-please/repo conventions
# that have bitten this repo before (see feedback_no_coauthor.md and
# feedback_no_code_in_commit_body.md in user memory).
commit_lint:
enforcement: blocking
forbid_co_authored_by: true
forbid_nested_parens_in_body: true
# Conventional Commits prefix on the FIRST commit of the PR (release-please
# uses the merge commit subject; we still want PR-level discipline).
require_conventional_commits: true
allowed_types:
- feat
- fix
- refactor
- perf
- docs
- test
- build
- ci
- chore
- revert
- style
# Floor 8 — Cyclomatic complexity on changed files only. Existing code is
# grandfathered (project-wide gocyclo is 70); new code is held to 30.
cyclo_new:
enforcement: blocking
max_complexity: 30
# Files whose path matches any of these are exempt (legacy hot spots that
# are intentionally large; splitting them is its own refactor).
exempt:
- "cli/agent_mode.go"
- "cli/cli.go"
- "cli/commands.go"
- "cli/command_handler_plugins.go"
- "main.go"
# Floor 9 — Secrets scan via gitleaks on the PR diff.
secrets_scan:
enforcement: blocking
# Floor 10 — i18n cross-locale + Go-source key parity. Runs against
# the whole repo; locale parity is a global invariant.
i18n_parity:
enforcement: blocking
# Floor 11 — controller-gen CRD drift detection. Only runs when the
# diff touches operator/api/ or operator/config/crd/.
crd_drift:
enforcement: blocking
# Floor 12 — license header presence on NEW Go files. Existing files
# are grandfathered (most of the tree predates this gate).
license_headers:
enforcement: blocking
# Floor 13 — apidiff against the base ref for every package whose
# Go files changed. Bypass label: `breaking-change`.
api_breaking:
enforcement: blocking
# Floor 14 — binary size budget for the final release binaries.
# Tune when intentional growth is announced.
binary_size:
enforcement: blocking
chatcli_mb: 100
operator_mb: 100
# Floor 15 — LLM provider parity matrix. Every catalog provider
# must be wired through tools/qg/providerparity touch points
# modulo documented exemptions.
provider_parity:
enforcement: blocking
# Bypass labels — applied manually by maintainers when an exception is
# legitimate. The gate logs which bypass was used so it shows up in the
# sticky comment.
bypass_labels:
- large-pr-approved
- wide-pr-approved
- deps:approved
- breaking-change
- refactor-only
- quality-gate-skip # nuclear option; logs prominently in summary