gplx/scripts/deploy.ps1

258 lines
11 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<#
.SYNOPSIS
Deployt GPLX MediaWiki auf den IONOS-Server.
.PARAMETER Mode
skin Cavendish-Skin synchronisieren (schnell)
pages Alle Wiki-Seiten aus scripts/templates/ auf Server pushen
db Lokalen DB-Dump erstellen und auf Server importieren
all Skin + Pages
initial Erstinstallation: gesamten MediaWiki-Core übertragen
.EXAMPLE
.\deploy.ps1 # Skin deployen
.\deploy.ps1 -Mode pages # Alle Wiki-Seiten pushen
.\deploy.ps1 -Mode db # DB synchronisieren
.\deploy.ps1 -Mode all # Skin + Pages
.\deploy.ps1 -Mode initial
#>
param(
[ValidateSet('skin', 'pages', 'db', 'all', 'initial')]
[string]$Mode = 'skin'
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
# ── Mapping: Dateiname in scripts/templates/ → Wiki-Seitentitel ──────────────
# Reihenfolge ist relevant: MediaWiki-Systemseiten zuerst, dann Templates,
# dann Inhaltsseiten.
$PAGE_MAP = [ordered]@{
'Sidebar.wiki' = 'MediaWiki:Sidebar'
'Common_js.wiki' = 'MediaWiki:Common.js'
'Editnotice_Advertisement.wiki' = 'MediaWiki:Editnotice-MediaWiki:Advertisement'
'Template_DocumentBox.wiki' = 'Template:DocumentBox'
'Template_ReferenceBox.wiki' = 'Template:ReferenceBox'
'Cat_Clinical.wiki' = 'Category:Clinical'
'Cat_EU_Regulation.wiki' = 'Category:EU Regulation'
'Cat_IVD.wiki' = 'Category:In Vitro Diagnostics'
'Cat_Labelling.wiki' = 'Category:Labelling'
'Cat_MedicalDevices.wiki' = 'Category:Medical Devices'
'Cat_PerformanceEvaluation.wiki' = 'Category:Performance Evaluation'
'Cat_PostMarket.wiki' = 'Category:Post-Market Surveillance'
'Cat_Traceability.wiki' = 'Category:Traceability'
'About_GxPlex.wiki' = 'About GxPlex'
'Contribute_to_GxPlex.wiki' = 'Contribute to GxPlex'
'Create_new_page.wiki' = 'Create new page'
'GxPlex_Search.wiki' = 'GxPlex Search'
'Help_Adding_a_topic.wiki' = 'Help:Adding a topic'
'Roadmap.wiki' = 'Development Roadmap'
'The_Project.wiki' = 'The Project'
'Themes_and_topics.wiki' = 'Themes and topics'
}
# ── .deploy.env laden ─────────────────────────────────────────────────────────
$envFile = Join-Path $PSScriptRoot '..' '.deploy.env'
if (-not (Test-Path $envFile)) {
Write-Error @"
.deploy.env nicht gefunden.
Kopiere .deploy.example.env zu .deploy.env und trage deine Zugangsdaten ein.
"@
exit 1
}
Get-Content $envFile | ForEach-Object {
if ($_ -match '^\s*([^#][^=]+)=(.*)$') {
[System.Environment]::SetEnvironmentVariable($Matches[1].Trim(), $Matches[2].Trim(), 'Process')
}
}
# Pflichtfelder prüfen
foreach ($var in @('DEPLOY_HOST', 'DEPLOY_USER', 'DEPLOY_MW_PATH', 'DEPLOY_PROJECT_PATH')) {
if (-not [System.Environment]::GetEnvironmentVariable($var, 'Process')) {
Write-Error "$var fehlt in .deploy.env."
exit 1
}
}
$deployHost = $env:DEPLOY_HOST
$deployUser = $env:DEPLOY_USER
$mwPath = $env:DEPLOY_MW_PATH
$projectPath = $env:DEPLOY_PROJECT_PATH
$serverPhp = if ($env:DEPLOY_PHP) { $env:DEPLOY_PHP } else { 'php' }
$mwUser = if ($env:DEPLOY_MW_USER) { $env:DEPLOY_MW_USER } else { 'Gxplex admin' }
$target = "${deployUser}@${deployHost}"
$repoRoot = Split-Path $PSScriptRoot
# ── Hilfsfunktionen ───────────────────────────────────────────────────────────
$hasWsl = $null -ne (Get-Command 'wsl' -ErrorAction SilentlyContinue)
function ConvertTo-WslPath([string]$winPath) {
$abs = [System.IO.Path]::GetFullPath($winPath)
$drive = $abs.Substring(0, 1).ToLower()
$rest = $abs.Substring(2).Replace('\', '/')
return "/mnt/$drive$rest"
}
function Sync-Dir([string]$localDir, [string]$remoteDir, [bool]$delete = $false) {
Write-Host " $localDir${target}:${remoteDir}" -ForegroundColor DarkGray
if ($hasWsl) {
$wslSrc = (ConvertTo-WslPath $localDir) + '/'
$rsyncArgs = @('-az', '--progress')
if ($delete) { $rsyncArgs += '--delete' }
$rsyncArgs += @($wslSrc, "${target}:${remoteDir}/")
wsl rsync @rsyncArgs
} else {
Write-Warning "WSL nicht gefunden nutze scp."
ssh $target "mkdir -p '$remoteDir'"
scp -r "${localDir}\*" "${target}:${remoteDir}/"
}
if ($LASTEXITCODE -ne 0) { Write-Error "Übertragung fehlgeschlagen (Exit $LASTEXITCODE)."; exit $LASTEXITCODE }
}
function Push-WikiPage([string]$remoteFile, [string]$title) {
# Titel für einfache Shell-Quoting escapen: einfache Anführungszeichen verdoppeln
$safeTitle = $title -replace "'", "'\"'\"'"
$cmd = "cat '$remoteFile' | $serverPhp $mwPath/maintenance/run.php edit --user '$mwUser' --summary 'Deploy' '$safeTitle' 2>&1"
$out = ssh $target $cmd
return $LASTEXITCODE -eq 0
}
# ── Deploy-Modi ───────────────────────────────────────────────────────────────
switch ($Mode) {
'skin' {
Write-Host "Deploye Cavendish-Skin..." -ForegroundColor Cyan
Sync-Dir "$repoRoot\mediawiki\skins\Cavendish" "$mwPath/skins/Cavendish" -delete $true
Write-Host "Fertig." -ForegroundColor Green
}
'pages' {
Write-Host "Deploye Wiki-Seiten ($($PAGE_MAP.Count) Seiten)..." -ForegroundColor Cyan
# 1. Template-Dateien auf Server synchronisieren
Write-Host "`n[1/2] Dateien übertragen..." -ForegroundColor DarkGray
Sync-Dir "$repoRoot\scripts\templates" "$projectPath/scripts/templates"
# 2. Jede Seite per Maintenance-Script einspielen
Write-Host "`n[2/2] Seiten pushen..." -ForegroundColor DarkGray
$ok = 0; $fail = 0; $skip = 0
foreach ($entry in $PAGE_MAP.GetEnumerator()) {
$localFile = Join-Path "$repoRoot\scripts\templates" $entry.Key
$remoteFile = "$projectPath/scripts/templates/$($entry.Key)"
$title = $entry.Value
if (-not (Test-Path $localFile)) {
Write-Host " SKIP $($entry.Key) (Datei nicht gefunden)" -ForegroundColor DarkYellow
$skip++
continue
}
Write-Host -NoNewline " $title ... "
if (Push-WikiPage $remoteFile $title) {
Write-Host "OK" -ForegroundColor Green
$ok++
} else {
Write-Host "FEHLER" -ForegroundColor Red
$fail++
}
}
Write-Host ""
$color = if ($fail -eq 0) { 'Green' } else { 'Yellow' }
Write-Host "Ergebnis: $ok OK | $fail Fehler | $skip übersprungen" -ForegroundColor $color
}
'db' {
Write-Host "Synchronisiere Datenbank lokal Server..." -ForegroundColor Cyan
# Konfiguration aus .deploy.env
$localDbName = if ($env:LOCAL_DB_NAME) { $env:LOCAL_DB_NAME } else { 'gflex_test' }
$localDump = if ($env:LOCAL_MYSQLDUMP) { $env:LOCAL_MYSQLDUMP } else { 'D:\xampp\mysql\bin\mysqldump.exe' }
$serverDbName = if ($env:DEPLOY_DB_NAME) { $env:DEPLOY_DB_NAME } else { 'gplx' }
$serverDbUser = if ($env:DEPLOY_DB_USER) { $env:DEPLOY_DB_USER } else { 'gplx' }
$serverDbPass = $env:DEPLOY_DB_PASS
if (-not $serverDbPass) {
Write-Error "DEPLOY_DB_PASS fehlt in .deploy.env."
exit 1
}
$dumpFile = Join-Path $env:TEMP "gplx_deploy_$(Get-Date -Format 'yyyyMMdd_HHmmss').sql"
# 1. Lokalen Dump erstellen
Write-Host "`n[1/3] Erstelle lokalen DB-Dump ($localDbName)..." -ForegroundColor DarkGray
& $localDump -u root $localDbName | Set-Content $dumpFile -Encoding UTF8
if ($LASTEXITCODE -ne 0) { Write-Error "Dump fehlgeschlagen."; exit 1 }
$sizeMb = [math]::Round((Get-Item $dumpFile).Length / 1MB, 1)
Write-Host " Dump erstellt: $dumpFile ($sizeMb MB)"
# 2. Dump auf Server übertragen
Write-Host "`n[2/3] Übertrage Dump auf Server..." -ForegroundColor DarkGray
scp $dumpFile "${target}:/tmp/gplx_deploy.sql"
if ($LASTEXITCODE -ne 0) { Write-Error "SCP fehlgeschlagen."; exit 1 }
# 3. Auf Server importieren (DB droppen + neu anlegen)
Write-Host "`n[3/3] Importiere auf Server (DB wird überschrieben)..." -ForegroundColor DarkGray
$importCmd = @"
mysql -u root <<'SQL'
DROP DATABASE IF EXISTS $serverDbName;
CREATE DATABASE $serverDbName CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON $serverDbName.* TO '${serverDbUser}'@'localhost';
FLUSH PRIVILEGES;
SQL
mysql -u$serverDbUser -p$serverDbPass $serverDbName < /tmp/gplx_deploy.sql
cd $mwPath && $serverPhp maintenance/run.php update --quick
rm /tmp/gplx_deploy.sql
"@
ssh $target $importCmd
if ($LASTEXITCODE -ne 0) { Write-Error "Import fehlgeschlagen."; exit 1 }
# Lokale Dump-Datei aufräumen
Remove-Item $dumpFile -Force
Write-Host "`nFertig. Datenbank wurde auf dem Server überschrieben." -ForegroundColor Green
Write-Host "Hinweis: LocalSettings.php auf dem Server muss ggf. angepasst werden." -ForegroundColor DarkYellow
}
'all' {
Write-Host "Deploye Skin + Wiki-Seiten..." -ForegroundColor Cyan
& $PSCommandPath -Mode skin
& $PSCommandPath -Mode pages
}
'initial' {
Write-Host "Erstinstallation übertrage MediaWiki-Core..." -ForegroundColor Yellow
Write-Host "Das kann einige Minuten dauern." -ForegroundColor DarkGray
$excludes = @(
'--exclude=.git',
'--exclude=vendor/',
'--exclude=images/',
'--exclude=cache/',
'--exclude=LocalSettings.php'
)
if ($hasWsl) {
$wslSrc = (ConvertTo-WslPath "$repoRoot\mediawiki") + '/'
$rsyncArgs = @('-az', '--progress') + $excludes + @($wslSrc, "${target}:${mwPath}/")
wsl rsync @rsyncArgs
} else {
Write-Error "WSL ist für die Erstinstallation erforderlich (große Datenmenge). Bitte WSL installieren."
exit 1
}
if ($LASTEXITCODE -ne 0) { Write-Error "Übertragung fehlgeschlagen."; exit 1 }
Write-Host ""
Write-Host "Erstinstallation abgeschlossen." -ForegroundColor Green
Write-Host ""
Write-Host "Nächste Schritte auf dem Server:" -ForegroundColor Yellow
Write-Host " 1. LocalSettings.php hochladen: scp mediawiki/LocalSettings.php ${target}:${mwPath}/"
Write-Host " 2. Composer: ssh $target 'cd $mwPath && composer install --no-dev'"
Write-Host " 3. DB-Setup: php maintenance/run.php install ... (siehe Runbook)"
Write-Host " 4. SMW-Setup: php extensions/SemanticMediaWiki/maintenance/setupStore.php --nochecks"
Write-Host " 5. Seiten pushen: .\deploy.ps1 -Mode pages"
}
}