From 3eae610c5eecc86769cd773d9dd756900e3526f7 Mon Sep 17 00:00:00 2001 From: Manus AI Date: Tue, 18 Aug 2026 17:38:13 +0000 Subject: [PATCH] =?UTF-8?q?fix(deploy):=20construire=20le=20dashboard=20de?= =?UTF-8?q?puis=20les=20sources=20versionn=C3=A9es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 4 ++- src/frontend/src/pages/GiteaPage.jsx | 49 ++++++++++++++++++++++++++-- src/frontend/src/utils/api.js | 2 ++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index d088854..3f6c03c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,9 @@ services: dashboard: build: - context: . + # Les sources actives sont versionnées sous src/. Le contexte racine + # pouvait réutiliser d’anciens dossiers backend/frontend restés sur l’hôte. + context: ./src dockerfile: Dockerfile container_name: manus-dashboard # Le dashboard doit repartir seul après un arrêt anormal du processus. diff --git a/src/frontend/src/pages/GiteaPage.jsx b/src/frontend/src/pages/GiteaPage.jsx index e36f657..42b9ac1 100644 --- a/src/frontend/src/pages/GiteaPage.jsx +++ b/src/frontend/src/pages/GiteaPage.jsx @@ -9,8 +9,11 @@ import { Clock, User, Code, + CheckCircle2, + XCircle, + Loader2, } from 'lucide-react'; -import { getGiteaRepos, getGiteaCommits } from '../utils/api'; +import { getGiteaRepos, getGiteaCommits, getGiteaWorkflowRuns } from '../utils/api'; function formatDate(dateStr) { if (!dateStr) return 'N/A'; @@ -27,11 +30,25 @@ function formatSize(kb) { return `${(kb / 1024).toFixed(1)} MB`; } +function formatDuration(seconds) { + if (!Number.isFinite(seconds)) return 'En attente'; + const minutes = Math.floor(seconds / 60); + const remainingSeconds = seconds % 60; + return minutes > 0 ? `${minutes} min ${remainingSeconds.toString().padStart(2, '0')} s` : `${remainingSeconds} s`; +} + +function CiStatus({ run }) { + if (run.status !== 'completed') return En cours; + if (run.conclusion === 'success') return Réussi; + return {run.conclusion || 'Échec'}; +} + export default function GiteaPage() { const [repos, setRepos] = useState([]); const [loading, setLoading] = useState(true); const [selectedRepo, setSelectedRepo] = useState(null); const [commits, setCommits] = useState([]); + const [workflowRuns, setWorkflowRuns] = useState([]); const [loadingCommits, setLoadingCommits] = useState(false); const fetchRepos = async () => { @@ -51,11 +68,16 @@ export default function GiteaPage() { setSelectedRepo(fullName); try { const [owner, repo] = fullName.split('/'); - const res = await getGiteaCommits(owner, repo); - setCommits(res.data); + const [commitsResponse, runsResponse] = await Promise.all([ + getGiteaCommits(owner, repo), + getGiteaWorkflowRuns(owner, repo), + ]); + setCommits(commitsResponse.data); + setWorkflowRuns(runsResponse.data); } catch (err) { console.error('Erreur chargement commits:', err); setCommits([]); + setWorkflowRuns([]); } finally { setLoadingCommits(false); } @@ -191,6 +213,27 @@ export default function GiteaPage() { ) : (
+
+

Dernières validations CI

+ {workflowRuns.length === 0 ? ( +

Aucune validation CI trouvée pour ce dépôt.

+ ) : ( +
+ {workflowRuns.slice(0, 5).map((run) => ( +
+
+

{run.name}

+

{run.commit?.slice(0, 7) || 'Commit inconnu'} · {formatDate(run.createdAt)}

+
+
+ + {formatDuration(run.durationSeconds)} +
+
+ ))} +
+ )} +
{commits.map((commit, idx) => (
diff --git a/src/frontend/src/utils/api.js b/src/frontend/src/utils/api.js index 322ad77..d3c675e 100644 --- a/src/frontend/src/utils/api.js +++ b/src/frontend/src/utils/api.js @@ -59,6 +59,8 @@ export const getDeployments = (appId) => export const getGiteaRepos = () => api.get('/gitea/repos'); export const getGiteaCommits = (owner, repo) => api.get(`/gitea/repos/${owner}/${repo}/commits`); +export const getGiteaWorkflowRuns = (owner, repo) => + api.get(`/gitea/repos/${owner}/${repo}/actions/runs`); // Docker export const getContainers = () => api.get('/docker/containers');