# Local Windows release pipeline. Run after committing a new version on main. $ErrorActionPreference = 'Stop' Set-StrictMode -Version Latest function Assert-LastCommand($description) { if ($LASTEXITCODE -ne 0) { throw "$description завершилась с кодом $LASTEXITCODE" } } $projectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path Push-Location $projectRoot try { $branch = (& git branch --show-current).Trim() Assert-LastCommand 'Проверка ветки' if ($branch -ne 'main') { throw 'Публикация возможна только из ветки main' } $changes = & git status --porcelain Assert-LastCommand 'Проверка рабочего дерева' if ($changes) { throw 'Перед выпуском закоммитьте все изменения' } $python = Join-Path $projectRoot '.venv_gui310\Scripts\python.exe' if (-not (Test-Path $python)) { & py -3.10 -m venv .venv_gui310 Assert-LastCommand 'Создание окружения Python 3.10' } & $python -m pip install -r requirements_gui.txt Assert-LastCommand 'Установка зависимостей' $version = (& $python -c 'from app_version import APP_VERSION; print(APP_VERSION)').Trim() Assert-LastCommand 'Чтение версии' $tag = "v$version" $versionLine = '#define MyAppVersion "' + $version + '"' if (-not (Select-String -Path installer.iss -SimpleMatch $versionLine)) { throw 'Версия installer.iss не совпадает с app_version.py' } $notes = Join-Path $projectRoot "docs\releases\$tag.md" if (-not (Test-Path $notes)) { throw "Нет описания релиза $notes" } $head = (& git rev-parse HEAD).Trim() Assert-LastCommand 'Чтение коммита' $existingTag = & git tag --list $tag Assert-LastCommand 'Проверка тега' if ($existingTag) { $tagCommit = (& git rev-list -n 1 $tag).Trim() Assert-LastCommand 'Проверка коммита тега' if ($tagCommit -ne $head) { throw "Тег $tag уже указывает на другой коммит. Увеличьте версию." } } & $python -m unittest discover -s tests -p '*_test.py' -v Assert-LastCommand 'Тесты' & $python -m PyInstaller gui_app.spec --clean --noconfirm Assert-LastCommand 'Сборка EXE' if (-not (Test-Path 'dist\MoySkladGenerator.exe')) { throw 'EXE не создан' } $iscc = Get-Command ISCC.exe -ErrorAction SilentlyContinue if ($iscc) { $compiler = $iscc.Source } elseif (Test-Path "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe") { $compiler = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe" } else { $compiler = "$env:LOCALAPPDATA\Programs\Inno Setup 6\ISCC.exe" } if (-not (Test-Path $compiler)) { throw 'Inno Setup 6 (ISCC.exe) не найден' } & $compiler installer.iss Assert-LastCommand 'Сборка установщика' if (-not (Test-Path 'installer_output\MoySklad_Generator_Setup.exe')) { throw 'Установщик не создан' } & git push gitea main Assert-LastCommand 'Отправка main в Gitea' & git push origin main Assert-LastCommand 'Отправка main в GitHub' if (-not $existingTag) { & git tag -a $tag -m "Release $tag" Assert-LastCommand 'Создание тега' } & git push gitea $tag Assert-LastCommand 'Отправка тега в Gitea' & git push origin $tag Assert-LastCommand 'Отправка тега в GitHub' & $python scripts\publish_gitea_release.py $tag --body-file $notes --use-git-credential Assert-LastCommand 'Публикация релиза в Gitea' } finally { Pop-Location }