param( [Parameter(Mandatory = $true)] [ValidatePattern('^\d+\.\d+\.\d+$')] [string]$Version, # Только для проверки сборки из рабочей копии. Такой архив помечен dev. [switch]$AllowDirty ) $ErrorActionPreference = 'Stop' $root = Split-Path -Parent $MyInvocation.MyCommand.Path Push-Location $root try { $inside = & git rev-parse --is-inside-work-tree 2>$null if ($LASTEXITCODE -ne 0 -or $inside -ne 'true') { throw 'Запустите скрипт из Git-репозитория проекта.' } $commit = (& git rev-parse --short=12 HEAD).Trim() if ($LASTEXITCODE -ne 0) { throw 'Не удалось определить Git-коммит.' } $changes = @(& git status --porcelain=v1 --untracked-files=normal) if ($LASTEXITCODE -ne 0) { throw 'Не удалось проверить состояние Git.' } $dirty = $changes.Count -gt 0 if ($dirty -and -not $AllowDirty) { throw 'Для релиза нужен чистый Git-коммит. Для пробной сборки используйте -AllowDirty.' } $tag = 'v' + $Version $tagCommit = & git rev-list -n 1 $tag 2>$null if ($LASTEXITCODE -eq 0) { $headCommit = (& git rev-parse HEAD).Trim() if ($tagCommit.Trim() -ne $headCommit) { throw "Тег $tag уже указывает на другой коммит. Выберите новую версию." } } $dist = Join-Path $root 'dist' New-Item -ItemType Directory -Path $dist -Force | Out-Null $stressRoot = Join-Path $dist ('stress-' + [guid]::NewGuid().ToString('N')) New-Item -ItemType Directory -Path $stressRoot | Out-Null $previousStressRoot = $env:SB_STRESS_ROOT $env:SB_STRESS_ROOT = $stressRoot try { foreach ($mode in @('staged', 'importtest', 'profiletest', 'stress')) { Write-Host "[*] build.cmd $mode" & $env:ComSpec /d /c build.cmd $mode if ($LASTEXITCODE -ne 0) { throw "Сборка или проверка $mode завершилась с ошибкой." } } } finally { $env:SB_STRESS_ROOT = $previousStressRoot $stressFull = [IO.Path]::GetFullPath($stressRoot) $distFull = [IO.Path]::GetFullPath($dist).TrimEnd('\') + '\' if ($stressFull.StartsWith($distFull, [StringComparison]::OrdinalIgnoreCase)) { Remove-Item -LiteralPath $stressFull -Recurse -Force } } $exe = Join-Path $root 'SbLauncher.updated.exe' $builtVersion = [Reflection.AssemblyName]::GetAssemblyName($exe).Version.ToString(3) if ($builtVersion -ne $Version) { throw "Версия сборки $builtVersion не совпадает с $Version. Обновите Version.cs." } $suffix = if ($dirty) { "-dev-$commit-$([DateTime]::UtcNow.ToString('yyyyMMddHHmmss'))" } else { '' } $baseName = "SbLauncher-v$Version-win-x64$suffix" $archive = Join-Path $dist ($baseName + '.zip') $checksum = $archive + '.sha256' if ((Test-Path -LiteralPath $archive) -or (Test-Path -LiteralPath $checksum)) { throw "Файл $baseName уже существует в dist. Удалите его вручную или выберите новую версию." } $stage = Join-Path $dist ('stage-' + [guid]::NewGuid().ToString('N')) New-Item -ItemType Directory -Path $stage | Out-Null try { Copy-Item -LiteralPath $exe -Destination (Join-Path $stage 'SbLauncher.exe') foreach ($name in @('Ui.xaml', 'README.md', 'CHANGELOG.md', 'profiles.example.json', 'local.example.json')) { Copy-Item -LiteralPath (Join-Path $root $name) -Destination $stage } $templates = Join-Path $stage 'templates' New-Item -ItemType Directory -Path $templates | Out-Null foreach ($name in @('wg.json', 'direct.json', 'wgonly.json')) { Copy-Item -LiteralPath (Join-Path (Join-Path $root 'templates') $name) -Destination $templates } $preview = Join-Path $stage 'preview' New-Item -ItemType Directory -Path $preview | Out-Null foreach ($name in @('glass-light.png', 'glass-dark.png')) { Copy-Item -LiteralPath (Join-Path (Join-Path $root 'preview') $name) -Destination $preview } @("Version: $tag", "Commit: $commit", "Build: win-x64") | Set-Content -LiteralPath (Join-Path $stage 'VERSION.txt') -Encoding UTF8 Compress-Archive -Path (Join-Path $stage '*') -DestinationPath $archive -CompressionLevel Optimal } finally { $stageFull = [IO.Path]::GetFullPath($stage) $distFull = [IO.Path]::GetFullPath($dist).TrimEnd('\') + '\' if ($stageFull.StartsWith($distFull, [StringComparison]::OrdinalIgnoreCase)) { Remove-Item -LiteralPath $stageFull -Recurse -Force } } $hash = (Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash.ToLowerInvariant() "$hash $($baseName).zip" | Set-Content -LiteralPath $checksum -Encoding ASCII Write-Host "[+] $archive" Write-Host "[+] $checksum" if ($dirty) { Write-Warning 'Это пробная сборка из изменённой рабочей копии. Не публикуйте её как релиз.' } } finally { Pop-Location }