<# ci\package.ps1 목적: - PyInstaller 결과물을 out\ 폴더에 “릴리즈 업로드용” 파일로 패키징 - onefile: dist\.exe -> out\--windows.exe - onedir : dist\\... -> out\--windows.zip 사용: powershell -NoProfile -ExecutionPolicy Bypass -File .\ci\package.ps1 -App "myapp" -Tag "v0.1.11" #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$App, [Parameter(Mandatory = $true)] [string]$Tag, # 작업 루트(기본: 현재 워크스페이스) [string]$Root = ".", # 결과물을 넣을 폴더 [string]$OutDir = "out", # PyInstaller 기본 출력 폴더 [string]$DistDir = "dist", # zip 생성 시 include 루트 폴더 자체를 포함할지 여부(기본: 포함) [switch]$IncludeRootFolder, # 기존 out\ 파일 삭제 여부(기본: true) [switch]$CleanOut = $true, # sha256 체크섬 파일 생성 여부 [switch]$WriteChecksum = $true ) Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" function Resolve-FullPath([string]$p) { return (Resolve-Path -LiteralPath $p).Path } function Ensure-Dir([string]$p) { if (-not (Test-Path -LiteralPath $p)) { New-Item -ItemType Directory -Path $p | Out-Null } } function Write-Sha256([string]$filePath, [string]$outPath) { $h = Get-FileHash -Algorithm SHA256 -LiteralPath $filePath # "SHA256 filename" 형태 "$($h.Hash) $([IO.Path]::GetFileName($filePath))" | Out-File -LiteralPath $outPath -Encoding ascii } # ---- paths ---- $rootPath = Resolve-FullPath $Root $distPath = Join-Path $rootPath $DistDir $outPath = Join-Path $rootPath $OutDir Ensure-Dir $outPath if ($CleanOut) { Get-ChildItem -LiteralPath $outPath -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue } if (-not (Test-Path -LiteralPath $distPath)) { throw "Dist folder not found: $distPath (PyInstaller output missing?)" } # ---- decide output type ---- $exePath = Join-Path $distPath "$App.exe" $onedirPath = Join-Path $distPath $App # 파일명 규칙(윈도우 릴리즈 자산명) # 예: parameter_editor-v0.1.11-windows.exe / .zip $baseName = "$App-$Tag-windows" Write-Host "[PACKAGE] App=$App Tag=$Tag" Write-Host "[PACKAGE] dist=$distPath" Write-Host "[PACKAGE] out =$outPath" # ---- onefile ---- if (Test-Path -LiteralPath $exePath) { $destExe = Join-Path $outPath "$baseName.exe" Copy-Item -LiteralPath $exePath -Destination $destExe -Force Write-Host "[PACKAGE] Copied onefile exe -> $destExe" if ($WriteChecksum) { $shaPath = Join-Path $outPath "$baseName.exe.sha256" Write-Sha256 $destExe $shaPath Write-Host "[PACKAGE] Wrote checksum -> $shaPath" } exit 0 } # ---- onedir ---- if (Test-Path -LiteralPath $onedirPath) { $zipPath = Join-Path $outPath "$baseName.zip" if (Test-Path -LiteralPath $zipPath) { Remove-Item -LiteralPath $zipPath -Force } if ($IncludeRootFolder) { # dist\\... 를 zip에 \... 형태로 포함 Compress-Archive -LiteralPath $onedirPath -DestinationPath $zipPath -Force } else { # dist\\ 내부만 zip에 담기 (루트 폴더 없이) $items = Get-ChildItem -LiteralPath $onedirPath if (-not $items -or $items.Count -eq 0) { throw "Onedir folder is empty: $onedirPath" } Compress-Archive -LiteralPath $items.FullName -DestinationPath $zipPath -Force } Write-Host "[PACKAGE] Created onedir zip -> $zipPath" if ($WriteChecksum) { $shaPath = Join-Path $outPath "$baseName.zip.sha256" Write-Sha256 $zipPath $shaPath Write-Host "[PACKAGE] Wrote checksum -> $shaPath" } exit 0 } throw "No PyInstaller output found. Expected one of:`n- $exePath`n- $onedirPath"