From 2ccd7a055381455c4f73d2eaf60e2cffc76cf3f6 Mon Sep 17 00:00:00 2001 From: Kaustav Ghosh Date: Sun, 28 Jun 2026 00:42:20 +0530 Subject: [PATCH] fix: bugfix and refactor Windows start script Review pass over scripts/start-windows.ps1: Bugs - Add `dart pub get` in backend/ before `dart_frog build` (fresh checkouts failed with unresolved deps). - Replace fixed `Start-Sleep -Seconds 3` with port polling (Wait-ForPort) and exit if the backend never starts listening. - Pass `-s ` to `adb reverse` (was ambiguous/failing with multiple devices attached). - Scope and restore `$env:PORT` so it no longer leaks into the session. Refactor - Dedupe device detection into a single Get-ConnectedAndroidDevice helper. - Hoist magic values into a param() block (-Port, -Avd) + SDK path vars. - Use Push-Location/Pop-Location with try/finally around the backend build. - Stay PowerShell 5.1 compatible (avoid Start-Process -Environment). Co-Authored-By: Claude Opus 4.8 --- scripts/start-windows.ps1 | 177 ++++++++++++++++++++++++++------------ 1 file changed, 121 insertions(+), 56 deletions(-) diff --git a/scripts/start-windows.ps1 b/scripts/start-windows.ps1 index 0c8591d..089cb2d 100644 --- a/scripts/start-windows.ps1 +++ b/scripts/start-windows.ps1 @@ -1,23 +1,80 @@ <# .SYNOPSIS -Starts the Familiarise application on Windows. +Starts the Familiarise application on Windows (full rebuild). + +.DESCRIPTION +Mirrors scripts/start-android.sh for Windows/PowerShell: + 1. Frees port 8080 + 2. Cleans + rebuilds Flutter and regenerates code + 3. Builds and starts the Dart Frog backend + 4. Ensures an Android device/emulator is available, sets up adb reverse + 5. Runs the Flutter app on the target device + +.PARAMETER Port +Backend port (default 8080). + +.PARAMETER Avd +Android Virtual Device name to launch when no device is connected (default Pixel_10). + +.EXAMPLE +.\scripts\start-windows.ps1 -Avd Pixel_7_API_34 #> +param( + [int]$Port = 8080, + [string]$Avd = "Pixel_10" +) $ErrorActionPreference = "Stop" -# Get the script directory and navigate to the project root +# Resolve project root from the script location and move there. $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path -Set-Location "$scriptDir\.." - -Write-Host "=== Killing processes on port 8080 ===" -ForegroundColor Cyan -$port8080Pids = (Get-NetTCPConnection -LocalPort 8080 -ErrorAction SilentlyContinue).OwningProcess -if ($port8080Pids) { - foreach ($pidToKill in $port8080Pids) { - Stop-Process -Id $pidToKill -Force -ErrorAction SilentlyContinue - Write-Host "Killed process $pidToKill on port 8080" +$projectRoot = Resolve-Path "$scriptDir\.." +Set-Location $projectRoot + +# Android SDK tool locations. +$sdkRoot = Join-Path $env:LOCALAPPDATA "Android\Sdk" +$adbExe = Join-Path $sdkRoot "platform-tools\adb.exe" +$emulatorExe = Join-Path $sdkRoot "emulator\emulator.exe" + +# --- Helpers ----------------------------------------------------------------- + +# Returns the id of the first fully-booted ("device" state) Android device, +# or $null if none are attached. Skips the "List of devices attached" header. +function Get-ConnectedAndroidDevice { + if (-not (Test-Path $adbExe)) { return $null } + $line = & $adbExe devices | + Select-Object -Skip 1 | + Where-Object { $_ -match '\bdevice$' } | + Select-Object -First 1 + if ($line) { return ($line -split '\s+')[0] } + return $null +} + +# Blocks until $Port accepts a TCP connection or the timeout elapses. +function Wait-ForPort { + param([int]$PortNumber, [int]$TimeoutSeconds = 30) + $deadline = (Get-Date).AddSeconds($TimeoutSeconds) + while ((Get-Date) -lt $deadline) { + if (Test-NetConnection -ComputerName "localhost" -Port $PortNumber -WarningAction SilentlyContinue -InformationLevel Quiet) { + return $true + } + Start-Sleep -Milliseconds 500 } + return $false +} + +# --- Free the backend port --------------------------------------------------- + +Write-Host "=== Killing processes on port $Port ===" -ForegroundColor Cyan +$portPids = (Get-NetTCPConnection -LocalPort $Port -ErrorAction SilentlyContinue).OwningProcess | + Sort-Object -Unique +foreach ($pidToKill in $portPids) { + Stop-Process -Id $pidToKill -Force -ErrorAction SilentlyContinue + Write-Host "Killed process $pidToKill on port $Port" } +# --- Flutter clean + codegen ------------------------------------------------- + Write-Host "=== Cleaning Flutter build ===" -ForegroundColor Cyan flutter clean @@ -27,77 +84,85 @@ flutter pub get Write-Host "=== Regenerating code ===" -ForegroundColor Cyan dart run build_runner build --delete-conflicting-outputs +# --- Backend build ----------------------------------------------------------- + Write-Host "=== Building backend ===" -ForegroundColor Cyan -Set-Location backend +Push-Location backend +try { + if (-not (Test-Path ".env")) { + Write-Host "WARNING: backend/.env not found! Copying .env.example to .env..." -ForegroundColor Yellow + Copy-Item ".env.example" ".env" + Write-Host "Please make sure to fill in your database credentials in backend/.env if needed." -ForegroundColor Yellow + } -if (-not (Test-Path ".env")) { - Write-Host "WARNING: backend/.env not found! Copying .env.example to .env..." -ForegroundColor Yellow - Copy-Item ".env.example" ".env" - Write-Host "Please make sure to fill in your database credentials in backend/.env if needed." -ForegroundColor Yellow + dart pub get + dart pub global run dart_frog_cli:dart_frog build + + Write-Host "=== Starting backend server ===" -ForegroundColor Cyan + # Set PORT for the child process (inherited from this session), then restore + # it so the variable doesn't leak. Avoids Start-Process -Environment, which + # requires PowerShell 7.4+ (Windows ships 5.1 by default). + $prevPort = $env:PORT + $env:PORT = "$Port" + try { + $serverProc = Start-Process dart ` + -ArgumentList "build/bin/server.dart" ` + -NoNewWindow -PassThru + } + finally { + $env:PORT = $prevPort + } + Write-Host "Backend server started (PID $($serverProc.Id))" +} +finally { + Pop-Location } - -dart pub global run dart_frog_cli:dart_frog build - -Write-Host "=== Starting backend server ===" -ForegroundColor Cyan -$env:PORT = "8080" -Start-Process dart -ArgumentList "build/bin/server.dart" -NoNewWindow -Set-Location .. Write-Host "=== Waiting for backend to start ===" -ForegroundColor Cyan -Start-Sleep -Seconds 3 - -$adbExe = "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe" -$deviceConnected = $false - -if (Test-Path $adbExe) { - $devices = & $adbExe devices - $connectedDevices = $devices | Where-Object { $_ -match '\bdevice$' } - if ($connectedDevices) { - $deviceConnected = $true - Write-Host "=== Device already connected ===" -ForegroundColor Green - Write-Host "Skipping emulator launch." - } +if (-not (Wait-ForPort -PortNumber $Port)) { + Write-Host "Backend did not start listening on port $Port in time." -ForegroundColor Red + exit 1 } +Write-Host "Backend is up on port $Port." -ForegroundColor Green + +# --- Ensure an Android device is available ----------------------------------- -if (-not $deviceConnected) { +$targetDevice = Get-ConnectedAndroidDevice + +if ($targetDevice) { + Write-Host "=== Device already connected ($targetDevice) ===" -ForegroundColor Green + Write-Host "Skipping emulator launch." +} else { Write-Host "=== Starting Android emulator ===" -ForegroundColor Cyan - $emulatorExe = "$env:LOCALAPPDATA\Android\Sdk\emulator\emulator.exe" if (Test-Path $emulatorExe) { - # You can change Pixel_10 to whatever your emulator AVD name is - Write-Host "Starting Pixel_10 emulator..." - Start-Process $emulatorExe -ArgumentList "-avd Pixel_10" -NoNewWindow - + Write-Host "Starting $Avd emulator..." + Start-Process $emulatorExe -ArgumentList "-avd", $Avd -NoNewWindow + Write-Host "=== Waiting for emulator to boot ===" -ForegroundColor Cyan if (Test-Path $adbExe) { & $adbExe wait-for-device Start-Sleep -Seconds 5 + $targetDevice = Get-ConnectedAndroidDevice } } else { Write-Host "Could not find emulator at $emulatorExe. Please ensure an emulator is running." -ForegroundColor Yellow } } -if (Test-Path $adbExe) { +# --- Port forwarding --------------------------------------------------------- + +if ($targetDevice) { Write-Host "=== Setting up port forwarding ===" -ForegroundColor Cyan - & $adbExe reverse tcp:8080 tcp:8080 + & $adbExe -s $targetDevice reverse "tcp:$Port" "tcp:$Port" } else { - Write-Host "Could not find adb at $adbExe. Skipping port forwarding." -ForegroundColor Yellow + Write-Host "No Android device detected. Skipping port forwarding." -ForegroundColor Yellow } -Write-Host "=== Running Flutter app ===" -ForegroundColor Cyan - -# Try to find a connected physical Android device ID -$targetDevice = $null -if (Test-Path $adbExe) { - $adbDevices = & $adbExe devices | Select-Object -Skip 1 - $physicalDevice = $adbDevices | Where-Object { $_ -match '\bdevice$' } | Select-Object -First 1 - if ($physicalDevice) { - $targetDevice = ($physicalDevice -split '\s+')[0] - Write-Host "Targeting device: $targetDevice" -ForegroundColor Green - } -} +# --- Run the app ------------------------------------------------------------- +Write-Host "=== Running Flutter app ===" -ForegroundColor Cyan if ($targetDevice) { + Write-Host "Targeting device: $targetDevice" -ForegroundColor Green flutter run -d $targetDevice } else { flutter run