diff --git a/backend/app/data/build_history.json b/backend/app/data/build_history.json deleted file mode 100644 index cf07192..0000000 --- a/backend/app/data/build_history.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "builds": [ - { - "number": 205, - "status": "success", - "branch": "main", - "commit": "9ac3f91", - "author": "Miau", - "finished_at": "2024-05-04T10:20:00Z", - "duration_seconds": 312 - }, - { - "number": 204, - "status": "failed", - "branch": "feature/nosetioestoesunmock", - "commit": "75c4ba2", - "author": "Miau", - "finished_at": "2024-05-04T09:50:00Z", - "duration_seconds": 188, - "failed_stage": "tests", - "fun_message": "woops" - }, - { - "number": 203, - "status": "failed", - "branch": "main", - "commit": "512ca7e", - "author": "Miau", - "finished_at": "2024-05-04T09:10:00Z", - "duration_seconds": 140, - "failed_stage": "lint", - "fun_message": "Nadie pasa en local el linter" - }, - { - "number": 202, - "status": "success", - "branch": "hotfix/tehedichoqueestoesunmock?", - "commit": "c73d8ab", - "author": "Miau", - "finished_at": "2024-05-03T18:30:00Z", - "duration_seconds": 276 - } - ] -} diff --git a/backend/app/main.py b/backend/app/main.py index 7451365..9aaedb9 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -16,8 +16,10 @@ import time -from fastapi import FastAPI +import requests +from fastapi import FastAPI, status from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse from app.services.builds import build_history from app.services.menu import build_menu @@ -76,4 +78,10 @@ def price_for_item(item: str): @app.get("/builds") def builds(): - return build_history() + try: + return build_history() + except (requests.RequestException, ValueError): + return JSONResponse( + status_code=status.HTTP_503_SERVICE_UNAVAILABLE, + content={"builds": [], "error": "jenkins_unavailable"}, + ) diff --git a/backend/app/services/builds.py b/backend/app/services/builds.py index d7634b3..93da222 100644 --- a/backend/app/services/builds.py +++ b/backend/app/services/builds.py @@ -15,26 +15,17 @@ # along with this program. If not, see . import base64 -import json -from pathlib import Path from typing import Dict, List import requests from app.settings import settings -DATA_DIR = Path(__file__).resolve().parent.parent / "data" - - -def _load_json(filename: str) -> Dict: - path = DATA_DIR / filename - with open(path, encoding="utf-8") as file: - return json.load(file) - def _sort_builds(builds: List[Dict]) -> List[Dict]: return sorted(builds, key=lambda build: build.get("number", 0), reverse=True) + def normalize_build(build: Dict) -> Dict: changes = build.get("changeSets", []) commits = [] @@ -58,11 +49,16 @@ def normalize_build(build: Dict) -> Dict: def _auth_header() -> Dict[str, str]: + if not settings.jenkins_user or not settings.jenkins_token: + return {} token = f"{settings.jenkins_user}:{settings.jenkins_token}" encoded = base64.b64encode(token.encode()).decode() return {"Authorization": f"Basic {encoded}"} + def fetch_builds(limit: int = 5) -> List[Dict]: + if not settings.jenkins_job_name: + raise ValueError("JENKINS_JOB_NAME not configured") url = ( f"{settings.jenkins_base_url}/job/{settings.jenkins_job_name}/api/json" "?tree=builds[number,url,result,timestamp,duration," @@ -78,6 +74,4 @@ def fetch_builds(limit: int = 5) -> List[Dict]: def build_history() -> Dict: """Return Jenkins build history data.""" builds = fetch_builds() - return { - "builds": [normalize_build(b) for b in builds] - } + return {"builds": [normalize_build(b) for b in builds]} diff --git a/backend/tests/test_api.py b/backend/tests/test_api.py index ee9d833..28165b9 100644 --- a/backend/tests/test_api.py +++ b/backend/tests/test_api.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import requests from fastapi.testclient import TestClient from app.main import app @@ -106,3 +107,16 @@ def test_build_history(monkeypatch): assert second["status"] == "running" assert second["duration_seconds"] == 1 assert second["commits"] == [] + + +def test_build_history_error_returns_empty(monkeypatch): + def raise_error(limit=5): + raise requests.RequestException("boom") + + monkeypatch.setattr("app.services.builds.fetch_builds", raise_error) + + response = client.get("/builds") + assert response.status_code == 503 + body = response.json() + assert body["builds"] == [] + assert body["error"] == "jenkins_unavailable"