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..27b835d 100644
--- a/backend/app/services/builds.py
+++ b/backend/app/services/builds.py
@@ -15,26 +15,16 @@
# 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 +48,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 +73,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"