generated from coulomb/repo-seed
feat(state-hub): v0.3 MCP tools + dashboard pages for contributions and SBOM
MCP server additions (5 tools + 3 resources):
- register_contribution(), update_contribution_status(), get_contributions()
- ingest_sbom_tool(repo_slug, lockfile_path) — shells out to ingest_sbom.py
- get_licence_report()
- state://contributions, state://sbom/aggregated, state://sbom/{repo_slug}
Dashboard pages:
- contributions.md — live-polled Kanban by status (draft→merged), filter bar
(type/status/repo), KPI grid (total + per type), follow-up banner, full table
- sbom.md — licence distribution bar chart (Plot), copyleft risk section,
package table with ecosystem/direct/dev filters, repo-slug resolution
- data/contributions.json.py, data/sbom.json.py — Observable data loaders
- index.md — added Contribution & SBOM Health KPI row (total, follow-up count,
copyleft risk indicator; sourced from state summary fields)
- observablehq.config.js — added Contributions + SBOM to nav
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
15
dashboard/src/data/contributions.json.py
Normal file
15
dashboard/src/data/contributions.json.py
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Observable data loader: fetches /contributions/ from the API."""
|
||||
import json
|
||||
import os
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
API_BASE = os.environ.get("API_BASE", "http://127.0.0.1:8000").rstrip("/")
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(f"{API_BASE}/contributions/", timeout=10) as resp:
|
||||
data = json.loads(resp.read())
|
||||
print(json.dumps(data))
|
||||
except urllib.error.URLError as e:
|
||||
print(json.dumps({"error": str(e), "contributions": []}))
|
||||
24
dashboard/src/data/sbom.json.py
Normal file
24
dashboard/src/data/sbom.json.py
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Observable data loader: fetches /sbom/ and /sbom/report/licences/ from the API."""
|
||||
import json
|
||||
import os
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
API_BASE = os.environ.get("API_BASE", "http://127.0.0.1:8000").rstrip("/")
|
||||
|
||||
result = {"entries": [], "licence_report": {"groups": [], "copyleft_direct_count": 0}}
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(f"{API_BASE}/sbom/", timeout=10) as resp:
|
||||
result["entries"] = json.loads(resp.read())
|
||||
except urllib.error.URLError as e:
|
||||
result["error_entries"] = str(e)
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(f"{API_BASE}/sbom/report/licences/", timeout=10) as resp:
|
||||
result["licence_report"] = json.loads(resp.read())
|
||||
except urllib.error.URLError as e:
|
||||
result["error_licences"] = str(e)
|
||||
|
||||
print(json.dumps(result))
|
||||
Reference in New Issue
Block a user