param( [string]$OutputDir, [string]$PackageName ) $ErrorActionPreference = "Stop" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 $OutputEncoding = [System.Text.Encoding]::UTF8 $env:PYTHONUTF8 = "1" $env:PYTHONIOENCODING = "utf-8" $Project = Split-Path -Parent $PSScriptRoot Set-Location $Project function Write-Step { param([string]$Message) Write-Host "" Write-Host "== $Message ==" -ForegroundColor Cyan } function Invoke-Git { param([string[]]$GitArgs) $Output = & git @GitArgs 2>&1 if ($LASTEXITCODE -ne 0) { throw "git $($GitArgs -join ' ') failed: $Output" } return $Output } if (-not (Get-Command git -ErrorAction SilentlyContinue)) { throw "Git is required to build the installer package." } $Commit = (Invoke-Git @("rev-parse", "--short=12", "HEAD")).Trim() $Branch = (Invoke-Git @("rev-parse", "--abbrev-ref", "HEAD")).Trim() $Status = Invoke-Git @("status", "--porcelain") if (-not $OutputDir) { $OutputDir = Join-Path $Project "dist" } if (-not [System.IO.Path]::IsPathRooted($OutputDir)) { $OutputDir = Join-Path $Project $OutputDir } if (-not $PackageName) { $Stamp = Get-Date -Format "yyyyMMdd_HHmmss" $PackageName = "stockbot_v3_installer_${Stamp}_${Commit}.zip" } if (-not $PackageName.EndsWith(".zip", [System.StringComparison]::OrdinalIgnoreCase)) { $PackageName = "$PackageName.zip" } New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null $PackagePath = Join-Path $OutputDir $PackageName $ManifestPath = Join-Path $OutputDir ($PackageName -replace "\.zip$", ".manifest.txt") Write-Step "Preflight" Write-Host "Project : $Project" Write-Host "Branch : $Branch" Write-Host "Commit : $Commit" if ($Status) { Write-Host "[warn] Working tree has uncommitted changes. Package uses committed HEAD only." -ForegroundColor Yellow $Status | ForEach-Object { Write-Host " $_" -ForegroundColor Yellow } } Write-Step "Archive" if (Test-Path $PackagePath) { Remove-Item -LiteralPath $PackagePath -Force } Invoke-Git @("archive", "--format=zip", "--output", $PackagePath, "HEAD") | Out-Null $PackageInfo = Get-Item $PackagePath $TrackedCount = (Invoke-Git @("ls-tree", "-r", "--name-only", "HEAD") | Measure-Object).Count $Manifest = @( "StockBot v3 installer package", "BuiltAt=$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')", "Branch=$Branch", "Commit=$Commit", "Package=$($PackageInfo.Name)", "Bytes=$($PackageInfo.Length)", "TrackedFiles=$TrackedCount", "", "Included:", "- committed project files from HEAD", "- vendor/wheels offline wheelhouse", "- models/scalping_model.* when tracked", "- data/*training_dataset.csv when tracked", "", "Excluded by design:", "- .git history", "- .env and credentials", "- data/stockbot.db", "- data/kis_token_*.json", "- logs and lock files", "- local virtual environments" ) $Manifest | Set-Content -Path $ManifestPath -Encoding UTF8 Write-Step "Done" Write-Host "Package : $PackagePath" -ForegroundColor Green Write-Host "Manifest: $ManifestPath" -ForegroundColor Green