diff --git a/.gitignore b/.gitignore index 97c3265..84d0f81 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ data/redis/ models/ logs/*.log logs/*.pid +dist/ __pycache__/ .venv/ *.pyc diff --git a/Build_StockBot_Installer.bat b/Build_StockBot_Installer.bat new file mode 100644 index 0000000..d05d347 --- /dev/null +++ b/Build_StockBot_Installer.bat @@ -0,0 +1,6 @@ +@echo off +setlocal +cd /d "%~dp0" +powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0scripts\build_installer.ps1" %* +echo. +pause diff --git a/INSTALL_FROM_PACKAGE.md b/INSTALL_FROM_PACKAGE.md new file mode 100644 index 0000000..0be66e6 --- /dev/null +++ b/INSTALL_FROM_PACKAGE.md @@ -0,0 +1,51 @@ +# StockBot v3 Install Package + +This package is built by `scripts/build_installer.ps1` from committed Git +contents only. It intentionally excludes secrets, runtime databases, logs, and +local lock files. + +## Install After Windows Reformat + +1. Extract the package to the target folder, for example: + `C:\Users\\Documents\stockbot_v3` +2. Restore private runtime files from your backup: + - `.env` + - `data\stockbot.db` + - optional: `data\daily_context.json`, `data\midday_context.json` +3. Run `Restore_StockBot.bat` as Administrator. +4. Keep `KIS_MOCK=true` and `DRY_RUN=true` until the restored environment has + passed connection and scheduler checks. + +## What Restore_StockBot.bat Does + +- Creates required folders. +- Installs Git, Node.js, and Python 3.11 with winget when available. +- Creates `.venv`. +- Installs Python dependencies, using `vendor\wheels` first. +- Installs Claude/Codex CLI when npm is available. +- Registers Windows Task Scheduler jobs unless skipped. +- Runs a basic Python dependency sanity check. + +## Useful Options + +```powershell +.\Restore_StockBot.bat -SkipWinget +.\Restore_StockBot.bat -SkipScheduler +.\Restore_StockBot.bat -OnlinePip +``` + +## Build A Package + +From the project root: + +```powershell +.\Build_StockBot_Installer.bat +``` + +or: + +```powershell +powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\build_installer.ps1 +``` + +The generated archive and manifest are written to `dist\`. diff --git a/scripts/build_installer.ps1 b/scripts/build_installer.ps1 new file mode 100644 index 0000000..6ec2ac3 --- /dev/null +++ b/scripts/build_installer.ps1 @@ -0,0 +1,104 @@ +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