#Requires -Version 5.1 <# .SYNOPSIS ClawdDotNet Deployment-Paket erstellen. Baut Release, packt alles Noetige in ein ZIP das per AnyDesk auf den Server kopiert wird. .DESCRIPTION Zwei Modi: -Full Komplettes Deployment (alle Dateien, ~300 MB) — fuer Erstinstallation oder Dependency-Updates -Quick Nur ClawdDotNet-eigene Binaries (~2 MB) — fuer normale Code-Aenderungen (DEFAULT) .EXAMPLE .\Deploy-Build.ps1 # Quick-Deploy (nur eigene DLLs) .\Deploy-Build.ps1 -Full # Alles inkl. Dependencies .\Deploy-Build.ps1 -SkipBuild # ZIP ohne vorher zu bauen (wenn Build schon aktuell) #> param( [switch]$Full, [switch]$SkipBuild, [switch]$IncludeAgentConfigs ) $ErrorActionPreference = 'Stop' # ─── Pfade ─── $projectRoot = $PSScriptRoot $buildOutput = Join-Path $projectRoot "bin\Release\net10.0-windows" $deployDir = Join-Path $projectRoot "deploy" $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" $mode = if ($Full) { "full" } else { "quick" } $zipName = "ClawdDotNet_${mode}_${timestamp}.zip" $zipPath = Join-Path $deployDir $zipName # ─── 1. Build ─── if (-not $SkipBuild) { Write-Host "`n=== Building Release ===" -ForegroundColor Cyan Push-Location $projectRoot dotnet build -c Release --no-restore if ($LASTEXITCODE -ne 0) { Write-Host "BUILD FAILED!" -ForegroundColor Red Pop-Location exit 1 } Pop-Location Write-Host "Build OK" -ForegroundColor Green } else { Write-Host "`n=== Build uebersprungen (SkipBuild) ===" -ForegroundColor Yellow } # ─── 2. Staging-Ordner vorbereiten ─── $stagingDir = Join-Path $deployDir "staging_$timestamp" if (Test-Path $stagingDir) { Remove-Item $stagingDir -Recurse -Force } New-Item -ItemType Directory -Path $stagingDir -Force | Out-Null if ($Full) { # ── Full Deploy: Alles ausser Instances/, Logs/, PDBs ── Write-Host "`n=== Full Deploy: Kopiere alle Dateien ===" -ForegroundColor Cyan # Dateien im Root Get-ChildItem $buildOutput -File | Where-Object { $_.Extension -ne '.pdb' } | ForEach-Object { Copy-Item $_.FullName $stagingDir } # Unterordner (ohne Instances und Logs) Get-ChildItem $buildOutput -Directory | Where-Object { $_.Name -notin @('Instances', 'Logs') } | ForEach-Object { Copy-Item $_.FullName (Join-Path $stagingDir $_.Name) -Recurse } } else { # ── Quick Deploy: Nur ClawdDotNet-eigene Dateien ── Write-Host "`n=== Quick Deploy: Nur eigene Binaries ===" -ForegroundColor Cyan Get-ChildItem $buildOutput -File | Where-Object { $_.Name -match '^ClawdDotNet\.' -and $_.Extension -ne '.pdb' } | ForEach-Object { Copy-Item $_.FullName $stagingDir } } # ─── 2b. Optional: Agent-Configs mitkopieren ─── if ($IncludeAgentConfigs) { Write-Host "=== Agent-Configs werden mitgepackt ===" -ForegroundColor Yellow $instancesSource = Join-Path $buildOutput "Instances" if (Test-Path $instancesSource) { $instancesDest = Join-Path $stagingDir "Instances" # Agent-Configs + Shared-Website-Templates kopieren Get-ChildItem $instancesSource -Recurse -File -Include "Identity.md","Soul.md","AgentSettings.json","AgentList.json","InstanceSettings.json","style.css","script.js" | ForEach-Object { $relPath = $_.FullName.Substring($instancesSource.Length) $destPath = Join-Path $instancesDest $relPath $destDir = Split-Path $destPath -Parent if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir -Force | Out-Null } Copy-Item $_.FullName $destPath } } } # ─── 3. Install-Skript beilegen ─── $installScript = @' #Requires -Version 5.1 <# .SYNOPSIS ClawdDotNet Update auf dem Server installieren. Stoppt die laufende Instanz, kopiert neue Dateien, startet neu. .EXAMPLE .\Deploy-Install.ps1 # Standard: ClawdDotNet.exe automatisch suchen .\Deploy-Install.ps1 -TargetDir "D:\ClawdDotNet" # Zielordner explizit angeben #> param( [string]$TargetDir ) $ErrorActionPreference = 'Stop' # Zielordner bestimmen if (-not $TargetDir) { $candidates = @( "C:\ClawdDotNet", "D:\ClawdDotNet", "$env:ProgramFiles\ClawdDotNet", "$env:LOCALAPPDATA\ClawdDotNet" ) foreach ($c in $candidates) { if (Test-Path (Join-Path $c "ClawdDotNet.exe")) { $TargetDir = $c break } } if (-not $TargetDir) { Write-Host "ClawdDotNet-Installation nicht gefunden!" -ForegroundColor Red Write-Host 'Bitte mit -TargetDir angeben, z.B.:' Write-Host ' .\Deploy-Install.ps1 -TargetDir "D:\ClawdDotNet"' exit 1 } } Write-Host "" Write-Host "=== ClawdDotNet Update ===" -ForegroundColor Cyan Write-Host "Ziel: $TargetDir" # 1. Prozess stoppen $proc = Get-Process -Name "ClawdDotNet" -ErrorAction SilentlyContinue if ($proc) { Write-Host "Stoppe ClawdDotNet..." -ForegroundColor Yellow $proc | Stop-Process -Force -Confirm:$false Start-Sleep -Seconds 2 $timeout = 15 while ((Get-Process -Name "ClawdDotNet" -ErrorAction SilentlyContinue) -and $timeout -gt 0) { Start-Sleep -Seconds 1 $timeout-- } if ($timeout -eq 0) { Write-Host "WARNUNG: Prozess konnte nicht gestoppt werden!" -ForegroundColor Red exit 1 } Write-Host "Gestoppt." -ForegroundColor Green } else { Write-Host "ClawdDotNet laeuft nicht - kein Stopp noetig." -ForegroundColor Gray } # 2. Backup erstellen (nur eigene DLLs) $backupDir = Join-Path $TargetDir ("_backup_" + (Get-Date -Format "yyyyMMdd_HHmmss")) New-Item -ItemType Directory -Path $backupDir -Force | Out-Null Get-ChildItem $TargetDir -File | Where-Object { $_.Name -match '^ClawdDotNet\.' } | ForEach-Object { Copy-Item $_.FullName $backupDir } Write-Host "Backup erstellt: $backupDir" -ForegroundColor Gray # 3. Neue Dateien kopieren $sourceDir = $PSScriptRoot $sourceFull = (Resolve-Path $sourceDir).Path.TrimEnd('\') $targetFull = (Resolve-Path $TargetDir).Path.TrimEnd('\') if ($sourceFull -eq $targetFull) { # ZIP wurde direkt im Zielordner entpackt - Dateien sind schon da Write-Host "ZIP wurde direkt im Zielordner entpackt - Dateien bereits vorhanden." -ForegroundColor Yellow $fileCount = (Get-ChildItem $sourceDir -File | Where-Object { $_.Name -notin @('Deploy-Install.ps1') }).Count } else { $fileCount = 0 Get-ChildItem $sourceDir -File | Where-Object { $_.Name -notin @('Deploy-Install.ps1') } | ForEach-Object { Copy-Item $_.FullName $TargetDir -Force $fileCount++ } # Unterordner kopieren (falls vorhanden, z.B. bei Full-Deploy) Get-ChildItem $sourceDir -Directory | Where-Object { $_.Name -notmatch '^_backup' } | ForEach-Object { $destSubDir = Join-Path $TargetDir $_.Name Copy-Item $_.FullName $destSubDir -Recurse -Force $fileCount += (Get-ChildItem $_.FullName -Recurse -File).Count } } Write-Host "$fileCount Dateien aktualisiert." -ForegroundColor Green # 4. Neu starten Write-Host "Starte ClawdDotNet..." -ForegroundColor Cyan $exePath = Join-Path $TargetDir "ClawdDotNet.exe" Start-Process $exePath -WorkingDirectory $TargetDir Start-Sleep -Seconds 3 if (Get-Process -Name "ClawdDotNet" -ErrorAction SilentlyContinue) { Write-Host "" Write-Host "=== Update erfolgreich! ClawdDotNet laeuft. ===" -ForegroundColor Green } else { Write-Host "" Write-Host "=== WARNUNG: Prozess nicht gefunden. Bitte manuell pruefen. ===" -ForegroundColor Yellow } # 5. Alte Backups aufraeumen (behalte die letzten 5) $oldBackups = Get-ChildItem $TargetDir -Directory | Where-Object { $_.Name -match '^_backup_' } | Sort-Object Name -Descending | Select-Object -Skip 5 foreach ($old in $oldBackups) { Remove-Item $old.FullName -Recurse -Force Write-Host "Altes Backup entfernt: $($old.Name)" -ForegroundColor Gray } Write-Host "" Write-Host "Fertig." -ForegroundColor Green '@ $installScriptPath = Join-Path $stagingDir "Deploy-Install.ps1" # UTF-8 OHNE BOM - wichtig fuer PowerShell 5.1 auf Windows Server $utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($installScriptPath, $installScript, $utf8NoBom) # ─── 4. ZIP erstellen ─── if (-not (Test-Path $deployDir)) { New-Item -ItemType Directory -Path $deployDir -Force | Out-Null } Write-Host "`n=== Erstelle ZIP: $zipName ===" -ForegroundColor Cyan if (Test-Path $zipPath) { Remove-Item $zipPath -Force } Compress-Archive -Path "$stagingDir\*" -DestinationPath $zipPath -CompressionLevel Optimal # Staging aufraeumen Remove-Item $stagingDir -Recurse -Force # ─── 5. Zusammenfassung ─── $zipSize = (Get-Item $zipPath).Length Write-Host "`n========================================" -ForegroundColor Green Write-Host " Deployment-Paket erstellt!" -ForegroundColor Green Write-Host "========================================" -ForegroundColor Green Write-Host "" Write-Host " Modus: $( if ($Full) { 'FULL (alle Dateien)' } else { 'QUICK (nur eigene DLLs)' } )" Write-Host " Datei: $zipPath" Write-Host " Groesse: $([math]::Round($zipSize/1KB, 0)) KB ($([math]::Round($zipSize/1MB, 1)) MB)" Write-Host "" Write-Host " Naechste Schritte:" -ForegroundColor Yellow Write-Host " 1. ZIP per AnyDesk auf den Server kopieren" Write-Host " 2. Auf dem Server entpacken" Write-Host " 3. Deploy-Install.ps1 als Admin ausfuehren" Write-Host "" # ZIP-Ordner im Explorer oeffnen Start-Process "explorer.exe" "/select,`"$zipPath`""