From 3489ea55a21063af42d0f917538e9a2da9ff3077 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 26 Sep 2025 09:28:34 +0000 Subject: [PATCH] Update --- backend/index.js | 48 ++++++++++++++++++++++- frontend/src/Stacks.jsx | 87 ++++++++++++++++++++++++++--------------- scripts/stash.sh | 34 +++++++++++++++- 3 files changed, 135 insertions(+), 34 deletions(-) diff --git a/backend/index.js b/backend/index.js index 398d5a3..2843036 100644 --- a/backend/index.js +++ b/backend/index.js @@ -14,7 +14,6 @@ const __dirname = path.dirname(__filename); const app = express(); app.use(express.json()); - app.use(express.static(path.join(__dirname, 'public'))); app.get('*', (req, res, next) => { @@ -49,6 +48,7 @@ const broadcastRedeployStatus = (stackId, status) => { // --- API Endpoints --- +// Stacks abrufen app.get('/api/stacks', async (req, res) => { console.log("ℹ️ [API] GET /api/stacks: Abruf gestartet"); try { @@ -89,6 +89,7 @@ app.get('/api/stacks', async (req, res) => { } }); +// Einzel-Redeploy app.put('/api/stacks/:id/redeploy', async (req, res) => { const { id } = req.params; console.log(`🔄 PUT /api/stacks/${id}/redeploy: Redeploy gestartet`); @@ -142,6 +143,51 @@ app.put('/api/stacks/:id/redeploy', async (req, res) => { } }); +// Redeploy ALL +app.put('/api/stacks/redeploy-all', async (req, res) => { + console.log(`🚀 PUT /api/stacks/redeploy-all: Redeploy ALL gestartet`); + + try { + const stacksRes = await axiosInstance.get('/api/stacks'); + const filteredStacks = stacksRes.data.filter(stack => stack.EndpointId === ENDPOINT_ID); + + console.log("📦 Redeploy ALL für folgende Stacks:"); + filteredStacks.forEach(s => console.log(` - ${s.Name}`)); + + filteredStacks.forEach(async (stack) => { + try { + broadcastRedeployStatus(stack.Id, true); + + if (stack.Type === 1) { + console.log(`🔄 [Redeploy] Git Stack "${stack.Name}" (${stack.Id})`); + await axiosInstance.put(`/api/stacks/${stack.Id}/git/redeploy?endpointId=${stack.EndpointId}`); + } else if (stack.Type === 2) { + console.log(`🔄 [Redeploy] Compose Stack "${stack.Name}" (${stack.Id})`); + const fileRes = await axiosInstance.get(`/api/stacks/${stack.Id}/file`); + const stackFileContent = fileRes.data?.StackFileContent; + if (stackFileContent) { + await axiosInstance.put(`/api/stacks/${stack.Id}`, + { StackFileContent: stackFileContent, Prune: false, PullImage: true }, + { params: { endpointId: stack.EndpointId } } + ); + } + } + + broadcastRedeployStatus(stack.Id, false); + console.log(`✅ Redeploy abgeschlossen: ${stack.Name}`); + } catch (err) { + broadcastRedeployStatus(stack.Id, false); + console.error(`❌ Fehler beim Redeploy von Stack ${stack.Name}:`, err.message); + } + }); + + res.json({ success: true, message: 'Redeploy ALL gestartet' }); + } catch (err) { + console.error(`❌ Fehler beim Redeploy ALL:`, err.message); + res.status(500).json({ error: err.message }); + } +}); + server.listen(PORT, '0.0.0.0', () => { console.log(`🚀 Backend läuft auf Port ${PORT}`); }); diff --git a/frontend/src/Stacks.jsx b/frontend/src/Stacks.jsx index cc6c353..00b9ac5 100644 --- a/frontend/src/Stacks.jsx +++ b/frontend/src/Stacks.jsx @@ -68,45 +68,68 @@ export default function Stacks() { } }; + const handleRedeployAll = async () => { + setStacks(prev => prev.map(stack => ({ ...stack, redeploying: true }))); + + try { + await axios.put("/api/stacks/redeploy-all"); + // Statusupdates kommen über Socket.IO + } catch (err) { + console.error("❌ Fehler beim Redeploy ALL:", err); + setStacks(prev => prev.map(stack => ({ ...stack, redeploying: false }))); + } + }; + if (loading) return

Lade Stacks...

; if (error) return

{error}

; return ( -
- {stacks.map(stack => { - const isRedeploying = stack.redeploying; +
+
+ +
- return ( -
-
-
-
-

{stack.Name}

-

ID: {stack.Id}

-
-
+
+ {stacks.map(stack => { + const isRedeploying = stack.redeploying; - -
- ); - })} - {stacks.length === 0 &&

Keine Stacks gefunden.

} +
+
+
+

{stack.Name}

+

ID: {stack.Id}

+
+
+ + +
+ ); + })} + {stacks.length === 0 &&

Keine Stacks gefunden.

} +
); } diff --git a/scripts/stash.sh b/scripts/stash.sh index 0235617..e4645d1 100755 --- a/scripts/stash.sh +++ b/scripts/stash.sh @@ -10,8 +10,9 @@ CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) echo "Aktueller Branch: $CURRENT_BRANCH" echo "Was möchtest du tun?" echo "1) Neuen Stash anlegen" -echo "2) Vorhandenen Stash laden" +echo "2) Vorhandenen Stash laden (apply)" echo "3) Vorhandenen Stash löschen" +echo "4) Stash anwenden und löschen (pop)" read -p "Auswahl: " action case $action in @@ -99,6 +100,37 @@ case $action in git stash drop "$SELECTED_STASH" ;; + 4) + # ========== Stash anwenden und löschen (pop) ========== + echo "Liste aller Stashes für Branch '$CURRENT_BRANCH':" + STASHES=$(git stash list | grep "$CURRENT_BRANCH") + + if [[ -z "$STASHES" ]]; then + echo "Keine Stashes für diesen Branch vorhanden." + exit 0 + fi + + i=1 + declare -A STASH_MAP + while IFS= read -r line; do + STASH_REF=$(echo "$line" | awk -F: '{print $1}') + STASH_MSG=$(echo "$line" | cut -d':' -f3- | sed 's/^ //') + echo "$i) $STASH_REF -> $STASH_MSG" + STASH_MAP[$i]=$STASH_REF + ((i++)) + done <<< "$STASHES" + + read -p "Wähle einen Stash zum Anwenden & Löschen (Nummer): " choice + if [[ -z "${STASH_MAP[$choice]}" ]]; then + echo "Ungültige Auswahl!" + exit 1 + fi + + SELECTED_STASH=${STASH_MAP[$choice]} + echo "Wende Stash an und lösche ihn: $SELECTED_STASH" + git stash pop "$SELECTED_STASH" + ;; + *) echo "Ungültige Auswahl!" exit 1