Skip to content

Commit 7666bcb

Browse files
committed
feat: add dynamic health and advanced metrics badges
- Success rate badge with color coding based on workflow performance - Average duration badge for performance monitoring - Code coverage badge with automated threshold coloring - Lines of code badge with smart formatting - Comment percentage badge encouraging documentation - Test execution duration badge for performance tracking All badges update automatically and link to relevant workflows. Requires HEALTH_GIST_ID and METRICS_GIST_ID secrets.
1 parent ffd306e commit 7666bcb

3 files changed

Lines changed: 223 additions & 0 deletions

File tree

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
name: Advanced Metrics Badges
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- 'src/**'
8+
- 'tests/**'
9+
- 'pyproject.toml'
10+
workflow_dispatch:
11+
12+
jobs:
13+
config:
14+
name: Configuration
15+
uses: ./.github/workflows/shared-config.yml
16+
17+
metrics:
18+
name: Generate Advanced Metrics
19+
needs: config
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
actions: read
24+
25+
steps:
26+
- name: Checkout code
27+
uses: actions/checkout@v6.0.1
28+
29+
- name: Set up Python
30+
uses: actions/setup-python@v5
31+
with:
32+
python-version: ${{ needs.config.outputs.default-python-version }}
33+
34+
- name: Cache management
35+
uses: ./.github/workflows/cache-management.yml
36+
with:
37+
python-version: ${{ needs.config.outputs.default-python-version }}
38+
39+
- name: Install dependencies
40+
run: |
41+
python -m pip install --upgrade pip
42+
pip install coverage pytest cloc
43+
44+
- name: Run tests with coverage
45+
run: |
46+
coverage run -m pytest tests/ --tb=short
47+
coverage report --format=total > coverage.txt
48+
coverage xml
49+
50+
- name: Calculate lines of code
51+
run: |
52+
# Install cloc if not available
53+
sudo apt-get update && sudo apt-get install -y cloc
54+
55+
# Count lines of code (excluding tests, docs, config)
56+
cloc src/ --json --out=cloc.json
57+
58+
# Extract metrics
59+
total_lines=$(jq -r '.SUM.code // 0' cloc.json)
60+
comment_lines=$(jq -r '.SUM.comment // 0' cloc.json)
61+
62+
# Calculate comment percentage
63+
if [ "$total_lines" -gt 0 ]; then
64+
comment_percent=$(echo "scale=1; $comment_lines * 100 / $total_lines" | bc)
65+
else
66+
comment_percent="0"
67+
fi
68+
69+
# Format for badges
70+
if [ "$total_lines" -ge 1000 ]; then
71+
loc_display=$(echo "scale=1; $total_lines / 1000" | bc)k
72+
else
73+
loc_display="$total_lines"
74+
fi
75+
76+
echo "TOTAL_LOC=$loc_display" >> $GITHUB_ENV
77+
echo "COMMENT_PERCENT=$comment_percent" >> $GITHUB_ENV
78+
79+
- name: Run performance test
80+
run: |
81+
start_time=$(date +%s.%N)
82+
python -m pytest tests/ -x --tb=no -q
83+
end_time=$(date +%s.%N)
84+
85+
# Calculate duration in seconds
86+
duration=$(echo "$end_time - $start_time" | bc)
87+
duration_formatted=$(printf "%.1fs" "$duration")
88+
89+
echo "TEST_DURATION=$duration_formatted" >> $GITHUB_ENV
90+
91+
- name: Extract coverage percentage
92+
run: |
93+
coverage_percent=$(cat coverage.txt)
94+
echo "COVERAGE_PERCENT=$coverage_percent" >> $GITHUB_ENV
95+
96+
# Set coverage color
97+
if [ "$coverage_percent" -ge 90 ]; then
98+
coverage_color="brightgreen"
99+
elif [ "$coverage_percent" -ge 75 ]; then
100+
coverage_color="yellow"
101+
elif [ "$coverage_percent" -ge 60 ]; then
102+
coverage_color="orange"
103+
else
104+
coverage_color="red"
105+
fi
106+
107+
echo "COVERAGE_COLOR=$coverage_color" >> $GITHUB_ENV
108+
109+
- name: Create coverage badge
110+
uses: schneegans/dynamic-badges-action@v1.7.0
111+
with:
112+
auth: ${{ secrets.GITHUB_TOKEN }}
113+
gistID: ${{ secrets.METRICS_GIST_ID }}
114+
filename: coverage.json
115+
label: Coverage
116+
message: ${{ env.COVERAGE_PERCENT }}%
117+
color: ${{ env.COVERAGE_COLOR }}
118+
119+
- name: Create lines of code badge
120+
uses: schneegans/dynamic-badges-action@v1.7.0
121+
with:
122+
auth: ${{ secrets.GITHUB_TOKEN }}
123+
gistID: ${{ secrets.METRICS_GIST_ID }}
124+
filename: lines-of-code.json
125+
label: Lines of Code
126+
message: ${{ env.TOTAL_LOC }}
127+
color: lightgrey
128+
129+
- name: Create comment percentage badge
130+
uses: schneegans/dynamic-badges-action@v1.7.0
131+
with:
132+
auth: ${{ secrets.GITHUB_TOKEN }}
133+
gistID: ${{ secrets.METRICS_GIST_ID }}
134+
filename: comments.json
135+
label: Comments
136+
message: ${{ env.COMMENT_PERCENT }}%
137+
valColorRange: ${{ env.COMMENT_PERCENT }}
138+
maxColorRange: 30
139+
minColorRange: 0
140+
141+
- name: Create test duration badge
142+
uses: schneegans/dynamic-badges-action@v1.7.0
143+
with:
144+
auth: ${{ secrets.GITHUB_TOKEN }}
145+
gistID: ${{ secrets.METRICS_GIST_ID }}
146+
filename: test-duration.json
147+
label: Test Duration
148+
message: ${{ env.TEST_DURATION }}
149+
color: blue
150+
151+
- name: Upload coverage report
152+
uses: actions/upload-artifact@v4.4.3
153+
with:
154+
name: coverage-report
155+
retention-days: 30
156+
path: |
157+
coverage.xml
158+
cloc.json

.github/workflows/health-monitoring.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,61 @@ jobs:
7676
echo "---" >> health-report.md
7777
echo "*Generated automatically by [Workflow Health Monitoring](.github/workflows/health-monitoring.yml)*" >> health-report.md
7878
79+
- name: Calculate badge metrics
80+
run: |
81+
if [ -f workflow-stats.csv ]; then
82+
# Calculate overall success rate
83+
overall_success=$(tail -n +2 workflow-stats.csv | awk -F',' '
84+
BEGIN { total_runs=0; weighted_success=0 }
85+
{ total_runs += $5; weighted_success += ($4 * $5) }
86+
END { if(total_runs > 0) print int(weighted_success/total_runs); else print 0 }
87+
')
88+
89+
# Calculate average duration
90+
avg_duration=$(tail -n +2 workflow-stats.csv | awk -F',' '
91+
BEGIN { total=0; count=0 }
92+
{ total += $2; count++ }
93+
END { if(count > 0) printf "%.1f", total/count; else print "0" }
94+
')
95+
96+
# Set badge colors based on success rate
97+
if [ "$overall_success" -ge 95 ]; then
98+
success_color="brightgreen"
99+
elif [ "$overall_success" -ge 80 ]; then
100+
success_color="yellow"
101+
else
102+
success_color="red"
103+
fi
104+
105+
echo "SUCCESS_RATE=$overall_success" >> $GITHUB_ENV
106+
echo "AVG_DURATION=${avg_duration}min" >> $GITHUB_ENV
107+
echo "SUCCESS_COLOR=$success_color" >> $GITHUB_ENV
108+
else
109+
echo "SUCCESS_RATE=0" >> $GITHUB_ENV
110+
echo "AVG_DURATION=0min" >> $GITHUB_ENV
111+
echo "SUCCESS_COLOR=lightgrey" >> $GITHUB_ENV
112+
fi
113+
114+
- name: Create success rate badge
115+
uses: schneegans/dynamic-badges-action@v1.7.0
116+
with:
117+
auth: ${{ secrets.GITHUB_TOKEN }}
118+
gistID: ${{ secrets.HEALTH_GIST_ID }}
119+
filename: success-rate.json
120+
label: Success Rate
121+
message: ${{ env.SUCCESS_RATE }}%
122+
color: ${{ env.SUCCESS_COLOR }}
123+
124+
- name: Create performance badge
125+
uses: schneegans/dynamic-badges-action@v1.7.0
126+
with:
127+
auth: ${{ secrets.GITHUB_TOKEN }}
128+
gistID: ${{ secrets.HEALTH_GIST_ID }}
129+
filename: avg-duration.json
130+
label: Avg Duration
131+
message: ${{ env.AVG_DURATION }}
132+
color: blue
133+
79134
- name: Create health report issue
80135
uses: peter-evans/create-issue-from-file@v5
81136
with:

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@
88
[![Python Versions](https://img.shields.io/pypi/pyversions/open-resource-broker)](https://pypi.org/project/open-resource-broker/)
99
[![License](https://img.shields.io/github/license/awslabs/open-resource-broker)](LICENSE)
1010

11+
**Health & Performance:**
12+
[![Success Rate](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/awslabs/HEALTH_GIST_ID/raw/success-rate.json)](https://github.com/awslabs/open-resource-broker/actions/workflows/health-monitoring.yml)
13+
[![Avg Duration](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/awslabs/HEALTH_GIST_ID/raw/avg-duration.json)](https://github.com/awslabs/open-resource-broker/actions/workflows/health-monitoring.yml)
14+
15+
**Code Quality:**
16+
[![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/awslabs/METRICS_GIST_ID/raw/coverage.json)](https://github.com/awslabs/open-resource-broker/actions/workflows/advanced-metrics.yml)
17+
[![Lines of Code](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/awslabs/METRICS_GIST_ID/raw/lines-of-code.json)](https://github.com/awslabs/open-resource-broker/actions/workflows/advanced-metrics.yml)
18+
[![Comments](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/awslabs/METRICS_GIST_ID/raw/comments.json)](https://github.com/awslabs/open-resource-broker/actions/workflows/advanced-metrics.yml)
19+
[![Test Duration](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/awslabs/METRICS_GIST_ID/raw/test-duration.json)](https://github.com/awslabs/open-resource-broker/actions/workflows/advanced-metrics.yml)
20+
1121
A cloud provider integration plugin for IBM Spectrum Symphony Host Factory, enabling dynamic provisioning of compute resources with a REST API interface and structured architecture implementation.
1222

1323
## Overview

0 commit comments

Comments
 (0)