Files
screen-translator/.gitea/workflows/build.yaml
T
gusadmin 8fdf242b12
build / build (push) Failing after 3s
CI: клонировать репозиторий напрямую вместо actions/checkout
С раннера не проходит TLS до github.com, откуда тянется действие checkout
(`net/http: TLS handshake timeout`), и сборка падала на первом же шаге.
Репозиторий публичный и живёт на том же сервере, поэтому обычный git clone
делает то же самое, но без похода наружу.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 15:56:03 +03:00

173 lines
9.8 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Сборка и публикация «Переводчика экрана».
#
# Идёт на self-hosted Windows-раннере (метка `windows`, host mode) — иначе никак:
# распознавание держится на Windows.Media.Ocr, а сборка — на Roslyn из VS Build Tools
# и на Windows.winmd из Windows SDK. В контейнере ничего этого нет.
#
# * push в master -> сборка + прогон проверок + перезапись релиза `latest`
# * push тега v* -> то же, но отдельный постоянный релиз с этой версией
#
# Требований к раннеру всего два, и оба уже выполнены (тот же хост собирает GusVoice):
# Visual Studio Build Tools (нужен Roslyn csc) и Windows SDK (Windows.winmd).
# Если Roslyn вдруг отсутствует, build.ps1 сам откатывается на компилятор из состава
# Windows — код специально написан без возможностей C# 6 и выше, чтобы это работало.
name: build
on:
push:
branches: [master]
tags: ['v*']
workflow_dispatch:
permissions:
contents: write
env:
GITEA_HOST: gitea.gusik.tech
jobs:
build:
runs-on: windows
steps:
# Обычный actions/checkout тянется с github.com, а до него из этой сети TLS не доходит
# (`net/http: TLS handshake timeout`). Репозиторий публичный и лежит рядом, поэтому
# проще и надёжнее склонировать его напрямую, без внешних действий.
- name: Checkout
shell: pwsh
env:
REPO: ${{ github.repository }}
SHA: ${{ github.sha }}
run: |
$ErrorActionPreference = 'Stop'
git init -q .
git remote add origin "https://$($env:GITEA_HOST)/$($env:REPO).git"
git -c protocol.version=2 fetch -q --depth 1 origin $env:SHA
git checkout -q FETCH_HEAD
git log --oneline -1
- name: Сборка exe и диагностической утилиты
shell: pwsh
run: .\build.ps1 -Test
# Модель правдоподобия английского — единственная часть, которую можно проверить
# без экрана и без языковых пакетов. Проверяет, что таблица биграмм на месте и
# всё ещё отделяет настоящие надписи от каши распознавания.
- name: Проверка биграммной модели
shell: pwsh
run: |
$out = & .\dist\RenderTest.exe --selftest 2>&1 | Out-String
Write-Host $out
if ($LASTEXITCODE -ne 0) { throw "selftest завершился с кодом $LASTEXITCODE" }
if ($out -notmatch 'худший «хороший»') { throw "selftest не выдал сводку — модель не загрузилась" }
# Гейт качества на эталонном кадре. Работает, только если на раннере установлен
# английский пакет распознавания; если его нет — не валим сборку, а предупреждаем:
# это среда, а не регрессия кода.
- name: Проверка распознавания на эталоне
shell: pwsh
run: |
.\tools\make-sample.ps1
$out = & .\dist\RenderTest.exe --in .\dist\sample.png --out .\dist\ci --no-translate 2>&1 | Out-String
Write-Host $out
if ($out -match 'OCR недоступен') {
Write-Host '::warning::на раннере нет модели распознавания — проверка кадра пропущена'
exit 0
}
if ($out -notmatch 'блоков (\d+)') { throw "RenderTest не отчитался о блоках" }
$blocks = [int]$Matches[1]
Write-Host "распознано блоков: $blocks"
# На этом кадре стабильно выходит 27-29 блоков. Резкое расхождение означает, что
# правки в Blocks.cs поехали — либо всё слиплось, либо рассыпалось.
if ($blocks -lt 18 -or $blocks -gt 40) { throw "неожиданное число блоков ($blocks) — сегментация сломана" }
- name: Сборка пакета
shell: pwsh
run: |
$rel = 'release'
New-Item -ItemType Directory -Force -Path $rel | Out-Null
Copy-Item .\dist\ScreenTranslator.exe $rel -Force
Copy-Item '.\ЧИТАЙ МЕНЯ.txt' $rel -Force -ErrorAction SilentlyContinue
# config.json генерирует само приложение из вшитого умолчания
& .\dist\ScreenTranslator.exe --write-config
Start-Sleep -Seconds 2
if (Test-Path .\dist\config.json) { Copy-Item .\dist\config.json $rel -Force }
else { Write-Host '::warning::config.json не создан — пакет уедет без него' }
Compress-Archive -Path "$rel\*" -DestinationPath 'ПереводчикЭкрана.zip' -Force
Get-ChildItem 'ПереводчикЭкрана.zip' | Format-List Name, Length
# Тег v* -> постоянный релиз. Любой push в master -> перезаписываемый `latest`,
# чтобы у тех, кому программу отдали, всегда была ссылка на свежую сборку.
- name: Публикация релиза
shell: pwsh
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
REPO: ${{ github.repository }}
REF_NAME: ${{ github.ref_name }}
REF: ${{ github.ref }}
SHA: ${{ github.sha }}
run: |
$ErrorActionPreference = 'Stop'
$host_ = $env:GITEA_HOST
$base = "https://${host_}/api/v1/repos/$($env:REPO)"
$hdr = @{ Authorization = "token $($env:GITEA_TOKEN)" }
$isTag = $env:REF -like 'refs/tags/*'
$tag = if ($isTag) { $env:REF_NAME } else { 'latest' }
if (-not $isTag) {
# Скользящий релиз: сносим прошлый вместе с тегом, иначе он останется
# висеть на старом коммите и «свежая сборка» перестанет быть свежей.
try {
$old = Invoke-RestMethod -Uri "$base/releases/tags/$tag" -Headers $hdr
if ($old.id) {
Invoke-RestMethod -Method Delete -Uri "$base/releases/$($old.id)" -Headers $hdr | Out-Null
Write-Host "удалён прошлый релиз $tag"
}
} catch { }
try { Invoke-RestMethod -Method Delete -Uri "$base/tags/$tag" -Headers $hdr | Out-Null } catch { }
}
$short = $env:SHA.Substring(0, 8)
$stamp = (Get-Date).ToUniversalTime().ToString('yyyy-MM-dd HH:mm') + ' UTC'
$notes = if ($isTag) {
"Версия $tag`n`nСборка из коммита $short."
} else {
"Свежая сборка из master, коммит $short, собрана $stamp.`n`n" +
"Обновляется автоматически при каждом изменении. Для стабильной версии смотрите релизы с номером."
}
$body = @{
tag_name = $tag
target_commitish = $env:SHA
name = if ($isTag) { $tag } else { "Свежая сборка ($short)" }
body = $notes
draft = $false
prerelease = (-not $isTag)
} | ConvertTo-Json -Compress
try {
$rel = Invoke-RestMethod -Method Post -Uri "$base/releases" -Headers $hdr -ContentType 'application/json' -Body $body
} catch {
# Релиз на этот тег уже есть (перезапуск задания) — берём его и обновляем описание
$rel = Invoke-RestMethod -Uri "$base/releases/tags/$tag" -Headers $hdr
$patch = @{ body = $notes } | ConvertTo-Json -Compress
Invoke-RestMethod -Method Patch -Uri "$base/releases/$($rel.id)" -Headers $hdr -ContentType 'application/json' -Body $patch | Out-Null
}
if (-not $rel.id) { throw "не удалось получить релиз для тега $tag" }
# Старые файлы с тем же именем API не заменяет, поэтому сначала чистим
try {
foreach ($a in (Invoke-RestMethod -Uri "$base/releases/$($rel.id)/assets" -Headers $hdr)) {
Invoke-RestMethod -Method Delete -Uri "$base/releases/$($rel.id)/assets/$($a.id)" -Headers $hdr | Out-Null
}
} catch { }
foreach ($f in @('ПереводчикЭкрана.zip', '.\dist\ScreenTranslator.exe')) {
$item = Get-Item $f
Write-Host "загружаю $($item.Name)…"
& curl.exe -sf -X POST "$base/releases/$($rel.id)/assets?name=$($item.Name)" `
-H "Authorization: token $($env:GITEA_TOKEN)" -F "attachment=@$($item.FullName)"
if ($LASTEXITCODE -ne 0) { throw "не удалось загрузить $($item.Name)" }
}
Write-Host "релиз $tag опубликован: https://${host_}/$($env:REPO)/releases"