tech-hub-skills 1.0.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/LICENSE +21 -0
- package/README.md +250 -0
- package/bin/cli.js +241 -0
- package/bin/copilot.js +182 -0
- package/bin/postinstall.js +42 -0
- package/package.json +46 -0
- package/tech_hub_skills/roles/ai-engineer/skills/01-prompt-engineering/README.md +252 -0
- package/tech_hub_skills/roles/ai-engineer/skills/02-rag-pipeline/README.md +448 -0
- package/tech_hub_skills/roles/ai-engineer/skills/03-agent-orchestration/README.md +599 -0
- package/tech_hub_skills/roles/ai-engineer/skills/04-llm-guardrails/README.md +735 -0
- package/tech_hub_skills/roles/ai-engineer/skills/05-vector-embeddings/README.md +711 -0
- package/tech_hub_skills/roles/ai-engineer/skills/06-llm-evaluation/README.md +777 -0
- package/tech_hub_skills/roles/azure/skills/01-infrastructure-fundamentals/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/02-data-factory/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/03-synapse-analytics/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/04-databricks/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/05-functions/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/06-kubernetes-service/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/07-openai-service/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/08-machine-learning/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/09-storage-adls/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/10-networking/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/11-sql-cosmos/README.md +264 -0
- package/tech_hub_skills/roles/azure/skills/12-event-hubs/README.md +264 -0
- package/tech_hub_skills/roles/code-review/skills/01-automated-code-review/README.md +394 -0
- package/tech_hub_skills/roles/code-review/skills/02-pr-review-workflow/README.md +427 -0
- package/tech_hub_skills/roles/code-review/skills/03-code-quality-gates/README.md +518 -0
- package/tech_hub_skills/roles/code-review/skills/04-reviewer-assignment/README.md +504 -0
- package/tech_hub_skills/roles/code-review/skills/05-review-analytics/README.md +540 -0
- package/tech_hub_skills/roles/data-engineer/skills/01-lakehouse-architecture/README.md +550 -0
- package/tech_hub_skills/roles/data-engineer/skills/02-etl-pipeline/README.md +580 -0
- package/tech_hub_skills/roles/data-engineer/skills/03-data-quality/README.md +579 -0
- package/tech_hub_skills/roles/data-engineer/skills/04-streaming-pipelines/README.md +608 -0
- package/tech_hub_skills/roles/data-engineer/skills/05-performance-optimization/README.md +547 -0
- package/tech_hub_skills/roles/data-governance/skills/01-data-catalog/README.md +112 -0
- package/tech_hub_skills/roles/data-governance/skills/02-data-lineage/README.md +129 -0
- package/tech_hub_skills/roles/data-governance/skills/03-data-quality-framework/README.md +182 -0
- package/tech_hub_skills/roles/data-governance/skills/04-access-control/README.md +39 -0
- package/tech_hub_skills/roles/data-governance/skills/05-master-data-management/README.md +40 -0
- package/tech_hub_skills/roles/data-governance/skills/06-compliance-privacy/README.md +46 -0
- package/tech_hub_skills/roles/data-scientist/skills/01-eda-automation/README.md +230 -0
- package/tech_hub_skills/roles/data-scientist/skills/02-statistical-modeling/README.md +264 -0
- package/tech_hub_skills/roles/data-scientist/skills/03-feature-engineering/README.md +264 -0
- package/tech_hub_skills/roles/data-scientist/skills/04-predictive-modeling/README.md +264 -0
- package/tech_hub_skills/roles/data-scientist/skills/05-customer-analytics/README.md +264 -0
- package/tech_hub_skills/roles/data-scientist/skills/06-campaign-analysis/README.md +264 -0
- package/tech_hub_skills/roles/data-scientist/skills/07-experimentation/README.md +264 -0
- package/tech_hub_skills/roles/data-scientist/skills/08-data-visualization/README.md +264 -0
- package/tech_hub_skills/roles/devops/skills/01-cicd-pipeline/README.md +264 -0
- package/tech_hub_skills/roles/devops/skills/02-container-orchestration/README.md +264 -0
- package/tech_hub_skills/roles/devops/skills/03-infrastructure-as-code/README.md +264 -0
- package/tech_hub_skills/roles/devops/skills/04-gitops/README.md +264 -0
- package/tech_hub_skills/roles/devops/skills/05-environment-management/README.md +264 -0
- package/tech_hub_skills/roles/devops/skills/06-automated-testing/README.md +264 -0
- package/tech_hub_skills/roles/devops/skills/07-release-management/README.md +264 -0
- package/tech_hub_skills/roles/devops/skills/08-monitoring-alerting/README.md +264 -0
- package/tech_hub_skills/roles/devops/skills/09-devsecops/README.md +265 -0
- package/tech_hub_skills/roles/finops/skills/01-cost-visibility/README.md +264 -0
- package/tech_hub_skills/roles/finops/skills/02-resource-tagging/README.md +264 -0
- package/tech_hub_skills/roles/finops/skills/03-budget-management/README.md +264 -0
- package/tech_hub_skills/roles/finops/skills/04-reserved-instances/README.md +264 -0
- package/tech_hub_skills/roles/finops/skills/05-spot-optimization/README.md +264 -0
- package/tech_hub_skills/roles/finops/skills/06-storage-tiering/README.md +264 -0
- package/tech_hub_skills/roles/finops/skills/07-compute-rightsizing/README.md +264 -0
- package/tech_hub_skills/roles/finops/skills/08-chargeback/README.md +264 -0
- package/tech_hub_skills/roles/ml-engineer/skills/01-mlops-pipeline/README.md +566 -0
- package/tech_hub_skills/roles/ml-engineer/skills/02-feature-engineering/README.md +655 -0
- package/tech_hub_skills/roles/ml-engineer/skills/03-model-training/README.md +704 -0
- package/tech_hub_skills/roles/ml-engineer/skills/04-model-serving/README.md +845 -0
- package/tech_hub_skills/roles/ml-engineer/skills/05-model-monitoring/README.md +874 -0
- package/tech_hub_skills/roles/mlops/skills/01-ml-pipeline-orchestration/README.md +264 -0
- package/tech_hub_skills/roles/mlops/skills/02-experiment-tracking/README.md +264 -0
- package/tech_hub_skills/roles/mlops/skills/03-model-registry/README.md +264 -0
- package/tech_hub_skills/roles/mlops/skills/04-feature-store/README.md +264 -0
- package/tech_hub_skills/roles/mlops/skills/05-model-deployment/README.md +264 -0
- package/tech_hub_skills/roles/mlops/skills/06-model-observability/README.md +264 -0
- package/tech_hub_skills/roles/mlops/skills/07-data-versioning/README.md +264 -0
- package/tech_hub_skills/roles/mlops/skills/08-ab-testing/README.md +264 -0
- package/tech_hub_skills/roles/mlops/skills/09-automated-retraining/README.md +264 -0
- package/tech_hub_skills/roles/platform-engineer/skills/01-internal-developer-platform/README.md +153 -0
- package/tech_hub_skills/roles/platform-engineer/skills/02-self-service-infrastructure/README.md +57 -0
- package/tech_hub_skills/roles/platform-engineer/skills/03-slo-sli-management/README.md +59 -0
- package/tech_hub_skills/roles/platform-engineer/skills/04-developer-experience/README.md +57 -0
- package/tech_hub_skills/roles/platform-engineer/skills/05-incident-management/README.md +73 -0
- package/tech_hub_skills/roles/platform-engineer/skills/06-capacity-management/README.md +59 -0
- package/tech_hub_skills/roles/product-designer/skills/01-requirements-discovery/README.md +407 -0
- package/tech_hub_skills/roles/product-designer/skills/02-user-research/README.md +382 -0
- package/tech_hub_skills/roles/product-designer/skills/03-brainstorming-ideation/README.md +437 -0
- package/tech_hub_skills/roles/product-designer/skills/04-ux-design/README.md +496 -0
- package/tech_hub_skills/roles/product-designer/skills/05-product-market-fit/README.md +376 -0
- package/tech_hub_skills/roles/product-designer/skills/06-stakeholder-management/README.md +412 -0
- package/tech_hub_skills/roles/security-architect/skills/01-pii-detection/README.md +319 -0
- package/tech_hub_skills/roles/security-architect/skills/02-threat-modeling/README.md +264 -0
- package/tech_hub_skills/roles/security-architect/skills/03-infrastructure-security/README.md +264 -0
- package/tech_hub_skills/roles/security-architect/skills/04-iam/README.md +264 -0
- package/tech_hub_skills/roles/security-architect/skills/05-application-security/README.md +264 -0
- package/tech_hub_skills/roles/security-architect/skills/06-secrets-management/README.md +264 -0
- package/tech_hub_skills/roles/security-architect/skills/07-security-monitoring/README.md +264 -0
- package/tech_hub_skills/roles/system-design/skills/01-architecture-patterns/README.md +337 -0
- package/tech_hub_skills/roles/system-design/skills/02-requirements-engineering/README.md +264 -0
- package/tech_hub_skills/roles/system-design/skills/03-scalability/README.md +264 -0
- package/tech_hub_skills/roles/system-design/skills/04-high-availability/README.md +264 -0
- package/tech_hub_skills/roles/system-design/skills/05-cost-optimization-design/README.md +264 -0
- package/tech_hub_skills/roles/system-design/skills/06-api-design/README.md +264 -0
- package/tech_hub_skills/roles/system-design/skills/07-observability-architecture/README.md +264 -0
- package/tech_hub_skills/roles/system-design/skills/08-process-automation/PROCESS_TEMPLATE.md +336 -0
- package/tech_hub_skills/roles/system-design/skills/08-process-automation/README.md +521 -0
- package/tech_hub_skills/skills/README.md +336 -0
- package/tech_hub_skills/skills/ai-engineer.md +104 -0
- package/tech_hub_skills/skills/azure.md +149 -0
- package/tech_hub_skills/skills/code-review.md +399 -0
- package/tech_hub_skills/skills/compliance-automation.md +747 -0
- package/tech_hub_skills/skills/data-engineer.md +113 -0
- package/tech_hub_skills/skills/data-governance.md +102 -0
- package/tech_hub_skills/skills/data-scientist.md +123 -0
- package/tech_hub_skills/skills/devops.md +160 -0
- package/tech_hub_skills/skills/docker.md +160 -0
- package/tech_hub_skills/skills/enterprise-dashboard.md +613 -0
- package/tech_hub_skills/skills/finops.md +184 -0
- package/tech_hub_skills/skills/ml-engineer.md +115 -0
- package/tech_hub_skills/skills/mlops.md +187 -0
- package/tech_hub_skills/skills/optimization-advisor.md +329 -0
- package/tech_hub_skills/skills/orchestrator.md +497 -0
- package/tech_hub_skills/skills/platform-engineer.md +102 -0
- package/tech_hub_skills/skills/process-automation.md +226 -0
- package/tech_hub_skills/skills/process-changelog.md +184 -0
- package/tech_hub_skills/skills/process-documentation.md +484 -0
- package/tech_hub_skills/skills/process-kanban.md +324 -0
- package/tech_hub_skills/skills/process-versioning.md +214 -0
- package/tech_hub_skills/skills/product-designer.md +104 -0
- package/tech_hub_skills/skills/project-starter.md +443 -0
- package/tech_hub_skills/skills/security-architect.md +135 -0
- package/tech_hub_skills/skills/system-design.md +126 -0
|
@@ -0,0 +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
|