diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c84e232..4c62aba 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -193,36 +193,48 @@ jobs: run: | New-Item -ItemType Directory -Force -Path release-artifacts + # Ensure we're using PowerShell 7+ with better ZIP support + $PSVersionTable.PSVersion + # Use generic naming - semantic-release will rename when uploading $version = "latest" # Create Windows scripts archive - Compress-Archive -Path ` - scripts/windows/*.ps1, ` - setup-machine.ps1, ` - README.md, ` - LICENSE ` - -DestinationPath "release-artifacts/devMachine-windows-scripts-$version.zip" -Force + $windowsFiles = @( + Get-ChildItem -Path "scripts/windows" -Filter "*.ps1" + Get-Item -Path "setup-machine.ps1" + Get-Item -Path "README.md" + Get-Item -Path "LICENSE" + ) + Compress-Archive -LiteralPath $windowsFiles.FullName ` + -DestinationPath "release-artifacts/devMachine-windows-scripts-$version.zip" ` + -CompressionLevel Optimal -Force # Create WSL scripts archive - Compress-Archive -Path ` - scripts/wsl/*.sh, ` - README.md, ` - LICENSE ` - -DestinationPath "release-artifacts/devMachine-wsl-scripts-$version.zip" -Force - - # Create complete archive - Compress-Archive -Path ` - scripts/, ` - tests/, ` - setup-machine.ps1, ` - README.md, ` - LICENSE, ` - SECURITY.md, ` - CONTRIBUTING.md, ` - CODE_OF_CONDUCT.md, ` - CHANGELOG.md ` - -DestinationPath "release-artifacts/devMachine-complete-$version.zip" -Force + $wslFiles = @( + Get-ChildItem -Path "scripts/wsl" -Filter "*.sh" + Get-Item -Path "README.md" + Get-Item -Path "LICENSE" + ) + Compress-Archive -LiteralPath $wslFiles.FullName ` + -DestinationPath "release-artifacts/devMachine-wsl-scripts-$version.zip" ` + -CompressionLevel Optimal -Force + + # Create complete archive with proper structure + $completeFiles = @( + "scripts" + "tests" + "setup-machine.ps1" + "README.md" + "LICENSE" + "SECURITY.md" + "CONTRIBUTING.md" + "CODE_OF_CONDUCT.md" + "CHANGELOG.md" + ) + Compress-Archive -Path $completeFiles ` + -DestinationPath "release-artifacts/devMachine-complete-$version.zip" ` + -CompressionLevel Optimal -Force # Generate checksums Set-Location release-artifacts diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f603f0..d2e4083 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [1.8.1](https://github.com/kpeacocke/devMachine/compare/v1.8.0...v1.8.1) (2025-11-12) + + +### šŸ› Bug Fixes + +* **10-windows-bootstrap.ps1:** update Ubuntu installation command to use default version and improve user instructions ([bb121c3](https://github.com/kpeacocke/devMachine/commit/bb121c375d30502b81daa73a134b90a047a92230)) + + +### ā™»ļø Code Refactoring + +* **doctor-ubuntu.sh:** improve readability by restructuring conditional checks for tool availability ([bdaee0b](https://github.com/kpeacocke/devMachine/commit/bdaee0bcc5afc18bf65bde17814b9fb83be0e6df)) + ## [1.8.0](https://github.com/kpeacocke/devMachine/compare/v1.7.0...v1.8.0) (2025-11-12) diff --git a/scripts/windows/10-windows-bootstrap.ps1 b/scripts/windows/10-windows-bootstrap.ps1 index d2227ba..6e8c18d 100644 --- a/scripts/windows/10-windows-bootstrap.ps1 +++ b/scripts/windows/10-windows-bootstrap.ps1 @@ -127,11 +127,11 @@ winget install Docker.DockerDesktop --source winget --silent --accept-package-ag Write-Host "🐧 Ubuntu for WSL" if (-not $skipWSL) { - # Install Ubuntu 24.04 LTS (latest) - winget install Canonical.Ubuntu.2404 --source winget --silent --accept-package-agreements --accept-source-agreements + # Install Ubuntu (default/latest version) + winget install Canonical.Ubuntu --source winget --silent --accept-package-agreements --accept-source-agreements # Set WSL 2 as default wsl --set-default-version 2 - Write-Host " Note: Launch 'Ubuntu 24.04 LTS' from Start Menu to complete first-time setup" -ForegroundColor Yellow + Write-Host " Note: Launch 'Ubuntu' from Start Menu to complete first-time setup" -ForegroundColor Yellow } else { Write-Host " → Skipped (WSL not installed)" -ForegroundColor Yellow } diff --git a/scripts/windows/41-devdrive-partition-setup.ps1 b/scripts/windows/41-devdrive-partition-setup.ps1 index b9b4b2f..3d78856 100644 --- a/scripts/windows/41-devdrive-partition-setup.ps1 +++ b/scripts/windows/41-devdrive-partition-setup.ps1 @@ -10,8 +10,17 @@ ReFS requires a minimum of 2GB per partition. The script automatically adjusts sizes to meet these requirements while ensuring 30% free space remains on C:. + PARTITION DETECTION: + The script detects existing Dev Drive partitions by their filesystem labels (DevCache, DevCode). + If partitions exist but are not mounted (e.g., after OS reinstall), the script will mount them + instead of creating new ones. This prevents duplicate partitions and preserves data. + .EXAMPLE .\scripts\windows\41-devdrive-partition-setup.ps1 + +.NOTES + After wiping/reinstalling Windows, existing Dev Drive partitions remain on disk but unmounted. + This script intelligently detects them by label and remounts them rather than creating duplicates. #> #Requires -RunAsAdministrator $ErrorActionPreference = 'Stop' @@ -206,29 +215,58 @@ if ($confirm -ne 'Y') { exit 0 } -# Check if mount points already exist +# Define mount points +$cacheMountPoint = "C:\DevCache" +$codeMountPoint = "C:\Users\$env:USERNAME\code" + +Write-Host "`nšŸ” Detecting existing Dev Drive partitions..." -ForegroundColor Cyan + +# Look for existing unmounted partitions by label (survives OS reinstalls) +$existingCachePartition = $null +$existingCodePartition = $null + +$allVolumes = Get-Volume | Where-Object { $_.FileSystem -eq 'ReFS' -and $_.FileSystemLabel -in @('DevCache', 'DevCode') } +foreach ($vol in $allVolumes) { + if ($vol.FileSystemLabel -eq 'DevCache') { + $existingCachePartition = $vol + Write-Host " Found existing DevCache partition: $([math]::Round($vol.Size / 1GB, 2)) GB (ReFS)" -ForegroundColor Yellow + } elseif ($vol.FileSystemLabel -eq 'DevCode') { + $existingCodePartition = $vol + Write-Host " Found existing DevCode partition: $([math]::Round($vol.Size / 1GB, 2)) GB (ReFS)" -ForegroundColor Yellow + } +} + +# Check if mount points already exist and have volumes mounted $cacheMountPoint = "C:\DevCache" $codeMountPoint = "C:\Users\$env:USERNAME\code" # Check if cache mount point exists and has a volume mounted $cacheExists = $false +$cacheMounted = $false if (Test-Path $cacheMountPoint) { $cacheVolume = Get-Volume | Where-Object { $_.Path -eq "$cacheMountPoint\" } if ($cacheVolume) { - Write-Host "āœ… Cache Dev Drive already exists at $cacheMountPoint" -ForegroundColor Green + Write-Host "āœ… Cache Dev Drive already mounted at $cacheMountPoint" -ForegroundColor Green Write-Host " Size: $([math]::Round($cacheVolume.Size / 1GB, 2)) GB, FileSystem: $($cacheVolume.FileSystem)" -ForegroundColor Gray $cacheExists = $true + $cacheMounted = $true } +} elseif ($existingCachePartition) { + Write-Host " Cache partition exists but not mounted - will mount it" -ForegroundColor Yellow + $cacheExists = $true + $cacheMounted = $false } # Check if code mount point exists and has a volume mounted $codeExists = $false +$codeMounted = $false if (Test-Path $codeMountPoint) { $codeVolume = Get-Volume | Where-Object { $_.Path -eq "$codeMountPoint\" } if ($codeVolume) { - Write-Host "āœ… Code Dev Drive already exists at $codeMountPoint" -ForegroundColor Green + Write-Host "āœ… Code Dev Drive already mounted at $codeMountPoint" -ForegroundColor Green Write-Host " Size: $([math]::Round($codeVolume.Size / 1GB, 2)) GB, FileSystem: $($codeVolume.FileSystem)" -ForegroundColor Gray $codeExists = $true + $codeMounted = $true } else { # Check if it's a regular directory with contents $items = Get-ChildItem $codeMountPoint -ErrorAction SilentlyContinue @@ -237,11 +275,15 @@ if (Test-Path $codeMountPoint) { Write-Host " This appears to be a regular directory, not a Dev Drive mount point" -ForegroundColor Gray } } +} elseif ($existingCodePartition) { + Write-Host " Code partition exists but not mounted - will mount it" -ForegroundColor Yellow + $codeExists = $true + $codeMounted = $false } -# Only skip ALL disk operations if BOTH mount points exist with volumes -if ($cacheExists -and $codeExists) { - Write-Host "šŸŽ‰ Both Dev Drive mount points already exist - no disk changes needed!" -ForegroundColor Green +# Only skip ALL operations if BOTH are already mounted +if ($cacheMounted -and $codeMounted) { + Write-Host "`nšŸŽ‰ Both Dev Drive mount points already exist and mounted - no changes needed!" -ForegroundColor Green Write-Host " Cache: $cacheMountPoint" -ForegroundColor Gray Write-Host " Code: $codeMountPoint" -ForegroundColor Gray Write-Host "šŸ“ Next Steps:" -ForegroundColor Cyan @@ -251,19 +293,26 @@ if ($cacheExists -and $codeExists) { exit 0 } -# Determine what needs to be created -if ($cacheExists) { - Write-Host "šŸ“ Cache Dev Drive exists, will only create code partition" -ForegroundColor Cyan +# Determine what needs to be created vs mounted +Write-Host "" +if ($cacheExists -and -not $cacheMounted) { + Write-Host "šŸ“ Cache Dev Drive partition exists - will mount it" -ForegroundColor Cyan + $skipCachePartition = $true # Skip creation, just mount +} elseif ($cacheMounted) { + Write-Host "šŸ“ Cache Dev Drive already mounted - skipping" -ForegroundColor Cyan $skipCachePartition = $true } else { - Write-Host "šŸ“ Cache Dev Drive missing, will create it" -ForegroundColor Cyan + Write-Host "šŸ“ Cache Dev Drive missing - will create and mount it" -ForegroundColor Cyan } -if ($codeExists) { - Write-Host "šŸ“ Code Dev Drive exists, will only create cache partition" -ForegroundColor Cyan +if ($codeExists -and -not $codeMounted) { + Write-Host "šŸ“ Code Dev Drive partition exists - will mount it" -ForegroundColor Cyan + $skipCodePartition = $true # Skip creation, just mount +} elseif ($codeMounted) { + Write-Host "šŸ“ Code Dev Drive already mounted - skipping" -ForegroundColor Cyan $skipCodePartition = $true } else { - Write-Host "šŸ“ Code Dev Drive missing, will create it" -ForegroundColor Cyan + Write-Host "šŸ“ Code Dev Drive missing - will create and mount it" -ForegroundColor Cyan } Write-Host "šŸ”§ Starting partition operations..." -ForegroundColor Cyan @@ -351,105 +400,161 @@ if (-not $skipCachePartition) { } # Step 3: Create Code partition -Write-Host "[3/5] Creating Code Dev Drive partition ($codePartitionGB GB)..." -ForegroundColor Yellow -try { - # Check available free space on disk first - $diskFreeSpace = Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3} | Measure-Object -Property FreeSpace -Sum - $availableSpaceGB = [math]::Floor($diskFreeSpace.Sum / 1GB) - - # Check for largest available extent on the disk - $maxExtent = Get-Disk -Number $disk.Number | Get-PartitionSupportedSize - $maxSizeBytes = if ($maxExtent.SizeMax -is [array]) { $maxExtent.SizeMax[0] } else { $maxExtent.SizeMax } - $maxAvailableGB = [math]::Floor($maxSizeBytes / 1GB) - - Write-Host " Available disk space: $availableSpaceGB GB, Max extent: $maxAvailableGB GB" -ForegroundColor Gray - - if ($maxAvailableGB -lt $codePartitionGB) { - Write-Host " āš ļø Insufficient contiguous space for $codePartitionGB GB partition" -ForegroundColor Yellow - $adjustedCodeGB = [math]::Max(5, [math]::Floor($maxAvailableGB * 0.8)) # Use 80% of available, minimum 5GB - Write-Host " Adjusting code partition to $adjustedCodeGB GB" -ForegroundColor Yellow - $codePartitionGB = $adjustedCodeGB - } +if (-not $skipCodePartition) { + Write-Host "`n[3/5] Creating Code Dev Drive partition ($codePartitionGB GB)..." -ForegroundColor Yellow + try { + # Check available free space on disk first + $diskFreeSpace = Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3} | Measure-Object -Property FreeSpace -Sum + $availableSpaceGB = [math]::Floor($diskFreeSpace.Sum / 1GB) - $codeSize = $codePartitionGB * 1GB - $codePartition = New-Partition -DiskNumber $disk.Number -Size $codeSize -AssignDriveLetter - $codeDriveLetter = $codePartition.DriveLetter + # Check for largest available extent on the disk + $maxExtent = Get-Disk -Number $disk.Number | Get-PartitionSupportedSize + $maxSizeBytes = if ($maxExtent.SizeMax -is [array]) { $maxExtent.SizeMax[0] } else { $maxExtent.SizeMax } + $maxAvailableGB = [math]::Floor($maxSizeBytes / 1GB) - Write-Host " Formatting as ReFS (Dev Drive)..." -ForegroundColor Gray - Format-Volume -DriveLetter $codeDriveLetter -FileSystem ReFS -NewFileSystemLabel "DevCode" -DevDrive -Confirm:$false | Out-Null + Write-Host " Available disk space: $availableSpaceGB GB, Max extent: $maxAvailableGB GB" -ForegroundColor Gray - Write-Host " āœ… Code partition created as $codeDriveLetter`: ($codePartitionGB GB)" -ForegroundColor Green -} catch { - Write-Host " āŒ Failed to create code partition: $_" -ForegroundColor Red - Write-Host " Trying to create with maximum available space..." -ForegroundColor Yellow - try { - # Try with maximum available space - $maxSizeInfo = Get-Disk -Number $disk.Number | Get-PartitionSupportedSize - $maxSize = if ($maxSizeInfo.SizeMax -is [array]) { $maxSizeInfo.SizeMax[0] } else { $maxSizeInfo.SizeMax } - if ($maxSize -gt 2GB) { - $fallbackSize = [math]::Min($maxSize, 5GB) # Max 5GB fallback - $codePartition = New-Partition -DiskNumber $disk.Number -Size $fallbackSize -AssignDriveLetter - $codeDriveLetter = $codePartition.DriveLetter - Format-Volume -DriveLetter $codeDriveLetter -FileSystem ReFS -NewFileSystemLabel "DevCode" -DevDrive -Confirm:$false | Out-Null - $codePartitionGB = [math]::Round($fallbackSize / 1GB, 1) - Write-Host " āœ… Code partition created as $codeDriveLetter`: ($codePartitionGB GB)" -ForegroundColor Green - } else { - Write-Host " āŒ Not enough space for any code partition" -ForegroundColor Red - $skipCodePartition = $true + if ($maxAvailableGB -lt $codePartitionGB) { + Write-Host " āš ļø Insufficient contiguous space for $codePartitionGB GB partition" -ForegroundColor Yellow + $adjustedCodeGB = [math]::Max(5, [math]::Floor($maxAvailableGB * 0.8)) # Use 80% of available, minimum 5GB + Write-Host " Adjusting code partition to $adjustedCodeGB GB" -ForegroundColor Yellow + $codePartitionGB = $adjustedCodeGB } + + $codeSize = $codePartitionGB * 1GB + $codePartition = New-Partition -DiskNumber $disk.Number -Size $codeSize -AssignDriveLetter + $codeDriveLetter = $codePartition.DriveLetter + + Write-Host " Formatting as ReFS (Dev Drive)..." -ForegroundColor Gray + Format-Volume -DriveLetter $codeDriveLetter -FileSystem ReFS -NewFileSystemLabel "DevCode" -DevDrive -Confirm:$false | Out-Null + + Write-Host " āœ… Code partition created as $codeDriveLetter`: ($codePartitionGB GB)" -ForegroundColor Green } catch { - Write-Host " āŒ Fallback partition creation also failed: $_" -ForegroundColor Red - $skipCodePartition = $true + Write-Host " āŒ Failed to create code partition: $_" -ForegroundColor Red + Write-Host " Trying to create with maximum available space..." -ForegroundColor Yellow + try { + # Try with maximum available space + $maxSizeInfo = Get-Disk -Number $disk.Number | Get-PartitionSupportedSize + $maxSize = if ($maxSizeInfo.SizeMax -is [array]) { $maxSizeInfo.SizeMax[0] } else { $maxSizeInfo.SizeMax } + if ($maxSize -gt 2GB) { + $fallbackSize = [math]::Min($maxSize, 5GB) # Max 5GB fallback + $codePartition = New-Partition -DiskNumber $disk.Number -Size $fallbackSize -AssignDriveLetter + $codeDriveLetter = $codePartition.DriveLetter + Format-Volume -DriveLetter $codeDriveLetter -FileSystem ReFS -NewFileSystemLabel "DevCode" -DevDrive -Confirm:$false | Out-Null + $codePartitionGB = [math]::Round($fallbackSize / 1GB, 1) + Write-Host " āœ… Code partition created as $codeDriveLetter`: ($codePartitionGB GB)" -ForegroundColor Green + } else { + Write-Host " āŒ Not enough space for any code partition" -ForegroundColor Red + $skipCodePartition = $true + } + } catch { + Write-Host " āŒ Fallback partition creation also failed: $_" -ForegroundColor Red + $skipCodePartition = $true + } } +} else { + Write-Host "`n[3/5] Skipping code partition creation (already exists)" -ForegroundColor Yellow } # Step 4: Mount Cache partition -if (-not $skipCachePartition) { +if (-not $cacheMounted) { Write-Host "`n[4/5] Mounting cache partition at $cacheMountPoint..." -ForegroundColor Yellow try { if (-not (Test-Path $cacheMountPoint)) { New-Item -ItemType Directory -Path $cacheMountPoint -Force | Out-Null } - # Remove drive letter and mount to folder - Remove-PartitionAccessPath -DiskNumber $disk.Number -PartitionNumber $cachePartition.PartitionNumber -AccessPath "$cacheDriveLetter`:\" - Add-PartitionAccessPath -DiskNumber $disk.Number -PartitionNumber $cachePartition.PartitionNumber -AccessPath "$cacheMountPoint\" - - Write-Host " āœ… Cache partition mounted at $cacheMountPoint" -ForegroundColor Green + # If we have an existing partition, find and mount it + if ($existingCachePartition -and -not $cachePartition) { + Write-Host " Mounting existing DevCache partition..." -ForegroundColor Gray + # Find the partition by matching the volume + $allPartitions = Get-Partition | Where-Object { $_.DriveLetter -or $_.AccessPaths } + foreach ($part in $allPartitions) { + $vol = Get-Volume -Partition $part -ErrorAction SilentlyContinue + if ($vol -and $vol.FileSystemLabel -eq 'DevCache') { + # Remove existing drive letter if present + if ($part.DriveLetter) { + Remove-PartitionAccessPath -DiskNumber $part.DiskNumber -PartitionNumber $part.PartitionNumber -AccessPath "$($part.DriveLetter):\" -ErrorAction SilentlyContinue + } + # Mount to folder + Add-PartitionAccessPath -DiskNumber $part.DiskNumber -PartitionNumber $part.PartitionNumber -AccessPath "$cacheMountPoint\" + Write-Host " āœ… Existing cache partition mounted at $cacheMountPoint" -ForegroundColor Green + break + } + } + } elseif ($cachePartition) { + # Mounting newly created partition + Remove-PartitionAccessPath -DiskNumber $disk.Number -PartitionNumber $cachePartition.PartitionNumber -AccessPath "$cacheDriveLetter`:\" -ErrorAction SilentlyContinue + Add-PartitionAccessPath -DiskNumber $disk.Number -PartitionNumber $cachePartition.PartitionNumber -AccessPath "$cacheMountPoint\" + Write-Host " āœ… Cache partition mounted at $cacheMountPoint" -ForegroundColor Green + } } catch { Write-Host " āŒ Failed to mount cache partition: $_" -ForegroundColor Red - Write-Host " Partition exists as $cacheDriveLetter`: but not mounted" -ForegroundColor Yellow + if ($cacheDriveLetter) { + Write-Host " Partition exists as $cacheDriveLetter`: but not mounted" -ForegroundColor Yellow + } } +} else { + Write-Host "`n[4/5] Cache partition already mounted - skipping" -ForegroundColor Yellow } # Step 5: Mount Code partition -if (-not $skipCodePartition) { +if (-not $codeMounted) { Write-Host "`n[5/5] Mounting code partition at $codeMountPoint..." -ForegroundColor Yellow try { if (-not (Test-Path $codeMountPoint)) { New-Item -ItemType Directory -Path $codeMountPoint -Force | Out-Null } - # Remove drive letter and mount to folder - Remove-PartitionAccessPath -DiskNumber $disk.Number -PartitionNumber $codePartition.PartitionNumber -AccessPath "$codeDriveLetter`:\" - Add-PartitionAccessPath -DiskNumber $disk.Number -PartitionNumber $codePartition.PartitionNumber -AccessPath "$codeMountPoint\" - - Write-Host " āœ… Code partition mounted at $codeMountPoint" -ForegroundColor Green + # If we have an existing partition, find and mount it + if ($existingCodePartition -and -not $codePartition) { + Write-Host " Mounting existing DevCode partition..." -ForegroundColor Gray + # Find the partition by matching the volume + $allPartitions = Get-Partition | Where-Object { $_.DriveLetter -or $_.AccessPaths } + foreach ($part in $allPartitions) { + $vol = Get-Volume -Partition $part -ErrorAction SilentlyContinue + if ($vol -and $vol.FileSystemLabel -eq 'DevCode') { + # Remove existing drive letter if present + if ($part.DriveLetter) { + Remove-PartitionAccessPath -DiskNumber $part.DiskNumber -PartitionNumber $part.PartitionNumber -AccessPath "$($part.DriveLetter):\" -ErrorAction SilentlyContinue + } + # Mount to folder + Add-PartitionAccessPath -DiskNumber $part.DiskNumber -PartitionNumber $part.PartitionNumber -AccessPath "$codeMountPoint\" + Write-Host " āœ… Existing code partition mounted at $codeMountPoint" -ForegroundColor Green + break + } + } + } elseif ($codePartition) { + # Mounting newly created partition + Remove-PartitionAccessPath -DiskNumber $disk.Number -PartitionNumber $codePartition.PartitionNumber -AccessPath "$codeDriveLetter`:\" -ErrorAction SilentlyContinue + Add-PartitionAccessPath -DiskNumber $disk.Number -PartitionNumber $codePartition.PartitionNumber -AccessPath "$codeMountPoint\" + Write-Host " āœ… Code partition mounted at $codeMountPoint" -ForegroundColor Green + } else { + # Fallback: create regular directory if partition creation was skipped/failed + Write-Host " No code partition available - creating regular directory" -ForegroundColor Yellow + if (-not (Test-Path $codeMountPoint)) { + New-Item -ItemType Directory -Path $codeMountPoint -Force | Out-Null + Write-Host " āœ… Created $codeMountPoint as regular directory" -ForegroundColor Green + } + } } catch { Write-Host " āŒ Failed to mount code partition: $_" -ForegroundColor Red - Write-Host " Partition exists as $codeDriveLetter`: but not mounted" -ForegroundColor Yellow - } -} else { - Write-Host "`n[5/5] Skipping code partition mount (creation failed)" -ForegroundColor Yellow - Write-Host " Creating regular directory for code instead..." -ForegroundColor Gray - try { - if (-not (Test-Path $codeMountPoint)) { - New-Item -ItemType Directory -Path $codeMountPoint -Force | Out-Null - Write-Host " āœ… Created regular directory at $codeMountPoint" -ForegroundColor Green + if ($codeDriveLetter) { + Write-Host " Partition exists as $codeDriveLetter`: but not mounted" -ForegroundColor Yellow + } + # Fallback: create regular directory + Write-Host " Creating regular directory for code instead..." -ForegroundColor Gray + try { + if (-not (Test-Path $codeMountPoint)) { + New-Item -ItemType Directory -Path $codeMountPoint -Force | Out-Null + Write-Host " āœ… Created $codeMountPoint as regular directory" -ForegroundColor Green + } + } catch { + Write-Host " āŒ Failed to create code directory: $_" -ForegroundColor Red } - } catch { - Write-Host " āŒ Failed to create code directory: $_" -ForegroundColor Red } +} else { + Write-Host "`n[5/5] Code partition already mounted - skipping" -ForegroundColor Yellow } # Verify setup diff --git a/scripts/wsl/doctor-ubuntu.sh b/scripts/wsl/doctor-ubuntu.sh index 7f16958..a90435b 100644 --- a/scripts/wsl/doctor-ubuntu.sh +++ b/scripts/wsl/doctor-ubuntu.sh @@ -38,27 +38,63 @@ if need composer; then bad "Composer global bin NOT on PATH" fi for t in phpcs phpstan psalm php-cs-fixer; do - if command -v "$t" >/dev/null 2>&1; then ok "$t found"; else bad "$t missing"; fi + if command -v "$t" >/dev/null 2>&1; then + ok "$t found" + else + bad "$t missing" + fi done -else bad "Composer missing"; fi +else + bad "Composer missing" +fi -if need ruby; then ok "Ruby found"; else bad "Ruby missing"; fi +if need ruby; then + ok "Ruby found" +else + bad "Ruby missing" +fi for g in bundler rubocop; do - if need "$g"; then ok "$g found"; else bad "$g missing"; fi + if need "$g"; then + ok "$g found" + else + bad "$g missing" + fi done -if need node && need npm; then ok "Node & npm found"; else bad "Node/npm missing"; fi +if need node && need npm; then + ok "Node & npm found" +else + bad "Node/npm missing" +fi for n in eslint prettier markdownlint stylelint tsc; do - if need "$n"; then ok "$n found"; else bad "$n missing"; fi + if need "$n"; then + ok "$n found" + else + bad "$n missing" + fi done if need docker; then - if docker info >/dev/null 2>&1; then ok "Docker CLI works (WSL integration)"; else bad "Docker CLI cannot reach daemon — enable WSL integration in Docker Desktop"; fi -else bad "docker missing"; fi + if docker info >/dev/null 2>&1; then + ok "Docker CLI works (WSL integration)" + else + bad "Docker CLI cannot reach daemon — enable WSL integration in Docker Desktop" + fi +else + bad "docker missing" +fi -if need tflint; then ok "tflint found"; else bad "tflint missing"; fi +if need tflint; then + ok "tflint found" +else + bad "tflint missing" +fi -if need shellcheck; then ok "shellcheck found"; else bad "shellcheck missing"; fi +if need shellcheck; then + ok "shellcheck found" +else + bad "shellcheck missing" +fi echo ok "Doctor check finished" diff --git a/setup-machine.ps1 b/setup-machine.ps1 index dc47a1d..5004c4b 100644 --- a/setup-machine.ps1 +++ b/setup-machine.ps1 @@ -11,6 +11,8 @@ Skip backup configuration (File History, System Protection) .PARAMETER SkipLicensedApps + Skip commercial/licensed applications (1Password, Office, GitKraken, Beyond Compare, + Scrivener, Obsidian, Backblaze, Malwarebytes, GlassWire). Skip commercial/licensed applications (1Password, Office, GitKraken, Beyond Compare, Scrivener, Obsidian, Backblaze, Malwarebytes, GlassWire). Use this for VMs or when you don't have licenses. @@ -169,13 +171,16 @@ function Invoke-Script { [hashtable]$Arguments = @{} ) + Write-Step $Description + if (-not (Test-Path $Path)) { Write-Warning "Script not found: $Path - SKIPPING" return } + try { if ($Arguments.Count -gt 0) { & $Path @Arguments @@ -360,8 +365,7 @@ if (-not $SkipLicensedApps) { Write-Host "šŸ’° Commercial/Licensed Applications" -ForegroundColor Yellow Write-Host " These require paid licenses or subscriptions" -ForegroundColor Yellow Write-Host " Estimated cost: ~$315-505 first year, ~$205-395/year after`n" -ForegroundColor Yellow - $installLicensed = Read-Host "Install licensed apps? (Y/N) [Default: N]" - if ([string]::IsNullOrWhiteSpace($installLicensed)) { $installLicensed = 'N' } + $installLicensed = Read-Host "Install licensed apps? (Y/N) [Recommended: N for VMs]" if ($installLicensed -eq 'Y') { Write-Step "PHASE 2.5: Licensed Applications" @@ -649,22 +653,14 @@ if (-not $SkipBackup) { # ============================================================================ if (-not $SkipInsiders) { - Write-Host "āš ļø Insider Programs Setup (Office & VS Code)" -ForegroundColor Yellow - Write-Host " This will configure Office Beta and VS Code Insiders" -ForegroundColor Yellow - Write-Host " āš ļø Windows Insider enrollment has been removed (too unreliable)" -ForegroundColor Yellow - - if ($UnattendedMode) { - Write-Host "šŸ¤– Unattended mode: Skipping Insider channels (use -SkipInsiders to avoid this message)" -ForegroundColor Yellow - $insider = 'N' - } else { - $insider = Read-Host " Enable Insider channels (Office/VS Code)? (Y/N) [Default: N]" - if ([string]::IsNullOrWhiteSpace($insider)) { $insider = 'N' } - } + Write-Host "`nāš ļø Windows Insider Program Setup" -ForegroundColor Yellow + Write-Host " This will configure Canary/Dev channels for Windows, Office, and VS Code" -ForegroundColor Yellow + $insider = Read-Host " Enable Insider channels? (Y/N)" if ($insider -eq 'Y') { Write-Step "PHASE 10: Insider Channels (Office & VS Code)" Invoke-Script -Path (Join-Path $WindowsScripts "70-insiders-optin.ps1") ` - -Description "Office Beta, VS Code Insiders (Windows Insider removed)" + -Description "Windows Canary, Office Beta, VS Code Insiders" Invoke-Script -Path (Join-Path $WindowsScripts "72-vscode-insiders-setup.ps1") ` -Description "VS Code Insiders profile and extensions" @@ -685,6 +681,7 @@ try { if ($ubuntuStatus) { Write-Host "āœ… Ubuntu is installed" -ForegroundColor Green + # Test if Ubuntu has been initialized wsl -d Ubuntu -e whoami 2>&1 | Out-Null if ($LASTEXITCODE -ne 0) { @@ -700,12 +697,15 @@ try { } } + Write-Step "PHASE 11: Ubuntu Bootstrap" Write-Host "Copying Ubuntu bootstrap script to WSL..." -ForegroundColor Cyan + $ubuntuBootstrap = Join-Path $WSLScripts "20-ubuntu-bootstrap.sh" $ubuntuTune = Join-Path $WSLScripts "21-wsl-tune.sh" + # Copy scripts to WSL wsl -d Ubuntu -e mkdir -p /tmp/setup wsl -d Ubuntu -e cp (Resolve-Path $ubuntuBootstrap).Path /tmp/setup/ @@ -713,15 +713,18 @@ try { wsl -d Ubuntu -e chmod +x /tmp/setup/20-ubuntu-bootstrap.sh wsl -d Ubuntu -e chmod +x /tmp/setup/21-wsl-tune.sh + Write-Host "Running Ubuntu bootstrap (this will take 15-30 minutes)..." -ForegroundColor Cyan wsl -d Ubuntu -e bash /tmp/setup/20-ubuntu-bootstrap.sh + Write-Host "`nRunning WSL tune-ups..." -ForegroundColor Cyan wsl -d Ubuntu -e bash /tmp/setup/21-wsl-tune.sh + Write-Host "āœ… Ubuntu setup complete" -ForegroundColor Green - Write-Host "āš ļø Shutting down WSL to apply .wslconfig changes..." -ForegroundColor Yellow + Write-Host "`nāš ļø Shutting down WSL to apply .wslconfig changes..." -ForegroundColor Yellow wsl --shutdown Write-Host "āœ… WSL shutdown complete. It will restart automatically when needed." -ForegroundColor Green }