EuerChat 0.1.0: Tauri-Client mit Direktverbindung, ZNC, Livestream, Updater und Installer-Build
This commit is contained in:
commit
df88f8abaa
27 files changed
+13167
No files matched your search
@@ -0,0 +1,178 @@
|
||||
param(
|
||||
[string]$Version = "",
|
||||
[string]$Notes = "",
|
||||
[switch]$ValidateOnly
|
||||
)
|
||||
|
||||
# Veroeffentlicht den Installer aus dist\ als Gitea-Release (Tag v<Version>) samt SHA-256-Datei.
|
||||
# Token: Umgebungsvariable GITEA_TOKEN oder DPAPI-Datei %LOCALAPPDATA%\EuerChat\developer\gitea-token.dpapi
|
||||
# (ersatzweise die MusicBrain-Token-Datei).
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Add-Type -AssemblyName System.Net.Http
|
||||
|
||||
$Root = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$BaseUrl = "https://gitea.davito.synology.me"
|
||||
$Owner = "Davito"
|
||||
$Repository = "EuerChat"
|
||||
$LocalAppData = [Environment]::GetFolderPath("LocalApplicationData")
|
||||
$TokenPaths = @(
|
||||
(Join-Path $LocalAppData "EuerChat\developer\gitea-token.dpapi"),
|
||||
(Join-Path $LocalAppData "MusicBrain\developer\gitea-token.dpapi")
|
||||
)
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($Version)) {
|
||||
$Version = (Get-Content -LiteralPath (Join-Path $Root "src-tauri\tauri.conf.json") -Raw -Encoding UTF8 | ConvertFrom-Json).version
|
||||
}
|
||||
if ($Version -notmatch '^\d+\.\d+\.\d+$') {
|
||||
throw "Ungueltige Release-Version: $Version"
|
||||
}
|
||||
|
||||
$Tag = "v$Version"
|
||||
$InstallerName = "EuerChat_${Version}_x64-setup.exe"
|
||||
$ChecksumName = "$InstallerName.sha256"
|
||||
$InstallerPath = Join-Path $Root "dist\$InstallerName"
|
||||
$ChecksumPath = Join-Path $Root "dist\$ChecksumName"
|
||||
|
||||
if (-not (Test-Path -LiteralPath $InstallerPath -PathType Leaf)) {
|
||||
throw "Installer fehlt: $InstallerPath (zuerst build.bat ausfuehren)"
|
||||
}
|
||||
|
||||
$sha256 = [System.Security.Cryptography.SHA256]::Create()
|
||||
$stream = [System.IO.File]::OpenRead($InstallerPath)
|
||||
try {
|
||||
$hash = -join ($sha256.ComputeHash($stream) | ForEach-Object { $_.ToString("x2") })
|
||||
}
|
||||
finally {
|
||||
$stream.Dispose()
|
||||
$sha256.Dispose()
|
||||
}
|
||||
[System.IO.File]::WriteAllText($ChecksumPath, "$hash $InstallerName`n", [System.Text.UTF8Encoding]::new($false))
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($Notes)) {
|
||||
$notesFile = Join-Path $Root "RELEASE_NOTES.md"
|
||||
if (Test-Path -LiteralPath $notesFile) {
|
||||
$Notes = (Get-Content -LiteralPath $notesFile -Raw -Encoding UTF8).Trim()
|
||||
}
|
||||
}
|
||||
|
||||
$plainToken = $env:GITEA_TOKEN
|
||||
if ([string]::IsNullOrWhiteSpace($plainToken)) {
|
||||
$tokenPath = $TokenPaths | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf } | Select-Object -First 1
|
||||
if (-not $tokenPath) {
|
||||
throw "Gitea-Token fehlt. Erwartet: GITEA_TOKEN oder $($TokenPaths[0])"
|
||||
}
|
||||
$secure = (Get-Content -LiteralPath $tokenPath -Raw -Encoding UTF8).Trim() | ConvertTo-SecureString
|
||||
$pointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure)
|
||||
try { $plainToken = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($pointer) }
|
||||
finally { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($pointer) }
|
||||
}
|
||||
|
||||
$client = [System.Net.Http.HttpClient]::new()
|
||||
$client.Timeout = [TimeSpan]::FromMinutes(20)
|
||||
$client.DefaultRequestHeaders.Authorization = [System.Net.Http.Headers.AuthenticationHeaderValue]::new("token", $plainToken.Trim())
|
||||
$client.DefaultRequestHeaders.UserAgent.ParseAdd("EuerChat-Release-Publisher/$Version")
|
||||
$client.DefaultRequestHeaders.Accept.ParseAdd("application/json")
|
||||
|
||||
function Send-Gitea {
|
||||
param([string]$Method, [string]$Path, [object]$Body, [string]$Action, [switch]$AllowNotFound)
|
||||
|
||||
$request = [System.Net.Http.HttpRequestMessage]::new([System.Net.Http.HttpMethod]::new($Method), "$BaseUrl/api/v1$Path")
|
||||
try {
|
||||
if ($null -ne $Body) {
|
||||
$request.Content = [System.Net.Http.StringContent]::new(
|
||||
($Body | ConvertTo-Json -Depth 8 -Compress), [System.Text.Encoding]::UTF8, "application/json")
|
||||
}
|
||||
$response = $client.SendAsync($request).GetAwaiter().GetResult()
|
||||
try {
|
||||
$text = $response.Content.ReadAsStringAsync().GetAwaiter().GetResult()
|
||||
if ($AllowNotFound -and [int]$response.StatusCode -eq 404) { return $null }
|
||||
if (-not $response.IsSuccessStatusCode) {
|
||||
throw "$Action fehlgeschlagen (HTTP $([int]$response.StatusCode)): $text"
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($text)) { return $null }
|
||||
return $text | ConvertFrom-Json
|
||||
}
|
||||
finally { $response.Dispose() }
|
||||
}
|
||||
finally { $request.Dispose() }
|
||||
}
|
||||
|
||||
try {
|
||||
$repo = Send-Gitea -Method GET -Path "/repos/$Owner/$Repository" -Action "Repository-Zugriff pruefen"
|
||||
if (-not $repo.permissions.push) {
|
||||
throw "Der Token besitzt keine Schreibrechte fuer $Owner/$Repository."
|
||||
}
|
||||
Write-Host "Repository: $($repo.full_name) Version: $Version SHA256: $hash"
|
||||
if ($ValidateOnly) { return }
|
||||
|
||||
$encodedTag = [Uri]::EscapeDataString($Tag)
|
||||
$release = Send-Gitea -Method GET -Path "/repos/$Owner/$Repository/releases/tags/$encodedTag" -Action "Release lesen" -AllowNotFound
|
||||
|
||||
if ($null -eq $release) {
|
||||
# Gitea datiert Releases nach dem Commit von main; ohne frischen Commit bleibt /releases/latest alt.
|
||||
$marker = Send-Gitea -Method GET -Path "/repos/$Owner/$Repository/contents/RELEASES.md?ref=main" -Action "Release-Marker lesen" -AllowNotFound
|
||||
$markerText = "# EuerChat Releases`n`nLetzter veroeffentlichter Release: v$Version ($([DateTime]::UtcNow.ToString('yyyy-MM-dd HH:mm:ss')) UTC)`n"
|
||||
$markerBody = @{
|
||||
message = "Release v$Version"
|
||||
content = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($markerText))
|
||||
branch = "main"
|
||||
}
|
||||
if ($marker) { $markerBody.sha = $marker.sha }
|
||||
$markerMethod = if ($marker) { "PUT" } else { "POST" }
|
||||
Send-Gitea -Method $markerMethod -Path "/repos/$Owner/$Repository/contents/RELEASES.md" -Body $markerBody -Action "Release-Marker-Commit anlegen" | Out-Null
|
||||
|
||||
Write-Host "Lege Gitea-Release $Tag an..."
|
||||
$release = Send-Gitea -Method POST -Path "/repos/$Owner/$Repository/releases" -Action "Release anlegen" -Body @{
|
||||
tag_name = $Tag
|
||||
target_commitish = "main"
|
||||
name = "EuerChat $Version"
|
||||
body = $Notes
|
||||
draft = $false
|
||||
prerelease = $false
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Host "Setze vorhandenen Release $Tag fort."
|
||||
}
|
||||
|
||||
$existing = @($release.assets | ForEach-Object { $_.name })
|
||||
foreach ($assetPath in @($InstallerPath, $ChecksumPath)) {
|
||||
$assetName = [System.IO.Path]::GetFileName($assetPath)
|
||||
if ($assetName -in $existing) {
|
||||
Write-Host "Bereits vorhanden: $assetName"
|
||||
continue
|
||||
}
|
||||
Write-Host "Lade hoch: $assetName"
|
||||
$uploadUrl = "$BaseUrl/api/v1/repos/$Owner/$Repository/releases/$($release.id)/assets?name=$([Uri]::EscapeDataString($assetName))"
|
||||
$multipart = [System.Net.Http.MultipartFormDataContent]::new()
|
||||
$fileStream = [System.IO.File]::OpenRead($assetPath)
|
||||
$fileContent = [System.Net.Http.StreamContent]::new($fileStream)
|
||||
$fileContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::new("application/octet-stream")
|
||||
$multipart.Add($fileContent, "attachment", $assetName)
|
||||
$request = [System.Net.Http.HttpRequestMessage]::new([System.Net.Http.HttpMethod]::Post, $uploadUrl)
|
||||
$request.Content = $multipart
|
||||
try {
|
||||
$response = $client.SendAsync($request).GetAwaiter().GetResult()
|
||||
try {
|
||||
if (-not $response.IsSuccessStatusCode) {
|
||||
throw "Upload von $assetName fehlgeschlagen (HTTP $([int]$response.StatusCode)): $($response.Content.ReadAsStringAsync().GetAwaiter().GetResult())"
|
||||
}
|
||||
}
|
||||
finally { $response.Dispose() }
|
||||
}
|
||||
finally {
|
||||
$request.Dispose(); $multipart.Dispose(); $fileContent.Dispose(); $fileStream.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
$published = Send-Gitea -Method GET -Path "/repos/$Owner/$Repository/releases/tags/$encodedTag" -Action "Veroeffentlichten Release pruefen"
|
||||
$names = @($published.assets | ForEach-Object { $_.name })
|
||||
foreach ($required in @($InstallerName, $ChecksumName)) {
|
||||
if ($required -notin $names) { throw "Release wurde angelegt, aber das Asset fehlt: $required" }
|
||||
}
|
||||
Write-Host "Fertig: $BaseUrl/$Owner/$Repository/releases/tag/$Tag"
|
||||
}
|
||||
finally {
|
||||
$client.Dispose()
|
||||
}
|
||||
Reference in new issue
Block a user