diff --git a/.github/workflows/stats-tracker.yml b/.github/workflows/stats-tracker.yml
index d26f0b7..d4c40b3 100644
--- a/.github/workflows/stats-tracker.yml
+++ b/.github/workflows/stats-tracker.yml
@@ -13,6 +13,7 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: write
+ metadata: read
steps:
- name: Checkout repository
diff --git a/REALTIME_STATS.json b/REALTIME_STATS.json
index 5d3ef15..d835670 100644
--- a/REALTIME_STATS.json
+++ b/REALTIME_STATS.json
@@ -1,13 +1,13 @@
{
- "timestamp": "2026-01-04T23:06:02.761107Z",
+ "timestamp": "2026-01-05T14:37:41.805435Z",
"local": {
- "commit_count": 4,
+ "commit_count": 5,
"unique_contributors": 2,
- "last_commit_date": "2026-01-04 23:04:23 +0000",
- "last_commit_message": "Remove stats files from .gitignore to enable auto-tracking workflow",
- "current_branch": "copilot/fix-auto-tracking-issues",
+ "last_commit_date": "2026-01-05 14:36:30 +0000",
+ "last_commit_message": "Add caching for GitHub stats when API calls fail",
+ "current_branch": "copilot/fix-real-time-stats-api",
"tracked_files": 63,
- "timestamp": "2026-01-04T23:06:02.771988Z"
+ "timestamp": "2026-01-05T14:37:41.816614Z"
},
"github": {}
}
\ No newline at end of file
diff --git a/REALTIME_STATS.md b/REALTIME_STATS.md
index 35bc497..bff996a 100644
--- a/REALTIME_STATS.md
+++ b/REALTIME_STATS.md
@@ -1,6 +1,6 @@
# Repository Statistics - Real-Time
-**Last Updated:** 2026-01-04T23:06:02.761107Z
+**Last Updated:** 2026-01-05T14:37:41.805435Z
## š Current Statistics
@@ -8,12 +8,12 @@
| Metric | Value |
|--------|-------|
-| šæ Current Branch | `copilot/fix-auto-tracking-issues` |
-| š Total Commits | 4 |
+| šæ Current Branch | `copilot/fix-real-time-stats-api` |
+| š Total Commits | 5 |
| š„ Contributors | 2 |
| š Tracked Files | 63 |
-| š Last Commit | 2026-01-04 23:04:23 |
-| š¬ Last Message | Remove stats files from .gitignore to enable auto-tracking workflow |
+| š Last Commit | 2026-01-05 14:36:30 |
+| š¬ Last Message | Add caching for GitHub stats when API calls fail |
---
@@ -22,7 +22,7 @@
Add these to your README.md:
```markdown
-
+
```
---
diff --git a/STATS_HISTORY.json b/STATS_HISTORY.json
index 7e01710..96034cd 100644
--- a/STATS_HISTORY.json
+++ b/STATS_HISTORY.json
@@ -89,5 +89,83 @@
"timestamp": "2026-01-04T23:06:02.771988Z"
},
"github": {}
+ },
+ {
+ "timestamp": "2026-01-05T14:28:02.069860Z",
+ "local": {
+ "commit_count": 2,
+ "unique_contributors": 2,
+ "last_commit_date": "2026-01-05 14:26:06 +0000",
+ "last_commit_message": "Initial plan",
+ "current_branch": "copilot/fix-real-time-stats-api",
+ "tracked_files": 63,
+ "timestamp": "2026-01-05T14:28:02.080588Z"
+ },
+ "github": {}
+ },
+ {
+ "timestamp": "2026-01-05T14:28:11.901823Z",
+ "local": {
+ "commit_count": 2,
+ "unique_contributors": 2,
+ "last_commit_date": "2026-01-05 14:26:06 +0000",
+ "last_commit_message": "Initial plan",
+ "current_branch": "copilot/fix-real-time-stats-api",
+ "tracked_files": 63,
+ "timestamp": "2026-01-05T14:28:11.912102Z"
+ },
+ "github": {}
+ },
+ {
+ "timestamp": "2026-01-05T14:31:28.134321Z",
+ "local": {
+ "commit_count": 3,
+ "unique_contributors": 2,
+ "last_commit_date": "2026-01-05 14:30:26 +0000",
+ "last_commit_message": "Initial plan",
+ "current_branch": "copilot/fix-real-time-stats-api",
+ "tracked_files": 63,
+ "timestamp": "2026-01-05T14:31:28.144853Z"
+ },
+ "github": {}
+ },
+ {
+ "timestamp": "2026-01-05T14:32:59.155485Z",
+ "local": {
+ "commit_count": 3,
+ "unique_contributors": 2,
+ "last_commit_date": "2026-01-05 14:30:26 +0000",
+ "last_commit_message": "Initial plan",
+ "current_branch": "copilot/fix-real-time-stats-api",
+ "tracked_files": 63,
+ "timestamp": "2026-01-05T14:32:59.166468Z"
+ },
+ "github": {}
+ },
+ {
+ "timestamp": "2026-01-05T14:36:19.877520Z",
+ "local": {
+ "commit_count": 4,
+ "unique_contributors": 2,
+ "last_commit_date": "2026-01-05 14:33:19 +0000",
+ "last_commit_message": "Improve GitHub API error handling and update auth format",
+ "current_branch": "copilot/fix-real-time-stats-api",
+ "tracked_files": 63,
+ "timestamp": "2026-01-05T14:36:19.888287Z"
+ },
+ "github": {}
+ },
+ {
+ "timestamp": "2026-01-05T14:37:41.805435Z",
+ "local": {
+ "commit_count": 5,
+ "unique_contributors": 2,
+ "last_commit_date": "2026-01-05 14:36:30 +0000",
+ "last_commit_message": "Add caching for GitHub stats when API calls fail",
+ "current_branch": "copilot/fix-real-time-stats-api",
+ "tracked_files": 63,
+ "timestamp": "2026-01-05T14:37:41.816614Z"
+ },
+ "github": {}
}
]
\ No newline at end of file
diff --git a/realtime_stats_tracker.py b/realtime_stats_tracker.py
index eaa6acf..8111eba 100755
--- a/realtime_stats_tracker.py
+++ b/realtime_stats_tracker.py
@@ -34,18 +34,41 @@ def github_api_request(self, endpoint):
token = self.get_github_token()
if token:
- headers['Authorization'] = f'token {token}'
+ headers['Authorization'] = f'Bearer {token}'
try:
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req, timeout=10) as response:
return json.loads(response.read().decode())
except urllib.error.HTTPError as e:
+ # Try to get detailed error message from response body
+ error_msg = None
+ try:
+ error_body = e.read().decode()
+ error_data = json.loads(error_body)
+ error_msg = error_data.get('message', '')
+ except Exception:
+ pass
+
if e.code == 403:
- print(f"ā ļø GitHub API rate limit reached. Set GITHUB_TOKEN env var for higher limits.")
+ if error_msg:
+ print(f"ā ļø GitHub API error (403): {error_msg}")
+ if 'rate limit' in error_msg.lower():
+ print(f"š” Set GITHUB_TOKEN env var for higher rate limits.")
+ elif 'credentials' in error_msg.lower() or 'token' in error_msg.lower():
+ print(f"š” Check that GITHUB_TOKEN has the correct permissions.")
+ else:
+ print(f"ā ļø GitHub API access denied (403). Set GITHUB_TOKEN env var with proper permissions.")
+ return None
+ elif e.code == 404:
+ print(f"ā ļø GitHub API endpoint not found (404): {endpoint}")
+ return None
+ else:
+ if error_msg:
+ print(f"ā ļø GitHub API error {e.code}: {error_msg}")
+ else:
+ print(f"ā ļø GitHub API error {e.code}: {e.reason}")
return None
- print(f"ā ļø GitHub API error {e.code}: {e.reason}")
- return None
except Exception as e:
print(f"ā ļø Error fetching from GitHub API: {e}")
return None
@@ -151,12 +174,28 @@ def collect_stats(self):
"""Collect all statistics"""
print("š Collecting repository statistics...\n")
+ # Try to load previous stats for fallback
+ previous_github_stats = {}
+ if self.stats_file.exists():
+ try:
+ with open(self.stats_file, 'r') as f:
+ previous_data = json.load(f)
+ previous_github_stats = previous_data.get('github', {})
+ except Exception:
+ pass
+
stats = {
"timestamp": datetime.now(UTC).strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
"local": self.get_local_git_stats(),
"github": self.get_github_stats()
}
+ # If GitHub stats are empty but we have previous stats, preserve them
+ if not stats["github"] and previous_github_stats:
+ print("ā¹ļø Using cached GitHub stats from previous successful fetch")
+ stats["github"] = previous_github_stats
+ stats["github_cached"] = True
+
return stats
def save_stats(self, stats):
@@ -226,6 +265,8 @@ def display_stats(self, stats):
# GitHub stats
if stats.get("github"):
print("\nš GITHUB STATISTICS:")
+ if stats.get("github_cached"):
+ print(" ā¹ļø (Using cached data from previous successful fetch)")
print("-" * 80)
gh = stats["github"]
print(f" ā Stars: {gh.get('stars', 'N/A')}")
@@ -251,7 +292,12 @@ def generate_stats_markdown(self, stats):
md = f"""# Repository Statistics - Real-Time
**Last Updated:** {stats['timestamp']}
-
+"""
+
+ if stats.get("github_cached"):
+ md += "\n> ā¹ļø **Note:** GitHub metrics below are cached from previous successful fetch (current API call failed)\n"
+
+ md += """
## š Current Statistics
"""