Update
This commit is contained in:
+47
-1
@@ -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}`);
|
||||
});
|
||||
|
||||
+24
-1
@@ -68,11 +68,33 @@ 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 <p className="text-gray-400">Lade Stacks...</p>;
|
||||
if (error) return <p className="text-red-400">{error}</p>;
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 p-6">
|
||||
<div className="p-6">
|
||||
<div className="flex justify-end mb-4">
|
||||
<button
|
||||
onClick={handleRedeployAll}
|
||||
className="px-5 py-2 rounded-lg font-medium transition bg-purple-500 hover:bg-purple-600"
|
||||
>
|
||||
Redeploy All
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{stacks.map(stack => {
|
||||
const isRedeploying = stack.redeploying;
|
||||
|
||||
@@ -108,5 +130,6 @@ export default function Stacks() {
|
||||
})}
|
||||
{stacks.length === 0 && <p className="text-gray-400">Keine Stacks gefunden.</p>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+33
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user