Release v2.0.3
This commit is contained in:
parent
2f022bf085
commit
19fdd7d91e
@ -8,7 +8,7 @@
|
||||
# RELEASE VERSION
|
||||
# =====================================================
|
||||
# Tag fra Gitea (f.eks. v1.0.0, v1.2.3)
|
||||
RELEASE_VERSION=v2.0.2
|
||||
RELEASE_VERSION=v2.0.3
|
||||
|
||||
# =====================================================
|
||||
# GITEA AUTHENTICATION
|
||||
|
||||
8
RELEASE_NOTES_v2.0.3.md
Normal file
8
RELEASE_NOTES_v2.0.3.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Release Notes v2.0.3
|
||||
|
||||
## Changes
|
||||
- Allow executing SQL migration files directly from `/settings/migrations`, including user feedback on success/failure.
|
||||
- Pipe the migration SQL files into the Postgres container so the execution works across Docker and Podman.
|
||||
|
||||
---
|
||||
Release Date: 28. januar 2026
|
||||
@ -7,6 +7,8 @@ from pathlib import Path
|
||||
from fastapi import APIRouter, Request, HTTPException
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from pydantic import BaseModel
|
||||
import shlex
|
||||
import subprocess
|
||||
|
||||
from app.core.config import settings
|
||||
@ -49,11 +51,15 @@ async def migrations_page(request: Request):
|
||||
})
|
||||
|
||||
|
||||
class MigrationExecution(BaseModel):
|
||||
file_name: str
|
||||
|
||||
|
||||
@router.post("/settings/migrations/execute", tags=["Frontend"])
|
||||
def execute_migration(file_name: str):
|
||||
def execute_migration(payload: MigrationExecution):
|
||||
"""Execute a migration SQL file"""
|
||||
migrations_dir = Path(__file__).resolve().parents[3] / "migrations"
|
||||
migration_file = migrations_dir / file_name
|
||||
migration_file = migrations_dir / payload.file_name
|
||||
|
||||
if not migration_file.exists():
|
||||
raise HTTPException(status_code=404, detail="Migration file not found")
|
||||
@ -62,7 +68,11 @@ def execute_migration(file_name: str):
|
||||
container_runtime = "podman" if settings.CONTAINER_RUNTIME == "podman" else "docker"
|
||||
|
||||
# Execute the migration file
|
||||
command = f"{container_runtime} exec bmc-hub-postgres psql -U {settings.POSTGRES_USER} -d {settings.POSTGRES_DB} -f {migration_file}"
|
||||
command = (
|
||||
f"cat {shlex.quote(str(migration_file))} | "
|
||||
f"{container_runtime} exec -i bmc-hub-postgres "
|
||||
f"psql -U {settings.POSTGRES_USER} -d {settings.POSTGRES_DB}"
|
||||
)
|
||||
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
|
||||
@ -67,10 +67,13 @@
|
||||
</td>
|
||||
<td>{{ migration.size_kb }} KB</td>
|
||||
<td>{{ migration.modified }}</td>
|
||||
<td class="text-end">
|
||||
<td class="text-end d-flex gap-2 justify-content-end">
|
||||
<button class="btn btn-sm btn-outline-primary" onclick="showCommand('{{ migration.name }}')">
|
||||
<i class="bi bi-terminal me-1"></i>Vis kommando
|
||||
</button>
|
||||
<button class="btn btn-sm btn-success" onclick="runMigration('{{ migration.name }}', this)">
|
||||
<i class="bi bi-play-circle me-1"></i>Kør migration
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@ -103,6 +106,7 @@
|
||||
<i class="bi bi-clipboard-plus me-2"></i>Kopiér alt
|
||||
</button>
|
||||
</div>
|
||||
<div id="migrationFeedback" class="alert d-none mt-3" role="alert"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -148,5 +152,34 @@
|
||||
if (!currentAltCommand) return;
|
||||
await navigator.clipboard.writeText(currentAltCommand);
|
||||
}
|
||||
|
||||
async function runMigration(migrationName, button) {
|
||||
const feedback = document.getElementById('migrationFeedback');
|
||||
const url = '/settings/migrations/execute';
|
||||
|
||||
button.disabled = true;
|
||||
feedback.className = 'alert alert-info mt-3';
|
||||
feedback.textContent = 'Kører migration...';
|
||||
feedback.classList.remove('d-none');
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ file_name: migrationName })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (!response.ok) throw new Error(data.detail || data.message);
|
||||
|
||||
feedback.className = 'alert alert-success mt-3';
|
||||
feedback.innerHTML = `<strong>Migration kørt</strong><br><pre class="mb-0">${data.output}</pre>`;
|
||||
} catch (error) {
|
||||
feedback.className = 'alert alert-danger mt-3';
|
||||
feedback.innerHTML = `<strong>Fejl</strong><br>${error.message}`;
|
||||
} finally {
|
||||
button.disabled = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user