badge router
This commit is contained in:
72
main.py
72
main.py
@@ -1,58 +1,28 @@
|
|||||||
from fastapi import FastAPI, HTTPException, Query
|
from fastapi import FastAPI
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from pathlib import Path
|
|
||||||
import xml.etree.ElementTree as ET
|
|
||||||
|
|
||||||
app = FastAPI()
|
from routers.badge import router as coverage_badge_router
|
||||||
|
|
||||||
|
app = FastAPI(title="Coverage API")
|
||||||
|
|
||||||
|
# Optional: CORS for your frontend or badges
|
||||||
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=["*"], # tighten if needed
|
||||||
|
allow_credentials=True,
|
||||||
|
allow_methods=["*"],
|
||||||
|
allow_headers=["*"],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Mount routers
|
||||||
|
app.include_router(coverage_badge_router)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/health")
|
@app.get("/health")
|
||||||
async def health_check():
|
async def root():
|
||||||
return {"status": "ok"}
|
return {"status": "ok"}
|
||||||
|
|
||||||
|
|
||||||
def parse_coverage_percentage(coverage_file: Path) -> float:
|
@app.get("/")
|
||||||
"""Parse the overall coverage percentage from coverage.xml."""
|
async def root():
|
||||||
tree = ET.parse(coverage_file)
|
return {"message": "Coverage API is running"}
|
||||||
root = tree.getroot()
|
|
||||||
line_rate = float(root.attrib.get("line-rate", 0))
|
|
||||||
return round(line_rate * 100, 2)
|
|
||||||
|
|
||||||
|
|
||||||
def get_color(pct: float) -> str:
|
|
||||||
"""Return badge color based on coverage."""
|
|
||||||
if pct >= 90:
|
|
||||||
return "brightgreen"
|
|
||||||
if pct >= 75:
|
|
||||||
return "green"
|
|
||||||
if pct >= 60:
|
|
||||||
return "yellow"
|
|
||||||
if pct >= 40:
|
|
||||||
return "orange"
|
|
||||||
return "red"
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/badge", response_class=JSONResponse)
|
|
||||||
async def get_coverage_badge(project: str = Query(..., description="Project folder name")):
|
|
||||||
"""
|
|
||||||
Return a Shields.io-compatible badge JSON for the given project's coverage.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
/badge?project=mongo-ops
|
|
||||||
Use with Shields.io:
|
|
||||||
https://img.shields.io/endpoint?url=https://api.aetoskia.com/coverage/badge?project=mongo-ops
|
|
||||||
"""
|
|
||||||
project_dir = Path.cwd() / project
|
|
||||||
coverage_file = project_dir / "coverage.xml"
|
|
||||||
|
|
||||||
if not coverage_file.exists():
|
|
||||||
raise HTTPException(status_code=404, detail=f"No coverage.xml found in '{project}'")
|
|
||||||
|
|
||||||
pct = parse_coverage_percentage(coverage_file)
|
|
||||||
|
|
||||||
return {
|
|
||||||
"schemaVersion": 1,
|
|
||||||
"label": f"{project} coverage",
|
|
||||||
"message": f"{pct}%",
|
|
||||||
"color": get_color(pct)
|
|
||||||
}
|
|
||||||
|
|||||||
57
routers/badge.py
Normal file
57
routers/badge.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
from fastapi import APIRouter, Query, HTTPException
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
from pathlib import Path
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/badge", tags=["coverage", "badge"])
|
||||||
|
|
||||||
|
|
||||||
|
# ---------- Helper functions ----------
|
||||||
|
|
||||||
|
def parse_coverage_percentage(coverage_file: Path) -> float:
|
||||||
|
"""Parse the overall coverage percentage from coverage.xml."""
|
||||||
|
tree = ET.parse(coverage_file)
|
||||||
|
root = tree.getroot()
|
||||||
|
line_rate = float(root.attrib.get("line-rate", 0))
|
||||||
|
return round(line_rate * 100, 2)
|
||||||
|
|
||||||
|
|
||||||
|
def get_color(pct: float) -> str:
|
||||||
|
"""Return badge color based on coverage."""
|
||||||
|
if pct >= 90:
|
||||||
|
return "brightgreen"
|
||||||
|
if pct >= 75:
|
||||||
|
return "green"
|
||||||
|
if pct >= 60:
|
||||||
|
return "yellow"
|
||||||
|
if pct >= 40:
|
||||||
|
return "orange"
|
||||||
|
return "red"
|
||||||
|
|
||||||
|
|
||||||
|
# ---------- Route ----------
|
||||||
|
@router.get("/{project}", response_class=JSONResponse)
|
||||||
|
async def get_coverage_badge(project: str):
|
||||||
|
"""
|
||||||
|
Return a Shields.io-compatible badge JSON for the given project's coverage.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
/coverage/badge?project=mongo-ops
|
||||||
|
|
||||||
|
Use with Shields.io:
|
||||||
|
https://img.shields.io/endpoint?url=https://api.aetoskia.com/coverage/mongo-ops/badge
|
||||||
|
"""
|
||||||
|
project_dir = Path.cwd() / project
|
||||||
|
coverage_file = project_dir / "coverage.xml"
|
||||||
|
|
||||||
|
if not coverage_file.exists():
|
||||||
|
raise HTTPException(status_code=404, detail=f"No coverage.xml found in '{project}'")
|
||||||
|
|
||||||
|
pct = parse_coverage_percentage(coverage_file)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"label": f"{project} coverage",
|
||||||
|
"message": f"{pct}%",
|
||||||
|
"color": get_color(pct),
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user