From cfc32c18651d4c1588c3754e13012633a558a24d Mon Sep 17 00:00:00 2001 From: Oksion Date: Wed, 29 Jul 2026 14:42:13 +0500 Subject: [PATCH] =?UTF-8?q?ci(winget):=20=D0=B0=D0=B2=D1=82=D0=BE-=D0=B2?= =?UTF-8?q?=D0=BE=D0=B7=D0=B2=D1=80=D0=B0=D1=82=20=D0=BF=D0=BE=D0=BB=D0=B5?= =?UTF-8?q?=D0=B9,=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5=20Komac=20?= =?UTF-8?q?=D1=82=D0=B5=D1=80=D1=8F=D0=B5=D1=82=20=D0=B2=20=D0=BC=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=84=D0=B5=D1=81=D1=82=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MinimumOSVersion уезжал из installer-манифеста и в 0.7.0, и в 0.8.0 — Komac пересобирает манифест из portable-exe и молча теряет поля, которые из бинаря не выводятся; валидатор winget-pkgs без них режет PR. До сих пор поле возвращали руками на каждом релизе. Новый шаг в winget.yml после winget-releaser гоняет .github/scripts/winget-restore-fields.ps1: - находит ветку PR в форке по детерминированному префиксу Oksion.XiControl-<версия>- (не через Search API — тот лагает первые минуты) - дописывает MinimumOSVersion перед InstallerType и коммитит в ветку форка, открытый PR подхватывает коммит сам - идемпотентен: поле на месте → выходит без изменений; можно гонять локально (-Tag vX.Y.Z) — так и пропатчен PR #409366 для 0.8.0 (скрипт проверен боем) Контрольная точка в скилле release остаётся: сверка с эталоном reference/winget/ ловит поля, которых скрипт ещё не знает. Co-Authored-By: Claude Fable 5 --- .github/scripts/winget-restore-fields.ps1 | 49 +++++++++++++++++++++++ .github/workflows/winget.yml | 11 +++++ CLAUDE.md | 3 ++ 3 files changed, 63 insertions(+) create mode 100644 .github/scripts/winget-restore-fields.ps1 diff --git a/.github/scripts/winget-restore-fields.ps1 b/.github/scripts/winget-restore-fields.ps1 new file mode 100644 index 0000000..cfab9ce --- /dev/null +++ b/.github/scripts/winget-restore-fields.ps1 @@ -0,0 +1,49 @@ +# Возвращает в winget-манифест рукописные поля, которые Komac (winget-releaser) +# теряет при пересборке installer-манифеста из portable-exe. История: MinimumOSVersion +# уехал в 0.7.0 и 0.8.0 — без него валидатор winget-pkgs режет PR («Inconsistencies +# detected … Missing property MinimumOSVersion»). +# +# Работает по ветке ФОРКА (Oksion/winget-pkgs), а не по PR: ветку Komac создаёт с +# детерминированным префиксом Oksion.XiControl-<версия>-, коммит в неё сам обновляет +# открытый PR, и не нужен Search API (он лагает первые минуты после создания PR). +# Идемпотентен: поле уже на месте → выходит без изменений, шаг можно перезапускать. +# +# Локальный запуск (нужен gh с правами на форк): ./winget-restore-fields.ps1 -Tag v0.8.0 +param([Parameter(Mandatory)][string]$Tag) +$ErrorActionPreference = 'Stop' + +$version = $Tag -replace '^v', '' +$fork = 'Oksion/winget-pkgs' +$prefix = "Oksion.XiControl-$version-" +$path = "manifests/o/Oksion/XiControl/$version/Oksion.XiControl.installer.yaml" + +# ветка появляется, когда winget-releaser отработал; в CI шаг идёт следом, +# но даём API время на согласованность +$branch = $null +for ($i = 0; $i -lt 12 -and -not $branch; $i++) { + if ($i) { Start-Sleep -Seconds 10 } + $branch = gh api "repos/$fork/branches?per_page=100" --paginate --jq '.[].name' | + Where-Object { $_.StartsWith($prefix) } | Select-Object -First 1 +} +if (-not $branch) { throw "Ветка $prefix* в $fork не найдена — winget-releaser не отработал?" } +Write-Host "Ветка PR: $branch" + +$file = gh api "repos/$fork/contents/${path}?ref=$branch" | ConvertFrom-Json +$text = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($file.content)) + +if ($text -match '(?m)^MinimumOSVersion:') { + Write-Host 'MinimumOSVersion уже на месте — Komac починили? Патч не нужен.' + exit 0 +} + +# вставляем по порядку полей эталона (reference/winget/): после Platform, перед InstallerType +$lines = [System.Collections.Generic.List[string]]($text -split "`r?`n") +$idx = $lines.FindIndex({ param($l) $l -match '^InstallerType:' }) +if ($idx -lt 0) { throw "В $path не нашлась строка InstallerType — формат манифеста изменился, нужен глаз." } +$lines.Insert($idx, 'MinimumOSVersion: 10.0.0.0') + +$b64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(($lines -join "`n"))) +gh api -X PUT "repos/$fork/contents/$path" ` + -f message="Restore MinimumOSVersion dropped by Komac (portable manifest)" ` + -f content=$b64 -f sha=$($file.sha) -f branch=$branch | Out-Null +Write-Host "MinimumOSVersion возвращён в $path (ветка $branch); валидация PR перезапустится сама." diff --git a/.github/workflows/winget.yml b/.github/workflows/winget.yml index cc31d84..0ea84ef 100644 --- a/.github/workflows/winget.yml +++ b/.github/workflows/winget.yml @@ -23,6 +23,8 @@ jobs: env: HAS_TOKEN: ${{ secrets.WINGET_TOKEN != '' }} steps: + - uses: actions/checkout@v7 # ради .github/scripts (winget-releaser чекаут не нужен) + if: env.HAS_TOKEN == 'true' - name: Publish to winget if: env.HAS_TOKEN == 'true' uses: vedantmgoyal9/winget-releaser@v2 @@ -32,6 +34,15 @@ jobs: # тег: из ввода при ручном запуске, иначе из события release release-tag: ${{ inputs.tag || github.event.release.tag_name }} token: ${{ secrets.WINGET_TOKEN }} + # Komac пересобирает installer-манифест из exe и теряет рукописные поля — + # MinimumOSVersion уезжал в 0.7.0 и 0.8.0, валидатор winget без него режет PR. + # Возвращаем поля прямо в ветку форка (PR обновится сам); скрипт идемпотентен. + - name: Restore hand-written manifest fields + if: env.HAS_TOKEN == 'true' + shell: pwsh + env: + GH_TOKEN: ${{ secrets.WINGET_TOKEN }} + run: ./.github/scripts/winget-restore-fields.ps1 -Tag '${{ inputs.tag || github.event.release.tag_name }}' - name: No token — skip if: env.HAS_TOKEN != 'true' run: echo "Секрет WINGET_TOKEN не задан — публикация в winget пропущена." diff --git a/CLAUDE.md b/CLAUDE.md index 190fbd4..ff619bc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -225,6 +225,9 @@ WMI-событий). `Program.cs`: single-instance mutex → DI-контейне файл с живым железом — впиши его в исключения, иначе гейт покраснеет на ровном месте. - Локальная сборка помечается версией `0.0.0-dev` (дев-дефолт в `XiControl.csproj`, суффикс виден в AboutTab); реальную версию подставляет CI из тега: `publish -p:Version=X.Y.Z`. +- winget-PR Komac пересобирает из exe и теряет рукописные поля (`MinimumOSVersion` — в 0.7.0 и 0.8.0); + `winget.yml` возвращает их сам шагом `.github/scripts/winget-restore-fields.ps1` (правит ветку + форка, идемпотентен). После релиза всё равно свериться с эталоном `reference/winget/<версия>/`. ## Ограничения среды