Skip to content

Commit 175a907

Browse files
Merge pull request #3 from Lackadaisical-Security/copilot/fix-real-time-stats-api
Fix GitHub API authentication and add stats caching for resilient tracking
2 parents 0e97d1a + 0e0fe0a commit 175a907

5 files changed

Lines changed: 142 additions & 17 deletions

File tree

.github/workflows/stats-tracker.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ jobs:
1313
runs-on: ubuntu-latest
1414
permissions:
1515
contents: write
16+
metadata: read
1617

1718
steps:
1819
- name: Checkout repository

REALTIME_STATS.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
2-
"timestamp": "2026-01-04T23:06:02.761107Z",
2+
"timestamp": "2026-01-05T14:37:41.805435Z",
33
"local": {
4-
"commit_count": 4,
4+
"commit_count": 5,
55
"unique_contributors": 2,
6-
"last_commit_date": "2026-01-04 23:04:23 +0000",
7-
"last_commit_message": "Remove stats files from .gitignore to enable auto-tracking workflow",
8-
"current_branch": "copilot/fix-auto-tracking-issues",
6+
"last_commit_date": "2026-01-05 14:36:30 +0000",
7+
"last_commit_message": "Add caching for GitHub stats when API calls fail",
8+
"current_branch": "copilot/fix-real-time-stats-api",
99
"tracked_files": 63,
10-
"timestamp": "2026-01-04T23:06:02.771988Z"
10+
"timestamp": "2026-01-05T14:37:41.816614Z"
1111
},
1212
"github": {}
1313
}

REALTIME_STATS.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
# Repository Statistics - Real-Time
22

3-
**Last Updated:** 2026-01-04T23:06:02.761107Z
3+
**Last Updated:** 2026-01-05T14:37:41.805435Z
44

55
## 📊 Current Statistics
66

77
### Local Repository
88

99
| Metric | Value |
1010
|--------|-------|
11-
| 🌿 Current Branch | `copilot/fix-auto-tracking-issues` |
12-
| 📝 Total Commits | 4 |
11+
| 🌿 Current Branch | `copilot/fix-real-time-stats-api` |
12+
| 📝 Total Commits | 5 |
1313
| 👥 Contributors | 2 |
1414
| 📄 Tracked Files | 63 |
15-
| 🕐 Last Commit | 2026-01-04 23:04:23 |
16-
| 💬 Last Message | Remove stats files from .gitignore to enable auto-tracking workflow |
15+
| 🕐 Last Commit | 2026-01-05 14:36:30 |
16+
| 💬 Last Message | Add caching for GitHub stats when API calls fail |
1717

1818
---
1919

@@ -22,7 +22,7 @@
2222
Add these to your README.md:
2323

2424
```markdown
25-
<img src="https://img.shields.io/badge/commits-4-orange?style=flat-square">
25+
<img src="https://img.shields.io/badge/commits-5-orange?style=flat-square">
2626
```
2727

2828
---

STATS_HISTORY.json

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,83 @@
8989
"timestamp": "2026-01-04T23:06:02.771988Z"
9090
},
9191
"github": {}
92+
},
93+
{
94+
"timestamp": "2026-01-05T14:28:02.069860Z",
95+
"local": {
96+
"commit_count": 2,
97+
"unique_contributors": 2,
98+
"last_commit_date": "2026-01-05 14:26:06 +0000",
99+
"last_commit_message": "Initial plan",
100+
"current_branch": "copilot/fix-real-time-stats-api",
101+
"tracked_files": 63,
102+
"timestamp": "2026-01-05T14:28:02.080588Z"
103+
},
104+
"github": {}
105+
},
106+
{
107+
"timestamp": "2026-01-05T14:28:11.901823Z",
108+
"local": {
109+
"commit_count": 2,
110+
"unique_contributors": 2,
111+
"last_commit_date": "2026-01-05 14:26:06 +0000",
112+
"last_commit_message": "Initial plan",
113+
"current_branch": "copilot/fix-real-time-stats-api",
114+
"tracked_files": 63,
115+
"timestamp": "2026-01-05T14:28:11.912102Z"
116+
},
117+
"github": {}
118+
},
119+
{
120+
"timestamp": "2026-01-05T14:31:28.134321Z",
121+
"local": {
122+
"commit_count": 3,
123+
"unique_contributors": 2,
124+
"last_commit_date": "2026-01-05 14:30:26 +0000",
125+
"last_commit_message": "Initial plan",
126+
"current_branch": "copilot/fix-real-time-stats-api",
127+
"tracked_files": 63,
128+
"timestamp": "2026-01-05T14:31:28.144853Z"
129+
},
130+
"github": {}
131+
},
132+
{
133+
"timestamp": "2026-01-05T14:32:59.155485Z",
134+
"local": {
135+
"commit_count": 3,
136+
"unique_contributors": 2,
137+
"last_commit_date": "2026-01-05 14:30:26 +0000",
138+
"last_commit_message": "Initial plan",
139+
"current_branch": "copilot/fix-real-time-stats-api",
140+
"tracked_files": 63,
141+
"timestamp": "2026-01-05T14:32:59.166468Z"
142+
},
143+
"github": {}
144+
},
145+
{
146+
"timestamp": "2026-01-05T14:36:19.877520Z",
147+
"local": {
148+
"commit_count": 4,
149+
"unique_contributors": 2,
150+
"last_commit_date": "2026-01-05 14:33:19 +0000",
151+
"last_commit_message": "Improve GitHub API error handling and update auth format",
152+
"current_branch": "copilot/fix-real-time-stats-api",
153+
"tracked_files": 63,
154+
"timestamp": "2026-01-05T14:36:19.888287Z"
155+
},
156+
"github": {}
157+
},
158+
{
159+
"timestamp": "2026-01-05T14:37:41.805435Z",
160+
"local": {
161+
"commit_count": 5,
162+
"unique_contributors": 2,
163+
"last_commit_date": "2026-01-05 14:36:30 +0000",
164+
"last_commit_message": "Add caching for GitHub stats when API calls fail",
165+
"current_branch": "copilot/fix-real-time-stats-api",
166+
"tracked_files": 63,
167+
"timestamp": "2026-01-05T14:37:41.816614Z"
168+
},
169+
"github": {}
92170
}
93171
]

realtime_stats_tracker.py

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,41 @@ def github_api_request(self, endpoint):
3434

3535
token = self.get_github_token()
3636
if token:
37-
headers['Authorization'] = f'token {token}'
37+
headers['Authorization'] = f'Bearer {token}'
3838

3939
try:
4040
req = urllib.request.Request(url, headers=headers)
4141
with urllib.request.urlopen(req, timeout=10) as response:
4242
return json.loads(response.read().decode())
4343
except urllib.error.HTTPError as e:
44+
# Try to get detailed error message from response body
45+
error_msg = None
46+
try:
47+
error_body = e.read().decode()
48+
error_data = json.loads(error_body)
49+
error_msg = error_data.get('message', '')
50+
except Exception:
51+
pass
52+
4453
if e.code == 403:
45-
print(f"⚠️ GitHub API rate limit reached. Set GITHUB_TOKEN env var for higher limits.")
54+
if error_msg:
55+
print(f"⚠️ GitHub API error (403): {error_msg}")
56+
if 'rate limit' in error_msg.lower():
57+
print(f"💡 Set GITHUB_TOKEN env var for higher rate limits.")
58+
elif 'credentials' in error_msg.lower() or 'token' in error_msg.lower():
59+
print(f"💡 Check that GITHUB_TOKEN has the correct permissions.")
60+
else:
61+
print(f"⚠️ GitHub API access denied (403). Set GITHUB_TOKEN env var with proper permissions.")
62+
return None
63+
elif e.code == 404:
64+
print(f"⚠️ GitHub API endpoint not found (404): {endpoint}")
65+
return None
66+
else:
67+
if error_msg:
68+
print(f"⚠️ GitHub API error {e.code}: {error_msg}")
69+
else:
70+
print(f"⚠️ GitHub API error {e.code}: {e.reason}")
4671
return None
47-
print(f"⚠️ GitHub API error {e.code}: {e.reason}")
48-
return None
4972
except Exception as e:
5073
print(f"⚠️ Error fetching from GitHub API: {e}")
5174
return None
@@ -151,12 +174,28 @@ def collect_stats(self):
151174
"""Collect all statistics"""
152175
print("🔍 Collecting repository statistics...\n")
153176

177+
# Try to load previous stats for fallback
178+
previous_github_stats = {}
179+
if self.stats_file.exists():
180+
try:
181+
with open(self.stats_file, 'r') as f:
182+
previous_data = json.load(f)
183+
previous_github_stats = previous_data.get('github', {})
184+
except Exception:
185+
pass
186+
154187
stats = {
155188
"timestamp": datetime.now(UTC).strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
156189
"local": self.get_local_git_stats(),
157190
"github": self.get_github_stats()
158191
}
159192

193+
# If GitHub stats are empty but we have previous stats, preserve them
194+
if not stats["github"] and previous_github_stats:
195+
print("ℹ️ Using cached GitHub stats from previous successful fetch")
196+
stats["github"] = previous_github_stats
197+
stats["github_cached"] = True
198+
160199
return stats
161200

162201
def save_stats(self, stats):
@@ -226,6 +265,8 @@ def display_stats(self, stats):
226265
# GitHub stats
227266
if stats.get("github"):
228267
print("\n🌐 GITHUB STATISTICS:")
268+
if stats.get("github_cached"):
269+
print(" ℹ️ (Using cached data from previous successful fetch)")
229270
print("-" * 80)
230271
gh = stats["github"]
231272
print(f" ⭐ Stars: {gh.get('stars', 'N/A')}")
@@ -251,7 +292,12 @@ def generate_stats_markdown(self, stats):
251292
md = f"""# Repository Statistics - Real-Time
252293
253294
**Last Updated:** {stats['timestamp']}
254-
295+
"""
296+
297+
if stats.get("github_cached"):
298+
md += "\n> ℹ️ **Note:** GitHub metrics below are cached from previous successful fetch (current API call failed)\n"
299+
300+
md += """
255301
## 📊 Current Statistics
256302
257303
"""

0 commit comments

Comments
 (0)