W
dbosoft/windevdrive/1.2
configure
Architecture: any
Architecture: any
name: configure
variables:
# Where the dev drive goes - set devdrive_disk, devdrive_location or both:
# devdrive_disk: an empty eryph drive of the catlet (e.g. sdb) that becomes the dev drive;
# if it can't be used, the dev drive goes to devdrive_location
- name: devdrive_disk
value: ""
required: false
# Former name of devdrive_disk, still accepted
- name: devdrive_name
value: ""
required: false
# devdrive_location: an existing volume (e.g. C) that hosts the dev drive,
# either as VHD file (devdrive_type vhd) or in space shrunk off the volume (resize)
- name: devdrive_location
value: ""
required: false
- name: devdrive_type
value: "vhd"
required: false
# Size in GB for devdrive_location (Microsoft's minimum for a dev drive is 50 GB)
- name: devdrive_size
value: "50"
required: false
- name: devdrive_letter
value: "E"
required: false
- name: devdrive_label
value: "DevDrive"
required: false
fodder:
- name: configure-devdrive
type: shellscript
filename: configure-devdrive.ps1
content: |
Write-Host "=== Configuring Dev Drive ==="
$eryphDriveName = "{{ devdrive_disk }}".Trim()
if (-not $eryphDriveName) { $eryphDriveName = "{{ devdrive_name }}".Trim() }
$location = "{{ devdrive_location }}".Trim().TrimEnd(':', '\')
$type = "{{ devdrive_type }}".Trim().ToLower()
$sizeGB = [int]"{{ devdrive_size }}"
$driveLetter = "{{ devdrive_letter }}".Trim().TrimEnd(':')
$driveLabel = "{{ devdrive_label }}"
# Dev Drive requires Windows 11 Build 22621.2338 or later; older builds get a ReFS volume
$osBuild = [int](Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").CurrentBuildNumber
$devDriveSupported = $osBuild -ge 22621
Write-Host "Windows Build: $osBuild - Dev Drive supported: $devDriveSupported"
function Get-DevDrivePartition {
Get-Partition -DriveLetter $driveLetter -ErrorAction SilentlyContinue
}
# Checks the dedicated eryph drive (sda = Disk 0, sdb = Disk 1, ...).
# Returns the disk, or throws why it can't hold the dev drive.
function Get-EryphDisk {
if ($eryphDriveName -notmatch '^sd([a-h])$') {
throw "'$eryphDriveName' is not an eryph drive name (sdb, sdc, ...)"
}
$diskNumber = [int][char]$Matches[1] - [int][char]'a'
$disk = Get-Disk -Number $diskNumber -ErrorAction SilentlyContinue
if (-not $disk) { throw "eryph drive '$eryphDriveName' (Disk $diskNumber) not found; add it to the catlet's drives" }
Write-Host "Eryph drive '$eryphDriveName' is Disk ${diskNumber}: $([Math]::Round($disk.Size / 1GB, 2)) GB, $($disk.PartitionStyle)"
if ($disk.PartitionStyle -ne 'RAW') {
# Running again (e.g. after a reboot): accept the disk when it already
# carries the dev drive volume
$existing = Get-DevDrivePartition
if (-not ($existing -and $existing.DiskNumber -eq $diskNumber)) {
throw "Disk $diskNumber is already initialized (PartitionStyle: $($disk.PartitionStyle)); a dev drive needs an empty disk"
}
}
return $disk
}
# Prepares the disk/space and creates the partition $driveLetter.
# Returns $true when the partition was created now, $false when it exists already.
function New-DevDrivePartition {
if ($eryphDriveName) {
$disk = $null
try {
$disk = Get-EryphDisk
} catch {
if (-not $location) { throw }
Write-Host "WARNING: $_ - using devdrive_location $location instead"
}
if ($disk) {
if ($disk.PartitionStyle -ne 'RAW') { return $false }
Initialize-Disk -Number $disk.Number -PartitionStyle GPT -ErrorAction Stop
New-Partition -DiskNumber $disk.Number -UseMaximumSize -DriveLetter $driveLetter -ErrorAction Stop | Out-Null
return $true
}
}
if (-not $location) {
throw "Set devdrive_disk (an eryph drive) or devdrive_location (an existing volume, e.g. C)"
}
$sizeBytes = [int64]$sizeGB * 1GB
if ($type -eq 'vhd') {
# Like the Windows settings page: a dynamically expanding VHDX on the volume
$vhdPath = "${location}:\DevDrives\$driveLabel.vhdx"
if (-not (Test-Path $vhdPath)) {
New-Item -ItemType Directory -Path (Split-Path $vhdPath -Parent) -Force | Out-Null
Write-Host "Creating $sizeGB GB VHDX at $vhdPath..."
$script = Join-Path $env:TEMP 'devdrive-diskpart.txt'
Set-Content -Path $script -Encoding ASCII -Value "create vdisk file=`"$vhdPath`" maximum=$($sizeGB * 1024) type=expandable"
$output = diskpart /s $script 2>&1
Remove-Item $script -Force
if ($LASTEXITCODE -ne 0) { throw "diskpart failed: $output" }
}
$image = Get-DiskImage -ImagePath $vhdPath
if (-not $image.Attached) {
$image = Mount-DiskImage -ImagePath $vhdPath -PassThru -ErrorAction Stop
}
$disk = $image | Get-Disk
# Windows doesn't attach a VHD again after a reboot; a startup task does
$action = New-ScheduledTaskAction -Execute 'powershell.exe' `
-Argument "-NoProfile -NonInteractive -Command `"Mount-DiskImage -ImagePath '$vhdPath' -ErrorAction SilentlyContinue`""
Register-ScheduledTask -TaskName "Mount Dev Drive $driveLabel" -Action $action `
-Trigger (New-ScheduledTaskTrigger -AtStartup) -User 'SYSTEM' -RunLevel Highest -Force | Out-Null
if ($disk.PartitionStyle -ne 'RAW') {
if (Get-DevDrivePartition) { return $false }
throw "$vhdPath is already initialized but has no ${driveLetter}: volume"
}
Initialize-Disk -Number $disk.Number -PartitionStyle GPT -ErrorAction Stop
New-Partition -DiskNumber $disk.Number -UseMaximumSize -DriveLetter $driveLetter -ErrorAction Stop | Out-Null
return $true
}
if ($type -eq 'resize') {
if (Get-DevDrivePartition) { return $false }
# Like "resize an existing volume": shrink it and use the freed space
$source = Get-Partition -DriveLetter $location -ErrorAction Stop
$supported = Get-PartitionSupportedSize -DiskNumber $source.DiskNumber -PartitionNumber $source.PartitionNumber
$newSize = $source.Size - $sizeBytes
if ($newSize -lt $supported.SizeMin) {
throw "${location}: can shrink by at most $([Math]::Floor(($source.Size - $supported.SizeMin) / 1GB)) GB, $sizeGB GB requested"
}
Write-Host "Shrinking ${location}: by $sizeGB GB..."
Resize-Partition -DiskNumber $source.DiskNumber -PartitionNumber $source.PartitionNumber -Size $newSize -ErrorAction Stop
New-Partition -DiskNumber $source.DiskNumber -UseMaximumSize -DriveLetter $driveLetter -ErrorAction Stop | Out-Null
return $true
}
throw "Unsupported devdrive_type '$type' (vhd or resize)"
}
try {
$created = New-DevDrivePartition
} catch {
Write-Host "ERROR: $_"
exit 1
}
if ($created) {
if ($devDriveSupported) {
Write-Host "Formatting ${driveLetter}: as Dev Drive..."
$formatResult = cmd /c "format ${driveLetter}: /devdrv /q /y /v:$driveLabel" 2>&1
Write-Host $formatResult
if ($LASTEXITCODE -ne 0) {
# /devdrv needs 22621.2338 or later; older 22621 builds reject it
Write-Host "Dev Drive format failed (exit code $LASTEXITCODE), formatting as ReFS instead..."
$devDriveSupported = $false
}
}
if (-not $devDriveSupported) {
Write-Host "Formatting ${driveLetter}: as ReFS..."
$formatResult = cmd /c "format ${driveLetter}: /fs:ReFS /q /y /v:$driveLabel" 2>&1
Write-Host $formatResult
}
if ($LASTEXITCODE -ne 0) {
Write-Host "ERROR: format failed with exit code $LASTEXITCODE"
exit 1
}
} else {
Write-Host "${driveLetter}: exists already - skipping partitioning and format"
}
$volume = Get-Volume -DriveLetter $driveLetter -ErrorAction SilentlyContinue
if (-not $volume) {
Write-Host "ERROR: volume ${driveLetter}: not found"
exit 1
}
Write-Host "Volume ${driveLetter}: $($volume.FileSystem), $([Math]::Round($volume.Size / 1GB, 2)) GB, label $($volume.FileSystemLabel)"
# Only configure Dev Drive trust on Windows 11 with Dev Drive support
if ($devDriveSupported) {
# Mark the Dev Drive as trusted
Write-Host "Marking Dev Drive as trusted..."
$trustCmd = "fsutil devdrv trust ${driveLetter}:"
Write-Host "Running: $trustCmd"
$trustResult = cmd /c $trustCmd 2>&1
Write-Host $trustResult
# Query Dev Drive status
Write-Host ""
Write-Host "Querying Dev Drive status..."
$queryCmd = "fsutil devdrv query ${driveLetter}:"
$queryResult = cmd /c $queryCmd 2>&1
Write-Host $queryResult
} else {
Write-Host "Dev Drive trust configuration skipped (not supported on this Windows version)"
Write-Host "ReFS volume created at ${driveLetter}: will still provide improved performance for development"
}
Write-Host ""
Write-Host "=== Setting System-Wide Environment Variables ==="
# Create directories for package caches
$directories = @(
"${driveLetter}:\.nuget\packages",
"${driveLetter}:\npm-cache",
"${driveLetter}:\pip-cache",
"${driveLetter}:\maven-cache",
"${driveLetter}:\gradle-cache",
"${driveLetter}:\cargo-cache",
"${driveLetter}:\vcpkg-cache"
)
foreach ($dir in $directories) {
if (-not (Test-Path $dir)) {
New-Item -ItemType Directory -Path $dir -Force | Out-Null
Write-Host "Created: $dir"
}
}
# Set SYSTEM-WIDE environment variables
# These will apply to all users and services
$envVars = @{
"NUGET_PACKAGES" = "${driveLetter}:\.nuget\packages"
"npm_config_cache" = "${driveLetter}:\npm-cache"
"PIP_CACHE_DIR" = "${driveLetter}:\pip-cache"
"MAVEN_OPTS" = "-Dmaven.repo.local=${driveLetter}:\maven-cache"
"GRADLE_USER_HOME" = "${driveLetter}:\gradle-cache"
"CARGO_HOME" = "${driveLetter}:\cargo-cache"
"VCPKG_DEFAULT_BINARY_CACHE" = "${driveLetter}:\vcpkg-cache"
}
foreach ($key in $envVars.Keys) {
$value = $envVars[$key]
Write-Host "Setting $key = $value"
[System.Environment]::SetEnvironmentVariable($key, $value, [System.EnvironmentVariableTarget]::Machine)
}
Write-Host ""
Write-Host "=== Creating Developer Workspace ==="
# Create standard development directories
$workspaceDirs = @(
"${driveLetter}:\source",
"${driveLetter}:\source\repos",
"${driveLetter}:\source\projects",
"${driveLetter}:\tools",
"${driveLetter}:\temp"
)
foreach ($dir in $workspaceDirs) {
if (-not (Test-Path $dir)) {
New-Item -ItemType Directory -Path $dir -Force | Out-Null
Write-Host "Created workspace: $dir"
}
}
Write-Host ""
if ($devDriveSupported) {
Write-Host "=== Dev Drive Configuration Complete ==="
Write-Host "Dev Drive is ready at ${driveLetter}:"
Write-Host "- Trusted for development"
Write-Host "- Package caches configured (system-wide)"
Write-Host "- Developer workspace created"
Write-Host ""
Write-Host "To verify Dev Drive status, run: fsutil devdrv query ${driveLetter}:"
} else {
Write-Host "=== ReFS Development Drive Configuration Complete ==="
Write-Host "ReFS development drive is ready at ${driveLetter}:"
Write-Host "- Fast ReFS filesystem for development"
Write-Host "- Package caches configured (system-wide)"
Write-Host "- Developer workspace created"
Write-Host ""
Write-Host "Note: Full Dev Drive features require Windows 11 Build 22621+"
}
Write-Host "To see package cache paths, run: Get-ChildItem Env: | Where-Object { `$_.Name -like '*PACKAGE*' -or `$_.Name -like '*cache*' }"