<# .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" } }