param( [Parameter(Mandatory = $false)] [string]$Version, [Parameter(Mandatory = $false)] [string[]]$Brands = @("agravity"), [Parameter(Mandatory = $false)] [string]$ForgejoUser, [Parameter(Mandatory = $false)] [string]$ForgejoPW, [switch]$ClearCredentials, [string]$ForgejoUrl = "https://git.him-tools.de", [string]$Repo = "HIM-public/webdrop-bridge" ) $ErrorActionPreference = "Stop" $projectRoot = Resolve-Path (Join-Path $PSScriptRoot "..\..") $pythonExe = Join-Path $projectRoot ".venv\Scripts\python.exe" if (-not (Test-Path $pythonExe)) { $pythonExe = "python" } $brandHelper = Join-Path $projectRoot "build\scripts\brand_config.py" $manifestOutput = Join-Path $projectRoot "build\dist\release-manifest.json" function Get-CurrentVersion { return (& $pythonExe -c "from pathlib import Path; import sys; sys.path.insert(0, str(Path(r'$projectRoot/build/scripts').resolve())); from version_utils import get_current_version; print(get_current_version())").Trim() } if ($ClearCredentials) { Remove-Item env:FORGEJO_USER -ErrorAction SilentlyContinue Remove-Item env:FORGEJO_PASS -ErrorAction SilentlyContinue Write-Host "[OK] Credentials cleared from this session" -ForegroundColor Green exit 0 } if (-not $ForgejoUser) { $ForgejoUser = $env:FORGEJO_USER } if (-not $ForgejoPW) { $ForgejoPW = $env:FORGEJO_PASS } if (-not $ForgejoUser -or -not $ForgejoPW) { Write-Host "Forgejo credentials not found. Enter your credentials:" -ForegroundColor Yellow if (-not $ForgejoUser) { $ForgejoUser = Read-Host "Username" } if (-not $ForgejoPW) { $securePass = Read-Host "Password" -AsSecureString $ForgejoPW = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($securePass)) } $env:FORGEJO_USER = $ForgejoUser $env:FORGEJO_PASS = $ForgejoPW } if (-not $Version) { $Version = Get-CurrentVersion } $artifactPaths = New-Object System.Collections.Generic.List[string] foreach ($brand in $Brands) { $brandJson = & $pythonExe $brandHelper show --brand $brand | ConvertFrom-Json $msiPath = Join-Path $projectRoot "build\dist\windows\$($brandJson.brand_id)\$($brandJson.asset_prefix)-$Version-win-x64.msi" $checksumPath = "$msiPath.sha256" if (Test-Path $msiPath) { $artifactPaths.Add($msiPath) if (Test-Path $checksumPath) { $artifactPaths.Add($checksumPath) } $msiSize = (Get-Item $msiPath).Length / 1MB Write-Host "Windows artifact: $([System.IO.Path]::GetFileName($msiPath)) ($([math]::Round($msiSize, 2)) MB)" } } & $pythonExe $brandHelper release-manifest --version $Version --output $manifestOutput --brands $Brands | Out-Null if (Test-Path $manifestOutput) { $artifactPaths.Add($manifestOutput) } if ($artifactPaths.Count -eq 0) { Write-Host "ERROR: No Windows artifacts found for the requested brands" -ForegroundColor Red exit 1 } $auth = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("${ForgejoUser}:${ForgejoPW}")) $headers = @{ "Authorization" = "Basic $auth" "Content-Type" = "application/json" } $releaseLookupUrl = "$ForgejoUrl/api/v1/repos/$Repo/releases/tags/v$Version" $releaseUrl = "$ForgejoUrl/api/v1/repos/$Repo/releases" $releaseData = @{ tag_name = "v$Version" name = "WebDropBridge v$Version" body = "Shared branded release for WebDrop Bridge v$Version" draft = $false prerelease = $false } | ConvertTo-Json try { $lookupResponse = Invoke-WebRequest -Uri $releaseLookupUrl -Method GET -Headers $headers -TimeoutSec 30 -UseBasicParsing -ErrorAction Stop $releaseInfo = $lookupResponse.Content | ConvertFrom-Json $releaseId = $releaseInfo.id Write-Host "[OK] Using existing release (ID: $releaseId)" -ForegroundColor Green } catch { $response = Invoke-WebRequest -Uri $releaseUrl -Method POST -Headers $headers -Body $releaseData -TimeoutSec 30 -UseBasicParsing -ErrorAction Stop $releaseInfo = $response.Content | ConvertFrom-Json $releaseId = $releaseInfo.id Write-Host "[OK] Release created (ID: $releaseId)" -ForegroundColor Green } $curlAuth = "$ForgejoUser`:$ForgejoPW" $uploadUrl = "$ForgejoUrl/api/v1/repos/$Repo/releases/$releaseId/assets" foreach ($artifact in $artifactPaths) { $response = curl.exe -s -X POST -u $curlAuth -F "attachment=@$artifact" $uploadUrl if ($response -like "*error*" -or $response -like "*404*") { Write-Host "WARNING: Could not upload $artifact : $response" -ForegroundColor Yellow } else { Write-Host "[OK] Uploaded $([System.IO.Path]::GetFileName($artifact))" -ForegroundColor Green } } Write-Host "`n[OK] Release complete!" -ForegroundColor Green Write-Host "View at: $ForgejoUrl/$Repo/releases/tag/v$Version" -ForegroundColor Cyan