tech-hub-skills 1.2.0 → 1.5.2

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.
Files changed (198) hide show
  1. package/{LICENSE → .claude/LICENSE} +21 -21
  2. package/.claude/README.md +291 -0
  3. package/.claude/bin/cli.js +266 -0
  4. package/{bin → .claude/bin}/copilot.js +182 -182
  5. package/{bin → .claude/bin}/postinstall.js +42 -42
  6. package/{tech_hub_skills/skills → .claude/commands}/README.md +336 -336
  7. package/{tech_hub_skills/skills → .claude/commands}/ai-engineer.md +104 -104
  8. package/{tech_hub_skills/skills → .claude/commands}/aws.md +143 -143
  9. package/{tech_hub_skills/skills → .claude/commands}/azure.md +149 -149
  10. package/{tech_hub_skills/skills → .claude/commands}/backend-developer.md +108 -108
  11. package/{tech_hub_skills/skills → .claude/commands}/code-review.md +399 -399
  12. package/{tech_hub_skills/skills → .claude/commands}/compliance-automation.md +747 -747
  13. package/{tech_hub_skills/skills → .claude/commands}/compliance-officer.md +108 -108
  14. package/{tech_hub_skills/skills → .claude/commands}/data-engineer.md +113 -113
  15. package/{tech_hub_skills/skills → .claude/commands}/data-governance.md +102 -102
  16. package/{tech_hub_skills/skills → .claude/commands}/data-scientist.md +123 -123
  17. package/{tech_hub_skills/skills → .claude/commands}/database-admin.md +109 -109
  18. package/{tech_hub_skills/skills → .claude/commands}/devops.md +160 -160
  19. package/{tech_hub_skills/skills → .claude/commands}/docker.md +160 -160
  20. package/{tech_hub_skills/skills → .claude/commands}/enterprise-dashboard.md +613 -613
  21. package/{tech_hub_skills/skills → .claude/commands}/finops.md +184 -184
  22. package/{tech_hub_skills/skills → .claude/commands}/frontend-developer.md +108 -108
  23. package/{tech_hub_skills/skills → .claude/commands}/gcp.md +143 -143
  24. package/{tech_hub_skills/skills → .claude/commands}/ml-engineer.md +115 -115
  25. package/{tech_hub_skills/skills → .claude/commands}/mlops.md +187 -187
  26. package/{tech_hub_skills/skills → .claude/commands}/network-engineer.md +109 -109
  27. package/{tech_hub_skills/skills → .claude/commands}/optimization-advisor.md +329 -329
  28. package/{tech_hub_skills/skills → .claude/commands}/orchestrator.md +623 -623
  29. package/{tech_hub_skills/skills → .claude/commands}/platform-engineer.md +102 -102
  30. package/{tech_hub_skills/skills → .claude/commands}/process-automation.md +226 -226
  31. package/{tech_hub_skills/skills → .claude/commands}/process-changelog.md +184 -184
  32. package/{tech_hub_skills/skills → .claude/commands}/process-documentation.md +484 -484
  33. package/{tech_hub_skills/skills → .claude/commands}/process-kanban.md +324 -324
  34. package/{tech_hub_skills/skills → .claude/commands}/process-versioning.md +214 -214
  35. package/{tech_hub_skills/skills → .claude/commands}/product-designer.md +104 -104
  36. package/{tech_hub_skills/skills → .claude/commands}/project-starter.md +443 -443
  37. package/{tech_hub_skills/skills → .claude/commands}/qa-engineer.md +109 -109
  38. package/{tech_hub_skills/skills → .claude/commands}/security-architect.md +135 -135
  39. package/{tech_hub_skills/skills → .claude/commands}/sre.md +109 -109
  40. package/{tech_hub_skills/skills → .claude/commands}/system-design.md +126 -126
  41. package/{tech_hub_skills/skills → .claude/commands}/technical-writer.md +101 -101
  42. package/.claude/package.json +46 -0
  43. package/{tech_hub_skills → .claude}/roles/ai-engineer/skills/01-prompt-engineering/README.md +252 -252
  44. package/.claude/roles/ai-engineer/skills/01-prompt-engineering/prompt_ab_tester.py +356 -0
  45. package/.claude/roles/ai-engineer/skills/01-prompt-engineering/prompt_template_manager.py +274 -0
  46. package/.claude/roles/ai-engineer/skills/01-prompt-engineering/token_cost_estimator.py +324 -0
  47. package/{tech_hub_skills → .claude}/roles/ai-engineer/skills/02-rag-pipeline/README.md +448 -448
  48. package/.claude/roles/ai-engineer/skills/02-rag-pipeline/document_chunker.py +336 -0
  49. package/.claude/roles/ai-engineer/skills/02-rag-pipeline/rag_pipeline.sql +213 -0
  50. package/{tech_hub_skills → .claude}/roles/ai-engineer/skills/03-agent-orchestration/README.md +599 -599
  51. package/{tech_hub_skills → .claude}/roles/ai-engineer/skills/04-llm-guardrails/README.md +735 -735
  52. package/{tech_hub_skills → .claude}/roles/ai-engineer/skills/05-vector-embeddings/README.md +711 -711
  53. package/{tech_hub_skills → .claude}/roles/ai-engineer/skills/06-llm-evaluation/README.md +777 -777
  54. package/{tech_hub_skills → .claude}/roles/azure/skills/01-infrastructure-fundamentals/README.md +264 -264
  55. package/{tech_hub_skills → .claude}/roles/azure/skills/02-data-factory/README.md +264 -264
  56. package/{tech_hub_skills → .claude}/roles/azure/skills/03-synapse-analytics/README.md +264 -264
  57. package/{tech_hub_skills → .claude}/roles/azure/skills/04-databricks/README.md +264 -264
  58. package/{tech_hub_skills → .claude}/roles/azure/skills/05-functions/README.md +264 -264
  59. package/{tech_hub_skills → .claude}/roles/azure/skills/06-kubernetes-service/README.md +264 -264
  60. package/{tech_hub_skills → .claude}/roles/azure/skills/07-openai-service/README.md +264 -264
  61. package/{tech_hub_skills → .claude}/roles/azure/skills/08-machine-learning/README.md +264 -264
  62. package/{tech_hub_skills → .claude}/roles/azure/skills/09-storage-adls/README.md +264 -264
  63. package/{tech_hub_skills → .claude}/roles/azure/skills/10-networking/README.md +264 -264
  64. package/{tech_hub_skills → .claude}/roles/azure/skills/11-sql-cosmos/README.md +264 -264
  65. package/{tech_hub_skills → .claude}/roles/azure/skills/12-event-hubs/README.md +264 -264
  66. package/{tech_hub_skills → .claude}/roles/code-review/skills/01-automated-code-review/README.md +394 -394
  67. package/{tech_hub_skills → .claude}/roles/code-review/skills/02-pr-review-workflow/README.md +427 -427
  68. package/{tech_hub_skills → .claude}/roles/code-review/skills/03-code-quality-gates/README.md +518 -518
  69. package/{tech_hub_skills → .claude}/roles/code-review/skills/04-reviewer-assignment/README.md +504 -504
  70. package/{tech_hub_skills → .claude}/roles/code-review/skills/05-review-analytics/README.md +540 -540
  71. package/{tech_hub_skills → .claude}/roles/data-engineer/skills/01-lakehouse-architecture/README.md +550 -550
  72. package/.claude/roles/data-engineer/skills/01-lakehouse-architecture/bronze_ingestion.py +337 -0
  73. package/.claude/roles/data-engineer/skills/01-lakehouse-architecture/medallion_queries.sql +300 -0
  74. package/{tech_hub_skills → .claude}/roles/data-engineer/skills/02-etl-pipeline/README.md +580 -580
  75. package/{tech_hub_skills → .claude}/roles/data-engineer/skills/03-data-quality/README.md +579 -579
  76. package/{tech_hub_skills → .claude}/roles/data-engineer/skills/04-streaming-pipelines/README.md +608 -608
  77. package/{tech_hub_skills → .claude}/roles/data-engineer/skills/05-performance-optimization/README.md +547 -547
  78. package/{tech_hub_skills → .claude}/roles/data-governance/skills/01-data-catalog/README.md +112 -112
  79. package/{tech_hub_skills → .claude}/roles/data-governance/skills/02-data-lineage/README.md +129 -129
  80. package/{tech_hub_skills → .claude}/roles/data-governance/skills/03-data-quality-framework/README.md +182 -182
  81. package/{tech_hub_skills → .claude}/roles/data-governance/skills/04-access-control/README.md +39 -39
  82. package/{tech_hub_skills → .claude}/roles/data-governance/skills/05-master-data-management/README.md +40 -40
  83. package/{tech_hub_skills → .claude}/roles/data-governance/skills/06-compliance-privacy/README.md +46 -46
  84. package/{tech_hub_skills → .claude}/roles/data-scientist/skills/01-eda-automation/README.md +230 -230
  85. package/.claude/roles/data-scientist/skills/01-eda-automation/eda_generator.py +446 -0
  86. package/{tech_hub_skills → .claude}/roles/data-scientist/skills/02-statistical-modeling/README.md +264 -264
  87. package/{tech_hub_skills → .claude}/roles/data-scientist/skills/03-feature-engineering/README.md +264 -264
  88. package/{tech_hub_skills → .claude}/roles/data-scientist/skills/04-predictive-modeling/README.md +264 -264
  89. package/{tech_hub_skills → .claude}/roles/data-scientist/skills/05-customer-analytics/README.md +264 -264
  90. package/{tech_hub_skills → .claude}/roles/data-scientist/skills/06-campaign-analysis/README.md +264 -264
  91. package/{tech_hub_skills → .claude}/roles/data-scientist/skills/07-experimentation/README.md +264 -264
  92. package/{tech_hub_skills → .claude}/roles/data-scientist/skills/08-data-visualization/README.md +264 -264
  93. package/{tech_hub_skills → .claude}/roles/devops/skills/01-cicd-pipeline/README.md +264 -264
  94. package/{tech_hub_skills → .claude}/roles/devops/skills/02-container-orchestration/README.md +264 -264
  95. package/{tech_hub_skills → .claude}/roles/devops/skills/03-infrastructure-as-code/README.md +264 -264
  96. package/{tech_hub_skills → .claude}/roles/devops/skills/04-gitops/README.md +264 -264
  97. package/{tech_hub_skills → .claude}/roles/devops/skills/05-environment-management/README.md +264 -264
  98. package/{tech_hub_skills → .claude}/roles/devops/skills/06-automated-testing/README.md +264 -264
  99. package/{tech_hub_skills → .claude}/roles/devops/skills/07-release-management/README.md +264 -264
  100. package/{tech_hub_skills → .claude}/roles/devops/skills/08-monitoring-alerting/README.md +264 -264
  101. package/{tech_hub_skills → .claude}/roles/devops/skills/09-devsecops/README.md +265 -265
  102. package/{tech_hub_skills → .claude}/roles/finops/skills/01-cost-visibility/README.md +264 -264
  103. package/{tech_hub_skills → .claude}/roles/finops/skills/02-resource-tagging/README.md +264 -264
  104. package/{tech_hub_skills → .claude}/roles/finops/skills/03-budget-management/README.md +264 -264
  105. package/{tech_hub_skills → .claude}/roles/finops/skills/04-reserved-instances/README.md +264 -264
  106. package/{tech_hub_skills → .claude}/roles/finops/skills/05-spot-optimization/README.md +264 -264
  107. package/{tech_hub_skills → .claude}/roles/finops/skills/06-storage-tiering/README.md +264 -264
  108. package/{tech_hub_skills → .claude}/roles/finops/skills/07-compute-rightsizing/README.md +264 -264
  109. package/{tech_hub_skills → .claude}/roles/finops/skills/08-chargeback/README.md +264 -264
  110. package/{tech_hub_skills → .claude}/roles/ml-engineer/skills/01-mlops-pipeline/README.md +566 -566
  111. package/{tech_hub_skills → .claude}/roles/ml-engineer/skills/02-feature-engineering/README.md +655 -655
  112. package/{tech_hub_skills → .claude}/roles/ml-engineer/skills/03-model-training/README.md +704 -704
  113. package/{tech_hub_skills → .claude}/roles/ml-engineer/skills/04-model-serving/README.md +845 -845
  114. package/{tech_hub_skills → .claude}/roles/ml-engineer/skills/05-model-monitoring/README.md +874 -874
  115. package/{tech_hub_skills → .claude}/roles/mlops/skills/01-ml-pipeline-orchestration/README.md +264 -264
  116. package/{tech_hub_skills → .claude}/roles/mlops/skills/02-experiment-tracking/README.md +264 -264
  117. package/{tech_hub_skills → .claude}/roles/mlops/skills/03-model-registry/README.md +264 -264
  118. package/{tech_hub_skills → .claude}/roles/mlops/skills/04-feature-store/README.md +264 -264
  119. package/{tech_hub_skills → .claude}/roles/mlops/skills/05-model-deployment/README.md +264 -264
  120. package/{tech_hub_skills → .claude}/roles/mlops/skills/06-model-observability/README.md +264 -264
  121. package/{tech_hub_skills → .claude}/roles/mlops/skills/07-data-versioning/README.md +264 -264
  122. package/{tech_hub_skills → .claude}/roles/mlops/skills/08-ab-testing/README.md +264 -264
  123. package/{tech_hub_skills → .claude}/roles/mlops/skills/09-automated-retraining/README.md +264 -264
  124. package/{tech_hub_skills → .claude}/roles/platform-engineer/skills/01-internal-developer-platform/README.md +153 -153
  125. package/{tech_hub_skills → .claude}/roles/platform-engineer/skills/02-self-service-infrastructure/README.md +57 -57
  126. package/{tech_hub_skills → .claude}/roles/platform-engineer/skills/03-slo-sli-management/README.md +59 -59
  127. package/{tech_hub_skills → .claude}/roles/platform-engineer/skills/04-developer-experience/README.md +57 -57
  128. package/{tech_hub_skills → .claude}/roles/platform-engineer/skills/05-incident-management/README.md +73 -73
  129. package/{tech_hub_skills → .claude}/roles/platform-engineer/skills/06-capacity-management/README.md +59 -59
  130. package/{tech_hub_skills → .claude}/roles/product-designer/skills/01-requirements-discovery/README.md +407 -407
  131. package/{tech_hub_skills → .claude}/roles/product-designer/skills/02-user-research/README.md +382 -382
  132. package/{tech_hub_skills → .claude}/roles/product-designer/skills/03-brainstorming-ideation/README.md +437 -437
  133. package/{tech_hub_skills → .claude}/roles/product-designer/skills/04-ux-design/README.md +496 -496
  134. package/{tech_hub_skills → .claude}/roles/product-designer/skills/05-product-market-fit/README.md +376 -376
  135. package/{tech_hub_skills → .claude}/roles/product-designer/skills/06-stakeholder-management/README.md +412 -412
  136. package/{tech_hub_skills → .claude}/roles/security-architect/skills/01-pii-detection/README.md +319 -319
  137. package/{tech_hub_skills → .claude}/roles/security-architect/skills/02-threat-modeling/README.md +264 -264
  138. package/{tech_hub_skills → .claude}/roles/security-architect/skills/03-infrastructure-security/README.md +264 -264
  139. package/{tech_hub_skills → .claude}/roles/security-architect/skills/04-iam/README.md +264 -264
  140. package/{tech_hub_skills → .claude}/roles/security-architect/skills/05-application-security/README.md +264 -264
  141. package/{tech_hub_skills → .claude}/roles/security-architect/skills/06-secrets-management/README.md +264 -264
  142. package/{tech_hub_skills → .claude}/roles/security-architect/skills/07-security-monitoring/README.md +264 -264
  143. package/{tech_hub_skills → .claude}/roles/system-design/skills/01-architecture-patterns/README.md +337 -337
  144. package/{tech_hub_skills → .claude}/roles/system-design/skills/02-requirements-engineering/README.md +264 -264
  145. package/{tech_hub_skills → .claude}/roles/system-design/skills/03-scalability/README.md +264 -264
  146. package/{tech_hub_skills → .claude}/roles/system-design/skills/04-high-availability/README.md +264 -264
  147. package/{tech_hub_skills → .claude}/roles/system-design/skills/05-cost-optimization-design/README.md +264 -264
  148. package/{tech_hub_skills → .claude}/roles/system-design/skills/06-api-design/README.md +264 -264
  149. package/{tech_hub_skills → .claude}/roles/system-design/skills/07-observability-architecture/README.md +264 -264
  150. package/{tech_hub_skills → .claude}/roles/system-design/skills/08-process-automation/PROCESS_TEMPLATE.md +336 -336
  151. package/{tech_hub_skills → .claude}/roles/system-design/skills/08-process-automation/README.md +521 -521
  152. package/.claude/roles/system-design/skills/08-process-automation/ai_prompt_generator.py +744 -0
  153. package/.claude/roles/system-design/skills/08-process-automation/automation_recommender.py +688 -0
  154. package/.claude/roles/system-design/skills/08-process-automation/plan_generator.py +679 -0
  155. package/.claude/roles/system-design/skills/08-process-automation/process_analyzer.py +528 -0
  156. package/.claude/roles/system-design/skills/08-process-automation/process_parser.py +684 -0
  157. package/.claude/roles/system-design/skills/08-process-automation/role_matcher.py +615 -0
  158. package/.claude/skills/README.md +336 -0
  159. package/.claude/skills/ai-engineer.md +104 -0
  160. package/.claude/skills/aws.md +143 -0
  161. package/.claude/skills/azure.md +149 -0
  162. package/.claude/skills/backend-developer.md +108 -0
  163. package/.claude/skills/code-review.md +399 -0
  164. package/.claude/skills/compliance-automation.md +747 -0
  165. package/.claude/skills/compliance-officer.md +108 -0
  166. package/.claude/skills/data-engineer.md +113 -0
  167. package/.claude/skills/data-governance.md +102 -0
  168. package/.claude/skills/data-scientist.md +123 -0
  169. package/.claude/skills/database-admin.md +109 -0
  170. package/.claude/skills/devops.md +160 -0
  171. package/.claude/skills/docker.md +160 -0
  172. package/.claude/skills/enterprise-dashboard.md +613 -0
  173. package/.claude/skills/finops.md +184 -0
  174. package/.claude/skills/frontend-developer.md +108 -0
  175. package/.claude/skills/gcp.md +143 -0
  176. package/.claude/skills/ml-engineer.md +115 -0
  177. package/.claude/skills/mlops.md +187 -0
  178. package/.claude/skills/network-engineer.md +109 -0
  179. package/.claude/skills/optimization-advisor.md +329 -0
  180. package/.claude/skills/orchestrator.md +623 -0
  181. package/.claude/skills/platform-engineer.md +102 -0
  182. package/.claude/skills/process-automation.md +226 -0
  183. package/.claude/skills/process-changelog.md +184 -0
  184. package/.claude/skills/process-documentation.md +484 -0
  185. package/.claude/skills/process-kanban.md +324 -0
  186. package/.claude/skills/process-versioning.md +214 -0
  187. package/.claude/skills/product-designer.md +104 -0
  188. package/.claude/skills/project-starter.md +443 -0
  189. package/.claude/skills/qa-engineer.md +109 -0
  190. package/.claude/skills/security-architect.md +135 -0
  191. package/.claude/skills/sre.md +109 -0
  192. package/.claude/skills/system-design.md +126 -0
  193. package/.claude/skills/technical-writer.md +101 -0
  194. package/.gitattributes +2 -0
  195. package/GITHUB_COPILOT.md +106 -0
  196. package/README.md +192 -291
  197. package/package.json +16 -46
  198. package/bin/cli.js +0 -241
@@ -1,518 +1,518 @@
1
- # cr-03: Code Quality Gates
2
-
3
- Enforce quality standards with branch protection, required checks, and merge policies.
4
-
5
- ## Overview
6
-
7
- Quality gates are automated checkpoints that code must pass before merging. They ensure consistent standards, prevent regressions, and protect production branches from unsafe changes.
8
-
9
- ## Capabilities
10
-
11
- ### Branch Protection
12
- - Protected branch configuration
13
- - Required status checks
14
- - Required reviewers
15
- - Signed commits enforcement
16
- - Linear history requirement
17
-
18
- ### Merge Policies
19
- - Squash and merge only
20
- - Require up-to-date branches
21
- - Auto-merge when checks pass
22
- - Merge queue management
23
-
24
- ### Quality Thresholds
25
- - Code coverage minimums
26
- - Complexity limits
27
- - Security vulnerability blocks
28
- - Performance regression detection
29
-
30
- ## Implementation
31
-
32
- ### GitHub Branch Protection (via API)
33
-
34
- ```bash
35
- #!/bin/bash
36
- # setup-branch-protection.sh
37
-
38
- OWNER="your-org"
39
- REPO="your-repo"
40
- BRANCH="main"
41
-
42
- gh api repos/${OWNER}/${REPO}/branches/${BRANCH}/protection -X PUT \
43
- -H "Accept: application/vnd.github+json" \
44
- --input - << EOF
45
- {
46
- "required_status_checks": {
47
- "strict": true,
48
- "contexts": [
49
- "build",
50
- "test",
51
- "lint",
52
- "security-scan",
53
- "coverage"
54
- ]
55
- },
56
- "enforce_admins": true,
57
- "required_pull_request_reviews": {
58
- "dismissal_restrictions": {
59
- "users": [],
60
- "teams": ["security-team"]
61
- },
62
- "dismiss_stale_reviews": true,
63
- "require_code_owner_reviews": true,
64
- "required_approving_review_count": 2,
65
- "require_last_push_approval": true
66
- },
67
- "restrictions": null,
68
- "required_linear_history": true,
69
- "allow_force_pushes": false,
70
- "allow_deletions": false,
71
- "block_creations": false,
72
- "required_conversation_resolution": true,
73
- "required_signatures": true
74
- }
75
- EOF
76
-
77
- echo "Branch protection configured for ${BRANCH}"
78
- ```
79
-
80
- ### Quality Gate Workflow
81
-
82
- ```yaml
83
- # .github/workflows/quality-gates.yml
84
- name: Quality Gates
85
- on:
86
- pull_request:
87
- branches: [main, develop]
88
- push:
89
- branches: [main, develop]
90
-
91
- concurrency:
92
- group: ${{ github.workflow }}-${{ github.ref }}
93
- cancel-in-progress: true
94
-
95
- jobs:
96
- # Gate 1: Build must succeed
97
- build:
98
- runs-on: ubuntu-latest
99
- steps:
100
- - uses: actions/checkout@v4
101
- - uses: actions/setup-node@v4
102
- with:
103
- node-version: '20'
104
- cache: 'npm'
105
- - run: npm ci
106
- - run: npm run build
107
-
108
- # Gate 2: All tests must pass
109
- test:
110
- runs-on: ubuntu-latest
111
- steps:
112
- - uses: actions/checkout@v4
113
- - uses: actions/setup-node@v4
114
- with:
115
- node-version: '20'
116
- cache: 'npm'
117
- - run: npm ci
118
- - run: npm test -- --coverage
119
- - uses: actions/upload-artifact@v4
120
- with:
121
- name: coverage
122
- path: coverage/
123
-
124
- # Gate 3: Coverage threshold
125
- coverage:
126
- needs: test
127
- runs-on: ubuntu-latest
128
- steps:
129
- - uses: actions/checkout@v4
130
- - uses: actions/download-artifact@v4
131
- with:
132
- name: coverage
133
- path: coverage/
134
-
135
- - name: Check coverage threshold
136
- uses: actions/github-script@v7
137
- with:
138
- script: |
139
- const fs = require('fs');
140
- const coverage = JSON.parse(
141
- fs.readFileSync('coverage/coverage-summary.json')
142
- );
143
-
144
- const thresholds = {
145
- lines: 80,
146
- statements: 80,
147
- functions: 75,
148
- branches: 70
149
- };
150
-
151
- const total = coverage.total;
152
- const failures = [];
153
-
154
- for (const [metric, threshold] of Object.entries(thresholds)) {
155
- const actual = total[metric].pct;
156
- if (actual < threshold) {
157
- failures.push(
158
- `${metric}: ${actual}% < ${threshold}% required`
159
- );
160
- }
161
- }
162
-
163
- if (failures.length > 0) {
164
- core.setFailed(
165
- `Coverage below threshold:\n${failures.join('\n')}`
166
- );
167
- } else {
168
- core.info('Coverage thresholds met');
169
- }
170
-
171
- # Gate 4: Linting
172
- lint:
173
- runs-on: ubuntu-latest
174
- steps:
175
- - uses: actions/checkout@v4
176
- - uses: actions/setup-node@v4
177
- with:
178
- node-version: '20'
179
- cache: 'npm'
180
- - run: npm ci
181
- - run: npm run lint -- --max-warnings 0
182
-
183
- # Gate 5: Type checking
184
- typecheck:
185
- runs-on: ubuntu-latest
186
- steps:
187
- - uses: actions/checkout@v4
188
- - uses: actions/setup-node@v4
189
- with:
190
- node-version: '20'
191
- cache: 'npm'
192
- - run: npm ci
193
- - run: npm run typecheck
194
-
195
- # Gate 6: Security scan
196
- security:
197
- runs-on: ubuntu-latest
198
- steps:
199
- - uses: actions/checkout@v4
200
-
201
- - name: Run Snyk
202
- uses: snyk/actions/node@master
203
- env:
204
- SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
205
- with:
206
- args: --severity-threshold=high
207
-
208
- - name: Check for secrets
209
- uses: gitleaks/gitleaks-action@v2
210
- env:
211
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
212
-
213
- # Gate 7: Complexity check
214
- complexity:
215
- runs-on: ubuntu-latest
216
- steps:
217
- - uses: actions/checkout@v4
218
- - uses: actions/setup-node@v4
219
- with:
220
- node-version: '20'
221
- cache: 'npm'
222
- - run: npm ci
223
-
224
- - name: Check complexity
225
- run: |
226
- npx es6-plato -r -d report src/
227
- MAX_COMPLEXITY=$(cat report/report.json | jq '[.reports[].complexity.cyclomatic] | max')
228
- if [ "$MAX_COMPLEXITY" -gt 15 ]; then
229
- echo "Cyclomatic complexity too high: $MAX_COMPLEXITY (max: 15)"
230
- exit 1
231
- fi
232
-
233
- # Final gate: All checks must pass
234
- quality-gate:
235
- needs: [build, test, coverage, lint, typecheck, security, complexity]
236
- runs-on: ubuntu-latest
237
- steps:
238
- - name: All gates passed
239
- run: echo "All quality gates passed successfully"
240
- ```
241
-
242
- ### Quality Gate Configuration
243
-
244
- ```yaml
245
- # .quality-gates.yml
246
- version: 1
247
-
248
- gates:
249
- # Coverage requirements
250
- coverage:
251
- enabled: true
252
- thresholds:
253
- lines: 80
254
- statements: 80
255
- functions: 75
256
- branches: 70
257
- block_merge: true
258
- trend: "no_decrease" # Coverage cannot decrease
259
-
260
- # Complexity limits
261
- complexity:
262
- enabled: true
263
- max_cyclomatic: 15
264
- max_cognitive: 20
265
- max_lines_per_function: 100
266
- max_parameters: 5
267
- block_merge: true
268
-
269
- # Security requirements
270
- security:
271
- enabled: true
272
- vulnerabilities:
273
- critical: 0 # No critical vulns allowed
274
- high: 0 # No high vulns allowed
275
- medium_max: 5 # Max 5 medium vulns
276
- secrets_detection: true
277
- sast_required: true
278
- block_merge: true
279
-
280
- # Code quality
281
- quality:
282
- enabled: true
283
- max_duplications: 3%
284
- max_code_smells: 10
285
- maintainability_rating: "A" # SonarQube rating
286
- block_merge: true
287
-
288
- # Test requirements
289
- tests:
290
- enabled: true
291
- required: true
292
- minimum_pass_rate: 100
293
- new_code_coverage: 80
294
- block_merge: true
295
-
296
- # Documentation
297
- documentation:
298
- enabled: true
299
- require_pr_description: true
300
- require_changelog: true # For releases
301
- block_merge: false # Warning only
302
-
303
- # Performance (optional)
304
- performance:
305
- enabled: false
306
- max_bundle_increase: 5% # KB
307
- max_response_time_increase: 10% # ms
308
- block_merge: false
309
-
310
- notifications:
311
- slack:
312
- channel: "#code-quality"
313
- on_failure: true
314
- on_success: false
315
-
316
- email:
317
- recipients: ["leads@company.com"]
318
- on_failure: true
319
-
320
- exceptions:
321
- # Files/patterns excluded from quality checks
322
- exclude_patterns:
323
- - "**/*.test.ts"
324
- - "**/*.spec.ts"
325
- - "**/fixtures/**"
326
- - "**/mocks/**"
327
- ```
328
-
329
- ### Quality Gate Status Check
330
-
331
- ```python
332
- #!/usr/bin/env python3
333
- """Quality gate status checker."""
334
-
335
- import json
336
- import sys
337
- from dataclasses import dataclass
338
- from typing import Dict, List, Optional
339
- from enum import Enum
340
-
341
- class GateStatus(Enum):
342
- PASSED = "passed"
343
- FAILED = "failed"
344
- WARNING = "warning"
345
- SKIPPED = "skipped"
346
-
347
- @dataclass
348
- class GateResult:
349
- """Result of a quality gate check."""
350
- name: str
351
- status: GateStatus
352
- message: str
353
- details: Optional[Dict] = None
354
- blocking: bool = True
355
-
356
- class QualityGateChecker:
357
- """Checks all quality gates and reports status."""
358
-
359
- def __init__(self, config_path: str = ".quality-gates.yml"):
360
- self.config = self._load_config(config_path)
361
- self.results: List[GateResult] = []
362
-
363
- def _load_config(self, path: str) -> Dict:
364
- """Load quality gate configuration."""
365
- import yaml
366
- with open(path) as f:
367
- return yaml.safe_load(f)
368
-
369
- def check_coverage(self, coverage_report: Dict) -> GateResult:
370
- """Check coverage thresholds."""
371
- config = self.config.get("gates", {}).get("coverage", {})
372
- if not config.get("enabled", True):
373
- return GateResult("coverage", GateStatus.SKIPPED, "Coverage check disabled")
374
-
375
- thresholds = config.get("thresholds", {})
376
- failures = []
377
-
378
- for metric, threshold in thresholds.items():
379
- actual = coverage_report.get("total", {}).get(metric, {}).get("pct", 0)
380
- if actual < threshold:
381
- failures.append(f"{metric}: {actual}% < {threshold}%")
382
-
383
- if failures:
384
- return GateResult(
385
- "coverage",
386
- GateStatus.FAILED,
387
- f"Coverage below threshold: {', '.join(failures)}",
388
- {"failures": failures},
389
- blocking=config.get("block_merge", True)
390
- )
391
-
392
- return GateResult("coverage", GateStatus.PASSED, "Coverage thresholds met")
393
-
394
- def check_security(self, scan_results: Dict) -> GateResult:
395
- """Check security scan results."""
396
- config = self.config.get("gates", {}).get("security", {})
397
- if not config.get("enabled", True):
398
- return GateResult("security", GateStatus.SKIPPED, "Security check disabled")
399
-
400
- vuln_config = config.get("vulnerabilities", {})
401
- vulns = scan_results.get("vulnerabilities", {})
402
-
403
- failures = []
404
-
405
- if vulns.get("critical", 0) > vuln_config.get("critical", 0):
406
- failures.append(f"Critical vulnerabilities: {vulns['critical']}")
407
-
408
- if vulns.get("high", 0) > vuln_config.get("high", 0):
409
- failures.append(f"High vulnerabilities: {vulns['high']}")
410
-
411
- if vulns.get("medium", 0) > vuln_config.get("medium_max", 999):
412
- failures.append(f"Too many medium vulnerabilities: {vulns['medium']}")
413
-
414
- if failures:
415
- return GateResult(
416
- "security",
417
- GateStatus.FAILED,
418
- f"Security issues found: {', '.join(failures)}",
419
- {"vulnerabilities": vulns},
420
- blocking=True # Security always blocks
421
- )
422
-
423
- return GateResult("security", GateStatus.PASSED, "No security issues")
424
-
425
- def check_complexity(self, complexity_report: Dict) -> GateResult:
426
- """Check code complexity."""
427
- config = self.config.get("gates", {}).get("complexity", {})
428
- if not config.get("enabled", True):
429
- return GateResult("complexity", GateStatus.SKIPPED, "Complexity check disabled")
430
-
431
- max_cyclomatic = config.get("max_cyclomatic", 15)
432
- actual_max = complexity_report.get("max_cyclomatic", 0)
433
-
434
- if actual_max > max_cyclomatic:
435
- return GateResult(
436
- "complexity",
437
- GateStatus.FAILED,
438
- f"Cyclomatic complexity {actual_max} exceeds max {max_cyclomatic}",
439
- {"max_found": actual_max, "threshold": max_cyclomatic},
440
- blocking=config.get("block_merge", True)
441
- )
442
-
443
- return GateResult("complexity", GateStatus.PASSED, "Complexity within limits")
444
-
445
- def check_all(self, reports: Dict) -> bool:
446
- """Run all quality gate checks."""
447
- self.results = [
448
- self.check_coverage(reports.get("coverage", {})),
449
- self.check_security(reports.get("security", {})),
450
- self.check_complexity(reports.get("complexity", {})),
451
- ]
452
-
453
- blocking_failures = [r for r in self.results
454
- if r.status == GateStatus.FAILED and r.blocking]
455
-
456
- return len(blocking_failures) == 0
457
-
458
- def generate_report(self) -> str:
459
- """Generate markdown report."""
460
- report = "## Quality Gate Results\n\n"
461
-
462
- status_icons = {
463
- GateStatus.PASSED: "",
464
- GateStatus.FAILED: "",
465
- GateStatus.WARNING: "",
466
- GateStatus.SKIPPED: ""
467
- }
468
-
469
- for result in self.results:
470
- icon = status_icons[result.status]
471
- report += f"- {icon} **{result.name}**: {result.message}\n"
472
-
473
- passed = all(r.status in (GateStatus.PASSED, GateStatus.SKIPPED, GateStatus.WARNING)
474
- or not r.blocking for r in self.results)
475
-
476
- report += f"\n**Overall**: {'PASSED' if passed else 'FAILED'}\n"
477
-
478
- return report
479
-
480
-
481
- if __name__ == "__main__":
482
- checker = QualityGateChecker()
483
-
484
- # Example reports (would come from actual tools)
485
- reports = {
486
- "coverage": {"total": {"lines": {"pct": 85}, "branches": {"pct": 72}}},
487
- "security": {"vulnerabilities": {"critical": 0, "high": 0, "medium": 2}},
488
- "complexity": {"max_cyclomatic": 12}
489
- }
490
-
491
- passed = checker.check_all(reports)
492
- print(checker.generate_report())
493
- sys.exit(0 if passed else 1)
494
- ```
495
-
496
- ## Metrics
497
-
498
- | Metric | Target | Description |
499
- |--------|--------|-------------|
500
- | Gate pass rate | > 95% | PRs passing first time |
501
- | False positive rate | < 5% | Incorrect failures |
502
- | Gate execution time | < 10 min | Total check time |
503
- | Bypass rate | 0% | No bypasses allowed |
504
-
505
- ## Connections
506
-
507
- - **Inputs from**: Automated review (cr-01), PR workflow (cr-02)
508
- - **Outputs to**: Merge decision, analytics (cr-05)
509
- - **Integrates with**: Security (sa-05), DevOps (do-01)
510
-
511
- ## Best Practices
512
-
513
- 1. Start with lenient thresholds, tighten gradually
514
- 2. Never allow bypasses for security gates
515
- 3. Keep gate execution fast (< 10 minutes)
516
- 4. Provide clear failure messages with fix guidance
517
- 5. Track gate failures to identify common issues
518
- 6. Review and update thresholds quarterly
1
+ # cr-03: Code Quality Gates
2
+
3
+ Enforce quality standards with branch protection, required checks, and merge policies.
4
+
5
+ ## Overview
6
+
7
+ Quality gates are automated checkpoints that code must pass before merging. They ensure consistent standards, prevent regressions, and protect production branches from unsafe changes.
8
+
9
+ ## Capabilities
10
+
11
+ ### Branch Protection
12
+ - Protected branch configuration
13
+ - Required status checks
14
+ - Required reviewers
15
+ - Signed commits enforcement
16
+ - Linear history requirement
17
+
18
+ ### Merge Policies
19
+ - Squash and merge only
20
+ - Require up-to-date branches
21
+ - Auto-merge when checks pass
22
+ - Merge queue management
23
+
24
+ ### Quality Thresholds
25
+ - Code coverage minimums
26
+ - Complexity limits
27
+ - Security vulnerability blocks
28
+ - Performance regression detection
29
+
30
+ ## Implementation
31
+
32
+ ### GitHub Branch Protection (via API)
33
+
34
+ ```bash
35
+ #!/bin/bash
36
+ # setup-branch-protection.sh
37
+
38
+ OWNER="your-org"
39
+ REPO="your-repo"
40
+ BRANCH="main"
41
+
42
+ gh api repos/${OWNER}/${REPO}/branches/${BRANCH}/protection -X PUT \
43
+ -H "Accept: application/vnd.github+json" \
44
+ --input - << EOF
45
+ {
46
+ "required_status_checks": {
47
+ "strict": true,
48
+ "contexts": [
49
+ "build",
50
+ "test",
51
+ "lint",
52
+ "security-scan",
53
+ "coverage"
54
+ ]
55
+ },
56
+ "enforce_admins": true,
57
+ "required_pull_request_reviews": {
58
+ "dismissal_restrictions": {
59
+ "users": [],
60
+ "teams": ["security-team"]
61
+ },
62
+ "dismiss_stale_reviews": true,
63
+ "require_code_owner_reviews": true,
64
+ "required_approving_review_count": 2,
65
+ "require_last_push_approval": true
66
+ },
67
+ "restrictions": null,
68
+ "required_linear_history": true,
69
+ "allow_force_pushes": false,
70
+ "allow_deletions": false,
71
+ "block_creations": false,
72
+ "required_conversation_resolution": true,
73
+ "required_signatures": true
74
+ }
75
+ EOF
76
+
77
+ echo "Branch protection configured for ${BRANCH}"
78
+ ```
79
+
80
+ ### Quality Gate Workflow
81
+
82
+ ```yaml
83
+ # .github/workflows/quality-gates.yml
84
+ name: Quality Gates
85
+ on:
86
+ pull_request:
87
+ branches: [main, develop]
88
+ push:
89
+ branches: [main, develop]
90
+
91
+ concurrency:
92
+ group: ${{ github.workflow }}-${{ github.ref }}
93
+ cancel-in-progress: true
94
+
95
+ jobs:
96
+ # Gate 1: Build must succeed
97
+ build:
98
+ runs-on: ubuntu-latest
99
+ steps:
100
+ - uses: actions/checkout@v4
101
+ - uses: actions/setup-node@v4
102
+ with:
103
+ node-version: '20'
104
+ cache: 'npm'
105
+ - run: npm ci
106
+ - run: npm run build
107
+
108
+ # Gate 2: All tests must pass
109
+ test:
110
+ runs-on: ubuntu-latest
111
+ steps:
112
+ - uses: actions/checkout@v4
113
+ - uses: actions/setup-node@v4
114
+ with:
115
+ node-version: '20'
116
+ cache: 'npm'
117
+ - run: npm ci
118
+ - run: npm test -- --coverage
119
+ - uses: actions/upload-artifact@v4
120
+ with:
121
+ name: coverage
122
+ path: coverage/
123
+
124
+ # Gate 3: Coverage threshold
125
+ coverage:
126
+ needs: test
127
+ runs-on: ubuntu-latest
128
+ steps:
129
+ - uses: actions/checkout@v4
130
+ - uses: actions/download-artifact@v4
131
+ with:
132
+ name: coverage
133
+ path: coverage/
134
+
135
+ - name: Check coverage threshold
136
+ uses: actions/github-script@v7
137
+ with:
138
+ script: |
139
+ const fs = require('fs');
140
+ const coverage = JSON.parse(
141
+ fs.readFileSync('coverage/coverage-summary.json')
142
+ );
143
+
144
+ const thresholds = {
145
+ lines: 80,
146
+ statements: 80,
147
+ functions: 75,
148
+ branches: 70
149
+ };
150
+
151
+ const total = coverage.total;
152
+ const failures = [];
153
+
154
+ for (const [metric, threshold] of Object.entries(thresholds)) {
155
+ const actual = total[metric].pct;
156
+ if (actual < threshold) {
157
+ failures.push(
158
+ `${metric}: ${actual}% < ${threshold}% required`
159
+ );
160
+ }
161
+ }
162
+
163
+ if (failures.length > 0) {
164
+ core.setFailed(
165
+ `Coverage below threshold:\n${failures.join('\n')}`
166
+ );
167
+ } else {
168
+ core.info('Coverage thresholds met');
169
+ }
170
+
171
+ # Gate 4: Linting
172
+ lint:
173
+ runs-on: ubuntu-latest
174
+ steps:
175
+ - uses: actions/checkout@v4
176
+ - uses: actions/setup-node@v4
177
+ with:
178
+ node-version: '20'
179
+ cache: 'npm'
180
+ - run: npm ci
181
+ - run: npm run lint -- --max-warnings 0
182
+
183
+ # Gate 5: Type checking
184
+ typecheck:
185
+ runs-on: ubuntu-latest
186
+ steps:
187
+ - uses: actions/checkout@v4
188
+ - uses: actions/setup-node@v4
189
+ with:
190
+ node-version: '20'
191
+ cache: 'npm'
192
+ - run: npm ci
193
+ - run: npm run typecheck
194
+
195
+ # Gate 6: Security scan
196
+ security:
197
+ runs-on: ubuntu-latest
198
+ steps:
199
+ - uses: actions/checkout@v4
200
+
201
+ - name: Run Snyk
202
+ uses: snyk/actions/node@master
203
+ env:
204
+ SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
205
+ with:
206
+ args: --severity-threshold=high
207
+
208
+ - name: Check for secrets
209
+ uses: gitleaks/gitleaks-action@v2
210
+ env:
211
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
212
+
213
+ # Gate 7: Complexity check
214
+ complexity:
215
+ runs-on: ubuntu-latest
216
+ steps:
217
+ - uses: actions/checkout@v4
218
+ - uses: actions/setup-node@v4
219
+ with:
220
+ node-version: '20'
221
+ cache: 'npm'
222
+ - run: npm ci
223
+
224
+ - name: Check complexity
225
+ run: |
226
+ npx es6-plato -r -d report src/
227
+ MAX_COMPLEXITY=$(cat report/report.json | jq '[.reports[].complexity.cyclomatic] | max')
228
+ if [ "$MAX_COMPLEXITY" -gt 15 ]; then
229
+ echo "Cyclomatic complexity too high: $MAX_COMPLEXITY (max: 15)"
230
+ exit 1
231
+ fi
232
+
233
+ # Final gate: All checks must pass
234
+ quality-gate:
235
+ needs: [build, test, coverage, lint, typecheck, security, complexity]
236
+ runs-on: ubuntu-latest
237
+ steps:
238
+ - name: All gates passed
239
+ run: echo "All quality gates passed successfully"
240
+ ```
241
+
242
+ ### Quality Gate Configuration
243
+
244
+ ```yaml
245
+ # .quality-gates.yml
246
+ version: 1
247
+
248
+ gates:
249
+ # Coverage requirements
250
+ coverage:
251
+ enabled: true
252
+ thresholds:
253
+ lines: 80
254
+ statements: 80
255
+ functions: 75
256
+ branches: 70
257
+ block_merge: true
258
+ trend: "no_decrease" # Coverage cannot decrease
259
+
260
+ # Complexity limits
261
+ complexity:
262
+ enabled: true
263
+ max_cyclomatic: 15
264
+ max_cognitive: 20
265
+ max_lines_per_function: 100
266
+ max_parameters: 5
267
+ block_merge: true
268
+
269
+ # Security requirements
270
+ security:
271
+ enabled: true
272
+ vulnerabilities:
273
+ critical: 0 # No critical vulns allowed
274
+ high: 0 # No high vulns allowed
275
+ medium_max: 5 # Max 5 medium vulns
276
+ secrets_detection: true
277
+ sast_required: true
278
+ block_merge: true
279
+
280
+ # Code quality
281
+ quality:
282
+ enabled: true
283
+ max_duplications: 3%
284
+ max_code_smells: 10
285
+ maintainability_rating: "A" # SonarQube rating
286
+ block_merge: true
287
+
288
+ # Test requirements
289
+ tests:
290
+ enabled: true
291
+ required: true
292
+ minimum_pass_rate: 100
293
+ new_code_coverage: 80
294
+ block_merge: true
295
+
296
+ # Documentation
297
+ documentation:
298
+ enabled: true
299
+ require_pr_description: true
300
+ require_changelog: true # For releases
301
+ block_merge: false # Warning only
302
+
303
+ # Performance (optional)
304
+ performance:
305
+ enabled: false
306
+ max_bundle_increase: 5% # KB
307
+ max_response_time_increase: 10% # ms
308
+ block_merge: false
309
+
310
+ notifications:
311
+ slack:
312
+ channel: "#code-quality"
313
+ on_failure: true
314
+ on_success: false
315
+
316
+ email:
317
+ recipients: ["leads@company.com"]
318
+ on_failure: true
319
+
320
+ exceptions:
321
+ # Files/patterns excluded from quality checks
322
+ exclude_patterns:
323
+ - "**/*.test.ts"
324
+ - "**/*.spec.ts"
325
+ - "**/fixtures/**"
326
+ - "**/mocks/**"
327
+ ```
328
+
329
+ ### Quality Gate Status Check
330
+
331
+ ```python
332
+ #!/usr/bin/env python3
333
+ """Quality gate status checker."""
334
+
335
+ import json
336
+ import sys
337
+ from dataclasses import dataclass
338
+ from typing import Dict, List, Optional
339
+ from enum import Enum
340
+
341
+ class GateStatus(Enum):
342
+ PASSED = "passed"
343
+ FAILED = "failed"
344
+ WARNING = "warning"
345
+ SKIPPED = "skipped"
346
+
347
+ @dataclass
348
+ class GateResult:
349
+ """Result of a quality gate check."""
350
+ name: str
351
+ status: GateStatus
352
+ message: str
353
+ details: Optional[Dict] = None
354
+ blocking: bool = True
355
+
356
+ class QualityGateChecker:
357
+ """Checks all quality gates and reports status."""
358
+
359
+ def __init__(self, config_path: str = ".quality-gates.yml"):
360
+ self.config = self._load_config(config_path)
361
+ self.results: List[GateResult] = []
362
+
363
+ def _load_config(self, path: str) -> Dict:
364
+ """Load quality gate configuration."""
365
+ import yaml
366
+ with open(path) as f:
367
+ return yaml.safe_load(f)
368
+
369
+ def check_coverage(self, coverage_report: Dict) -> GateResult:
370
+ """Check coverage thresholds."""
371
+ config = self.config.get("gates", {}).get("coverage", {})
372
+ if not config.get("enabled", True):
373
+ return GateResult("coverage", GateStatus.SKIPPED, "Coverage check disabled")
374
+
375
+ thresholds = config.get("thresholds", {})
376
+ failures = []
377
+
378
+ for metric, threshold in thresholds.items():
379
+ actual = coverage_report.get("total", {}).get(metric, {}).get("pct", 0)
380
+ if actual < threshold:
381
+ failures.append(f"{metric}: {actual}% < {threshold}%")
382
+
383
+ if failures:
384
+ return GateResult(
385
+ "coverage",
386
+ GateStatus.FAILED,
387
+ f"Coverage below threshold: {', '.join(failures)}",
388
+ {"failures": failures},
389
+ blocking=config.get("block_merge", True)
390
+ )
391
+
392
+ return GateResult("coverage", GateStatus.PASSED, "Coverage thresholds met")
393
+
394
+ def check_security(self, scan_results: Dict) -> GateResult:
395
+ """Check security scan results."""
396
+ config = self.config.get("gates", {}).get("security", {})
397
+ if not config.get("enabled", True):
398
+ return GateResult("security", GateStatus.SKIPPED, "Security check disabled")
399
+
400
+ vuln_config = config.get("vulnerabilities", {})
401
+ vulns = scan_results.get("vulnerabilities", {})
402
+
403
+ failures = []
404
+
405
+ if vulns.get("critical", 0) > vuln_config.get("critical", 0):
406
+ failures.append(f"Critical vulnerabilities: {vulns['critical']}")
407
+
408
+ if vulns.get("high", 0) > vuln_config.get("high", 0):
409
+ failures.append(f"High vulnerabilities: {vulns['high']}")
410
+
411
+ if vulns.get("medium", 0) > vuln_config.get("medium_max", 999):
412
+ failures.append(f"Too many medium vulnerabilities: {vulns['medium']}")
413
+
414
+ if failures:
415
+ return GateResult(
416
+ "security",
417
+ GateStatus.FAILED,
418
+ f"Security issues found: {', '.join(failures)}",
419
+ {"vulnerabilities": vulns},
420
+ blocking=True # Security always blocks
421
+ )
422
+
423
+ return GateResult("security", GateStatus.PASSED, "No security issues")
424
+
425
+ def check_complexity(self, complexity_report: Dict) -> GateResult:
426
+ """Check code complexity."""
427
+ config = self.config.get("gates", {}).get("complexity", {})
428
+ if not config.get("enabled", True):
429
+ return GateResult("complexity", GateStatus.SKIPPED, "Complexity check disabled")
430
+
431
+ max_cyclomatic = config.get("max_cyclomatic", 15)
432
+ actual_max = complexity_report.get("max_cyclomatic", 0)
433
+
434
+ if actual_max > max_cyclomatic:
435
+ return GateResult(
436
+ "complexity",
437
+ GateStatus.FAILED,
438
+ f"Cyclomatic complexity {actual_max} exceeds max {max_cyclomatic}",
439
+ {"max_found": actual_max, "threshold": max_cyclomatic},
440
+ blocking=config.get("block_merge", True)
441
+ )
442
+
443
+ return GateResult("complexity", GateStatus.PASSED, "Complexity within limits")
444
+
445
+ def check_all(self, reports: Dict) -> bool:
446
+ """Run all quality gate checks."""
447
+ self.results = [
448
+ self.check_coverage(reports.get("coverage", {})),
449
+ self.check_security(reports.get("security", {})),
450
+ self.check_complexity(reports.get("complexity", {})),
451
+ ]
452
+
453
+ blocking_failures = [r for r in self.results
454
+ if r.status == GateStatus.FAILED and r.blocking]
455
+
456
+ return len(blocking_failures) == 0
457
+
458
+ def generate_report(self) -> str:
459
+ """Generate markdown report."""
460
+ report = "## Quality Gate Results\n\n"
461
+
462
+ status_icons = {
463
+ GateStatus.PASSED: "",
464
+ GateStatus.FAILED: "",
465
+ GateStatus.WARNING: "",
466
+ GateStatus.SKIPPED: ""
467
+ }
468
+
469
+ for result in self.results:
470
+ icon = status_icons[result.status]
471
+ report += f"- {icon} **{result.name}**: {result.message}\n"
472
+
473
+ passed = all(r.status in (GateStatus.PASSED, GateStatus.SKIPPED, GateStatus.WARNING)
474
+ or not r.blocking for r in self.results)
475
+
476
+ report += f"\n**Overall**: {'PASSED' if passed else 'FAILED'}\n"
477
+
478
+ return report
479
+
480
+
481
+ if __name__ == "__main__":
482
+ checker = QualityGateChecker()
483
+
484
+ # Example reports (would come from actual tools)
485
+ reports = {
486
+ "coverage": {"total": {"lines": {"pct": 85}, "branches": {"pct": 72}}},
487
+ "security": {"vulnerabilities": {"critical": 0, "high": 0, "medium": 2}},
488
+ "complexity": {"max_cyclomatic": 12}
489
+ }
490
+
491
+ passed = checker.check_all(reports)
492
+ print(checker.generate_report())
493
+ sys.exit(0 if passed else 1)
494
+ ```
495
+
496
+ ## Metrics
497
+
498
+ | Metric | Target | Description |
499
+ |--------|--------|-------------|
500
+ | Gate pass rate | > 95% | PRs passing first time |
501
+ | False positive rate | < 5% | Incorrect failures |
502
+ | Gate execution time | < 10 min | Total check time |
503
+ | Bypass rate | 0% | No bypasses allowed |
504
+
505
+ ## Connections
506
+
507
+ - **Inputs from**: Automated review (cr-01), PR workflow (cr-02)
508
+ - **Outputs to**: Merge decision, analytics (cr-05)
509
+ - **Integrates with**: Security (sa-05), DevOps (do-01)
510
+
511
+ ## Best Practices
512
+
513
+ 1. Start with lenient thresholds, tighten gradually
514
+ 2. Never allow bypasses for security gates
515
+ 3. Keep gate execution fast (< 10 minutes)
516
+ 4. Provide clear failure messages with fix guidance
517
+ 5. Track gate failures to identify common issues
518
+ 6. Review and update thresholds quarterly