-
Notifications
You must be signed in to change notification settings - Fork 1
363 lines (299 loc) · 11.2 KB
/
code-quality.yml
File metadata and controls
363 lines (299 loc) · 11.2 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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
name: Code Quality
# Run comprehensive code quality checks
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
# Run weekly quality checks on Sunday at 2 AM UTC
- cron: '0 2 * * 0'
workflow_dispatch:
permissions:
contents: read
security-events: write
actions: read
checks: write
pull-requests: write
env:
NODE_VERSION: '22'
jobs:
# Job 1: Code Complexity and Metrics
complexity-analysis:
name: Code Complexity Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci --prefer-offline --no-audit
- name: Run TypeScript complexity analysis
run: |
# Type check the project
npx tsc --noEmit --skipLibCheck
# Use eslint complexity rules for analysis
echo '{"summary": "TypeScript compilation successful", "status": "pass"}' > complexity-report.mjson
- name: Upload complexity report
uses: actions/upload-artifact@v4
with:
name: complexity-report
path: complexity-report.mjson
retention-days: 30
# Job 2: Dependency Analysis
dependency-analysis:
name: Dependency Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci --prefer-offline --no-audit
- name: Analyze bundle size
run: |
# Install bundle analyzer
npm install -g bundlesize webpack-bundle-analyzer
# Create a simple webpack config for analysis
cat > webpack.config.mjs << 'EOF'
import path from 'path';
module.exports = {
entry: './dist/index.mjs',
target: 'node',
mode: 'production',
output: {
path: path.resolve(__dirname, 'bundle-analysis'),
filename: 'bundle.mjs'
},
resolve: {
extensions: ['.mjs', '.mjson']
}
};
EOF
# Build for analysis
npm run build
# Analyze if webpack is available
if npm list webpack &> /dev/null; then
npx webpack --config webpack.config.mjs --json > bundle-stats.mjson
echo "Bundle analysis completed"
else
echo "Bundle analysis skipped - webpack not available"
fi
- name: Check for circular dependencies
run: |
# Install madge for circular dependency detection
npm install -g madge
# Check for circular dependencies in TypeScript source
madge --circular --extensions ts src/ > circular-deps.txt || echo "No circular dependencies found"
# Display results
cat circular-deps.txt
- name: Generate dependency tree
run: |
# Generate dependency tree
npm list --all --json > dependency-tree.mjson
# Generate license report
npm install -g license-checker
license-checker --json > license-report.mjson
- name: Upload dependency analysis
uses: actions/upload-artifact@v4
with:
name: dependency-analysis
path: |
bundle-stats.mjson
circular-deps.txt
dependency-tree.mjson
license-report.mjson
retention-days: 30
# Job 3: Code Duplication Detection
duplication-analysis:
name: Code Duplication Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci --prefer-offline --no-audit
- name: Run duplication detection
run: |
# Install jscpd for duplication detection
npm install -g jscpd
# Run duplication analysis on TypeScript files
jscpd src/ --format "json" --output "./duplication-report.mjson" --min-tokens 50 --reporters json,html || echo "Duplication analysis completed"
# Create summary
if [ -f "duplication-report.mjson" ]; then
echo "## Code Duplication Report" > duplication-summary.md
echo "Duplication analysis completed. Check artifacts for detailed report." >> duplication-summary.md
fi
- name: Upload duplication report
uses: actions/upload-artifact@v4
with:
name: duplication-report
path: |
duplication-report.mjson
duplication-summary.md
.mjscpd/
retention-days: 30
# Job 4: Type Coverage Analysis
type-coverage:
name: TypeScript Type Coverage
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci --prefer-offline --no-audit
- name: Run type coverage analysis
run: |
# Install type coverage tool
npm install -g type-coverage
# Run type coverage analysis
npx type-coverage --detail --strict --cache --ignore-catch > type-coverage-report.txt
# Extract coverage percentage
COVERAGE=$(npx type-coverage --strict | grep -o '[0-9]*\.[0-9]*%' | head -1)
echo "Type coverage: $COVERAGE"
echo "TYPE_COVERAGE=$COVERAGE" >> $GITHUB_ENV
- name: Comment type coverage on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const coverage = process.env.TYPE_COVERAGE;
const comment = `## 📊 Type Coverage Report
**Type Coverage: ${coverage}**
This PR's TypeScript type coverage analysis is complete.
Check the full report in the workflow artifacts.`;
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
- name: Upload type coverage report
uses: actions/upload-artifact@v4
with:
name: type-coverage-report
path: type-coverage-report.txt
retention-days: 30
# Job 5: Performance Budget Check
performance-budget:
name: Performance Budget Check
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci --prefer-offline --no-audit
- name: Build application
run: npm run build
- name: Check bundle size
run: |
# Create performance budget configuration
cat > performance-budget.mjson << 'EOF'
{
"budgets": [
{
"path": "dist/**/*.mjs",
"maxSize": "500kb",
"type": "bundle"
},
{
"path": "dist/index.mjs",
"maxSize": "200kb",
"type": "initial"
}
]
}
EOF
# Check file sizes against budget
echo "## Performance Budget Check" > budget-report.md
echo "" >> budget-report.md
for file in dist/*.mjs; do
if [ -f "$file" ]; then
size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null || echo "0")
size_kb=$((size / 1024))
echo "- $(basename $file): ${size_kb}KB" >> budget-report.md
# Check against budget (simplified check)
if [ $size_kb -gt 500 ]; then
echo " ⚠️ Exceeds 500KB budget" >> budget-report.md
echo "BUDGET_EXCEEDED=true" >> $GITHUB_ENV
else
echo " ✅ Within budget" >> budget-report.md
fi
fi
done
- name: Fail if budget exceeded
if: env.BUDGET_EXCEEDED == 'true'
run: |
echo "❌ Performance budget exceeded!"
cat budget-report.md
exit 1
- name: Upload budget report
uses: actions/upload-artifact@v4
with:
name: performance-budget-report
path: budget-report.md
retention-days: 30
# Job 6: Generate Quality Summary
quality-summary:
name: Quality Summary
runs-on: ubuntu-latest
needs: [complexity-analysis, dependency-analysis, duplication-analysis, type-coverage, performance-budget]
if: always()
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: ./reports
- name: Generate quality summary
run: |
echo "# 📊 Code Quality Summary" > quality-summary.md
echo "" >> quality-summary.md
echo "**Generated on:** $(date)" >> quality-summary.md
echo "" >> quality-summary.md
echo "## Job Results" >> quality-summary.md
echo "- **Complexity Analysis:** ${{ needs.complexity-analysis.result }}" >> quality-summary.md
echo "- **Dependency Analysis:** ${{ needs.dependency-analysis.result }}" >> quality-summary.md
echo "- **Duplication Analysis:** ${{ needs.duplication-analysis.result }}" >> quality-summary.md
echo "- **Type Coverage:** ${{ needs.type-coverage.result }}" >> quality-summary.md
echo "- **Performance Budget:** ${{ needs.performance-budget.result }}" >> quality-summary.md
echo "" >> quality-summary.md
echo "## Recommendations" >> quality-summary.md
echo "- Review complexity analysis for overly complex functions" >> quality-summary.md
echo "- Check for circular dependencies in the dependency analysis" >> quality-summary.md
echo "- Address any code duplication found" >> quality-summary.md
echo "- Improve type coverage where possible" >> quality-summary.md
echo "- Monitor bundle size to stay within performance budget" >> quality-summary.md
echo "" >> quality-summary.md
echo "📋 Full reports available in workflow artifacts."
- name: Upload quality summary
uses: actions/upload-artifact@v4
with:
name: quality-summary
path: quality-summary.md
retention-days: 90