From 612446d65b572f7d0191f6f5dc0ec81ac692e1f3 Mon Sep 17 00:00:00 2001 From: "ki.sagidullin" Date: Fri, 21 Aug 2026 00:05:54 +0500 Subject: [PATCH] chore(scripts): add build-publish-ui.ps1 --- scripts/build-publish-ui.ps1 | 109 +++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 scripts/build-publish-ui.ps1 diff --git a/scripts/build-publish-ui.ps1 b/scripts/build-publish-ui.ps1 new file mode 100644 index 0000000..e752d36 --- /dev/null +++ b/scripts/build-publish-ui.ps1 @@ -0,0 +1,109 @@ +<# +build-publish-ui.ps1 — локальная сборка Windows-бинаря с UI (Fyne) и публикация в Gitea Packages. + +Почему локально: Fyne-окно требует cgo + C-компилятор (MinGW/gcc), которых нет в CI. +CI собирает ТОЛЬКО headless-linux (см. .gitea/workflows/ci.yaml). Windows-бинарь +с графическим окном собирается на Windows-машине Камиля и публикуется скриптом ниже +в ту же версию commit-, что и CI, с теми же companion-файлами (.version/.sha256), +чтобы автообновление (U4 checksum, ResolveLatest) работало без изменений. + +Требования: + - Go с доступным C-компилятором (CGO_ENABLED=1). WinLibs gcc: см. память + `mem:toolchain/cgo-winlibs-gcc` — bin нужно добавить в PATH перед запуском. + - Файл scripts/.gitea-creds (git-ignored, см. ниже) с токенами. + Формат (по одной `ключ=значение` на строку): + GITEA_TOKEN=write:packages-токен + UPDATE_TOKEN=read:package-токен + GIT_MAIN_URL=http://gitea.hal9000.home + - Ветка уже запушена в `main` (VERSION = commit- от текущего HEAD). + +Пример: + powershell -ExecutionPolicy Bypass -File scripts/build-publish-ui.ps1 +#> + +$ErrorActionPreference = "Stop" + +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$RepoRoot = Split-Path -Parent $ScriptDir +$CredsFile = Join-Path $ScriptDir ".gitea-creds" +$Package = "ratatoskr" +$Owner = "kamelion" +$Filename = "ratatoskr-windows-amd64.exe" + +Set-Location $RepoRoot + +# --- 0. Проверка C-тулчейна --- +if ($env:CGO_ENABLED -eq "0") { Write-Error "CGO_ENABLED=0 — нужен C-компилятор (MinGW). Уберите его из env." } +if (-not (Get-Command gcc -ErrorAction SilentlyContinue)) { + Write-Host "gcc не найден в PATH. Пример (WinLibs):" + Write-Host ' $p = "<...>\mingw64\bin"; $env:Path = "$p;$env:Path"' + Write-Error "C-компилятор gcc не найден." +} +Write-Host "[ok] gcc: $((gcc --version | Select-Object -First 1))" + +# --- 1. Чтение секретов --- +if (-not (Test-Path $CredsFile)) { + Write-Error "Нет файла секретов: $CredsFile`nФормат: GITEA_TOKEN=... / UPDATE_TOKEN=... / GIT_MAIN_URL=..." +} +$creds = @{} +Get-Content $CredsFile | ForEach-Object { + $line = $_.Trim() + if ($line -and -not $line.StartsWith("#")) { + $kv = $line.Split("=", 2) + if ($kv.Count -eq 2) { $creds[$kv[0].Trim()] = $kv[1].Trim() } + } +} +$giteaToken = $creds["GITEA_TOKEN"] +$updateToken = $creds["UPDATE_TOKEN"] +$giteaUrl = $creds["GIT_MAIN_URL"] +if (-not $giteaToken) { Write-Error "В $CredsFile нет GITEA_TOKEN (нужен write:packages)." } +if (-not $giteaUrl) { Write-Error "В $CredsFile нет GIT_MAIN_URL." } + +# --- 2. Версия = commit- текущего HEAD (совпадает с именованием CI) --- +$sha = (git rev-parse --short HEAD).Trim() +if (-not $sha) { Write-Error "git rev-parse --short HEAD не дал хэш." } +$Version = "commit-$sha" +Write-Host "[build] VERSION=$Version FILENAME=$Filename" + +# --- 3. Сборка (cgo + UI) --- +$env:CGO_ENABLED = "1" +$out = Join-Path $RepoRoot $Filename +$ldflags = "-s -w -X main.version=${Version} -X main.updateToken=${updateToken}" +Write-Host "[build] go build -ldflags=... -o $Filename" +$goArgs = @("build", "-ldflags=$ldflags", "-o", $out, "./cmd/ratatoskr/") +go $goArgs +if ($LASTEXITCODE -ne 0) { Write-Error "go build завершился с кодом $LASTEXITCODE" } + +# --- 4. Companion-файлы (.version, .sha256) --- +$sha256Hex = (Get-FileHash -Algorithm SHA256 $out).Hash.ToLower() +$verFile = "$out.version" +$sumFile = "$out.sha256" +Set-Content -Path $verFile -Value $Version -NoNewline -Encoding ascii +Set-Content -Path $sumFile -Value $sha256Hex -NoNewline -Encoding ascii +Write-Host "[ok] bin: $out ($([math]::Round((Get-Item $out).Length/1MB,1)) MB)" +Write-Host "[ok] sha256: $sha256Hex" + +# --- 5. Публикация в Gitea Packages --- +$api = "$giteaUrl/api/packages/$Owner/generic/$Package/$Version" +$files = @($Filename, "$Filename.version", "$Filename.sha256") +foreach ($f in $files) { + Write-Host "[put] $api/$f" + curl.exe -sS -X PUT ` + -H "Authorization: token $giteaToken" ` + -H "Content-Type: application/octet-stream" ` + "$api/$f" ` + --data-binary "@$f" + if ($LASTEXITCODE -ne 0) { Write-Error "curl PUT $f завершился с кодом $LASTEXITCODE" } +} + +# --- 6. Самопроверка: читаем .sha256 обратно и сверяем (контракт U4) --- +Write-Host "[verify] перечитываю $Filename.sha256 из Gitea..." +$remoteSum = (curl.exe -sS -H "Authorization: token $giteaToken" "$api/$Filename.sha256").Trim() +if ($remoteSum -ne $sha256Hex) { + Write-Error "Проверка не сошлась: remote=$remoteSum local=$sha256Hex" +} +$remoteVer = (curl.exe -sS -H "Authorization: token $giteaToken" "$api/$Filename.version").Trim() +if ($remoteVer -ne $Version) { + Write-Error "Версия не сошлась: remote=$remoteVer local=$Version" +} +Write-Host "[ok] опубликовано и проверено: $Version/$Filename (+.version, +.sha256)"