Launcher 0.3.2: Updates aus Gitea-Releases, Server-Karte entfernt

Neueste Mod/Launcher-Version und Neuigkeiten kommen von git.mbm.wtf (bso-release.json mit Signatur),
die Website ist nur noch Reserve (mit -dev zuerst). SPIELEN auf der Startseite startet ohne Server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-28 21:01:20 +01:00
co-authored by Claude Opus 5.5
parent 5fd162fecb
commit 9cd5f2b153
9 changed files with 155 additions and 56 deletions
+36 -30
View File
@@ -1,13 +1,15 @@
# Signiert ein Release und laedt es auf die BSO-Website (wie release.ps1 bei MSCO).
# .\release.ps1 -Product mod|launcher|server -Version 0.2.0 -File dist\BSO-Mod.zip [-Changelog "..."]
# Laeuft auch automatisch bei "dotnet publish -p:BsoRelease=true" (Launcher und Server, siehe .csproj).
# Signiert ein Release und veroeffentlicht es als Gitea-Release auf git.mbm.wtf (Launcher und Website holen es von dort).
# .\release.ps1 -Product mod|launcher -Version 0.5.0 -File dist\BSO-Mod.zip [-Changelog "..."]
# Laeuft auch automatisch bei "dotnet publish -p:BsoRelease=true" (Launcher) bzw. "build.ps1 -Release" (Mod).
# - Repo: mod -> MrMaho/BSO-Mod, launcher -> MrMaho/BSO-Launcher; Tag v<Version> (wird auf dem Standard-Branch angelegt).
# - Ohne -Changelog: der Abschnitt "## <Version>" aus CHANGELOG.md neben diesem Skript.
# - Ist -File ein Ordner (Server: publish\), wird er ohne .pdb-Dateien gezippt.
# Braucht: Release-Schluessel (BSO-Launcher\new-release-key.ps1), BSO_RELEASE_TOKEN (= RELEASE_TOKEN der Website),
# optional BSO_MASTER_URL (Standard https://bso.mbm.wtf). Beide auch als Windows-Benutzervariable.
# Signiert wird "BSO-RELEASE|produkt|version|sha256" - der Launcher prueft das mit dem eingebauten oeffentlichen Schluessel.
# - Dateien im Release: die Datei (Launcher als BSO-Launcher-Setup.exe) und bso-release.json mit Version, SHA-256 und
# Signatur. Signiert wird "BSO-RELEASE|produkt|version|sha256" - der Launcher prueft das mit dem eingebauten
# oeffentlichen Schluessel, egal woher die Datei kommt.
# Braucht: Release-Schluessel (BSO-Launcher\new-release-key.ps1) und BSO_GITEA_TOKEN (Gitea: Einstellungen -> Anwendungen
# -> Token mit "repository: Lesen und Schreiben"), auch als Windows-Benutzervariable. Optional BSO_GITEA_URL.
param(
[Parameter(Mandatory)][ValidateSet("mod", "launcher", "server")][string]$Product,
[Parameter(Mandatory)][ValidateSet("mod", "launcher")][string]$Product,
[Parameter(Mandatory)][string]$Version,
[Parameter(Mandatory)][string]$File,
[string]$Changelog = ""
@@ -22,12 +24,14 @@ function Setting([string]$name) {
if (-not $v) { $v = [Environment]::GetEnvironmentVariable($name, "User") }
return $v
}
$master = ((Setting "BSO_MASTER_URL"), "https://bso.mbm.wtf" | Where-Object { $_ } | Select-Object -First 1).TrimEnd('/')
$token = Setting "BSO_RELEASE_TOKEN"
if (-not $token) { Write-Host "BSO_RELEASE_TOKEN nicht gesetzt - nicht hochgeladen"; return }
$gitea = ((Setting "BSO_GITEA_URL"), "https://git.mbm.wtf" | Where-Object { $_ } | Select-Object -First 1).TrimEnd('/')
$token = Setting "BSO_GITEA_TOKEN"
if (-not $token) { Write-Host "BSO_GITEA_TOKEN nicht gesetzt - kein Release angelegt"; return }
$keyFile = Join-Path $env:APPDATA "BSO\release-key.dpapi"
if (-not (Test-Path $keyFile)) { throw "Kein Release-Schluessel ($keyFile) - erst new-release-key.ps1 im BSO-Launcher-Repo" }
$Version = $Version.Split('+')[0]
$repo = @{ mod = "BSO-Mod"; launcher = "BSO-Launcher" }[$Product]
$api = "$gitea/api/v1/repos/MrMaho/$repo"
# Changelog aus CHANGELOG.md: alles unter "## <Version>" bis zur naechsten "## "-Zeile
if (-not $Changelog) {
@@ -44,15 +48,8 @@ if (-not $Changelog) {
if ($Changelog) { Write-Host "Changelog aus CHANGELOG.md ($Version)" } else { Write-Host "Kein Changelog fuer $Version in CHANGELOG.md" }
}
# Ordner (dotnet publish) -> zip
$path = (Resolve-Path $File).Path
if (Test-Path $path -PathType Container) {
$zip = Join-Path $env:TEMP "BSO-$Product-$Version.zip"
Remove-Item $zip -ErrorAction SilentlyContinue
Compress-Archive -Path (Get-ChildItem $path -File | Where-Object Extension -ne ".pdb").FullName -DestinationPath $zip
$path = $zip
}
$fileName = if ($Product -eq "launcher") { "BSO-Launcher-Setup.exe" } else { Split-Path $path -Leaf }
$data = [IO.File]::ReadAllBytes($path)
$sha = ([System.Security.Cryptography.SHA256]::Create().ComputeHash($data) | ForEach-Object { $_.ToString("x2") }) -join ""
$private = [System.Security.Cryptography.ProtectedData]::Unprotect([IO.File]::ReadAllBytes($keyFile), $null,
@@ -62,18 +59,27 @@ $rsa.FromXmlString([Text.Encoding]::UTF8.GetString($private))
$message = [Text.Encoding]::UTF8.GetBytes("BSO-RELEASE|$Product|$Version|$sha")
$signature = [Convert]::ToBase64String($rsa.SignData($message, [System.Security.Cryptography.HashAlgorithmName]::SHA256,
[System.Security.Cryptography.RSASignaturePadding]::Pkcs1))
$manifest = [ordered]@{ product = $Product; version = $Version; sha256 = $sha; size = $data.Length; file = $fileName; signature = $signature } |
ConvertTo-Json -Compress
$http = New-Object System.Net.Http.HttpClient
$http.Timeout = [TimeSpan]::FromMinutes(10)
$http.DefaultRequestHeaders.Authorization = New-Object System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", $token)
$form = New-Object System.Net.Http.MultipartFormDataContent
foreach ($pair in @(@("product", $Product), @("version", $Version), @("changelog", $Changelog), @("signature", $signature))) {
$form.Add((New-Object System.Net.Http.StringContent($pair[1])), "`"$($pair[0])`"")
}
$content = New-Object System.Net.Http.ByteArrayContent(, $data)
$form.Add($content, "`"file`"", "`"$(Split-Path $path -Leaf)`"")
$res = $http.PostAsync("$master/api/releases/upload", $form).Result
$http.DefaultRequestHeaders.Authorization = New-Object System.Net.Http.Headers.AuthenticationHeaderValue("token", $token)
# Release anlegen (Tag v<Version>)
$json = @{ tag_name = "v$Version"; name = "$Product $Version"; body = $Changelog; draft = $false; prerelease = $false } | ConvertTo-Json -Compress
$res = $http.PostAsync("$api/releases", (New-Object System.Net.Http.StringContent($json, [Text.Encoding]::UTF8, "application/json"))).Result
$body = $res.Content.ReadAsStringAsync().Result
if ($res.StatusCode -eq [Net.HttpStatusCode]::Conflict) { Write-Host "$Product $Version gibt es schon auf $master - Version in der .csproj erhoehen"; return }
if (-not $res.IsSuccessStatusCode) { throw "Hochladen fehlgeschlagen ($([int]$res.StatusCode)): $body" }
Write-Host "$Product $Version hochgeladen nach $master (sha256 $sha)"
if ($res.StatusCode -eq [Net.HttpStatusCode]::Conflict) { Write-Host "$repo v$Version gibt es schon - Version erhoehen"; return }
if (-not $res.IsSuccessStatusCode) { throw "Release anlegen fehlgeschlagen ($([int]$res.StatusCode)): $body" }
$id = ($body | ConvertFrom-Json).id
function Upload([string]$name, [byte[]]$bytes) {
$form = New-Object System.Net.Http.MultipartFormDataContent
$form.Add((New-Object System.Net.Http.ByteArrayContent(, $bytes)), "`"attachment`"", "`"$name`"")
$r = $http.PostAsync("$api/releases/$id/assets?name=$([Uri]::EscapeDataString($name))", $form).Result
if (-not $r.IsSuccessStatusCode) { throw "Hochladen von $name fehlgeschlagen ($([int]$r.StatusCode)): $($r.Content.ReadAsStringAsync().Result)" }
}
Upload $fileName $data
Upload "bso-release.json" ([Text.Encoding]::UTF8.GetBytes($manifest))
Write-Host "$Product $Version veroeffentlicht: $gitea/MrMaho/$repo/releases/tag/v$Version (sha256 $sha)"