Last active
February 29, 2024 02:37
-
-
Save JustinGrote/dc432cb4d4410fa0c190613c3e8e4db5 to your computer and use it in GitHub Desktop.
Powershell Bootstrap script for VSCode Server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#require -version 5.1 | |
#Usage: iwr https://tinyurl.com/VSCodeServer | iex | |
#Parameterized usage: & ([ScriptBlock]::Create((iwr https://tinyurl.com/VSCodeServer))) -Your -Options | |
param( | |
#Path to install the vscode binary to. This defaults to a folder in your Local AppData path. Must be writable by your current user without sudo | |
[ValidateNotNullOrEmpty()] | |
[string]$InstallPath = $(Join-Path -Path ([System.Environment]::GetFolderPath('LocalApplicationData')) -ChildPath 'vscode-cli'), | |
#Installation architecture. This is normally autodetected. | |
$Arch, | |
$OS, | |
[ValidateSet('stable', 'insider')] | |
[ValidateNotNullOrEmpty()] | |
$Build = 'stable', | |
#Path to find the vscode server launcher. You normally dont need to change. | |
[ValidateNotNullOrEmpty()] | |
$InstallUri = 'https://code.visualstudio.com/sha/download', | |
#Normally this script will use the existing detected code server or vscode instance. Specify to force a new install. | |
[Switch]$Force, | |
#This script typically starts code-server automatically upon run. Specify to prevent that behavior | |
[switch]$InstallOnly, | |
#This script updates the path to include code-server so it can be specified again. Specify to prevent that behavior | |
[switch]$NoUpdatePath, | |
#Additional arguments to pass to code --tunnel, such as if you want to customize the name of the tunnel | |
[string[]]$ArgumentList, | |
#By default this uses GitHub for auth, specify this to use MS | |
[switch]$UseMicrosoftLogin | |
) | |
$ErrorActionPreference = 'Stop' | |
if (-not $OS) { | |
#Polyfill for 5.1 | |
if ($null -eq $IsWindows) { | |
$IsWindows = $true | |
} | |
$OS = switch ($true) { | |
$IsWindows { 'win32' } | |
$IsLinux { 'alpine' } | |
$IsMacOS { 'darwin' } | |
default { throw [NotSupportedException]'This platform is not supported by this script.' } | |
} | |
} | |
if (-not $Arch) { | |
if ($OS -eq 'win32') { | |
if (-not $Arch) { | |
$Arch = switch ($ENV:PROCESSOR_ARCHITECTURE) { | |
'AMD64' { 'x64' } | |
'ARM64' { 'arm64' } | |
default { throw [NotSupportedException]'Unknown Windows Architecture, this is either a bug or you are trying to install on an x86 machine' } | |
} | |
} | |
} elseif ($isLinux -or $isMacOS) { | |
$arch = switch (uname -m) { | |
'x86_64' { 'x64' } | |
'aarch64' { 'arm64' } | |
'armv7l' { 'arm32' } | |
default { throw [NotSupportedException]'Unknown Linux Architecture, please specify x64, arm32, or arm64 for the Arch parameter of this command' } | |
} | |
} else { | |
throw [NotSupportedException]'This platform is not supported by this script.' | |
} | |
} | |
$Body = @{ | |
'build' = $Build | |
'os' = "cli-$OS-$Arch" | |
} | |
$OutBin = if ($IsWindows) { 'code-cli.exe' } else { 'code-cli' } | |
$CodeCliPath = Join-Path -Path $InstallPath -ChildPath $OutBin | |
if ((Test-Path $CodeCliPath) -and -not $Force) { | |
Write-Verbose "Found existing vscode CLI at $CodeCliPath" | |
$LocalInstallFound = $true | |
$OutBinPath = $CodeCliPath | |
} else { | |
Write-Verbose 'No vscode CLI install found or -Force specified, checking for existing vscode installations' | |
if ($Force) { | |
Write-Verbose '-Force Specified, skipping vscode binary detection' | |
} else { | |
$VSCodePath = foreach ($command in 'code-insiders', 'code') { | |
$candidatePath = (Get-Command $command -CommandType Application -ErrorAction Ignore) | | |
Select-Object -First 1 | | |
ForEach-Object Source | |
if ($candidatePath) { | |
Write-Verbose "Found existing vscode binary at $candidatePath" | |
$candidatePath | |
break | |
} | |
} | |
if ($VSCodePath) { | |
Write-Verbose "VSCode detected at $VSCodePath" | |
$OutBinPath = $VSCodePath | |
$LocalInstallFound = $true | |
} else { | |
Write-Verbose 'No existing vscode installation found' | |
} | |
} | |
Write-Host -Fore Magenta "Local Install Found: $LocalInstallFound" | |
if (-not $LocalInstallFound) { | |
$OutBinPath = $CodeCliPath | |
Write-Verbose "Downloading vscode $OS $Arch from $BaseUri" | |
#Prep the target folder if it doesn't exist and download the binary | |
New-Item -ItemType Directory -Force -Path $InstallPath | Out-Null | |
if ($IsWindows) { | |
#Improves download performance on 5.1 | |
$lastProgressPreference = $ProgressPreference | |
$ProgressPreference = 'SilentlyContinue' | |
} | |
$zipTempPath = [System.IO.Path]::GetTempPath() + [System.IO.Path]::GetRandomFileName() + '.zip' | |
try { | |
Invoke-WebRequest -Method GET -UseBasicParsing -Body $Body -Uri $InstallUri -OutFile $zipTempPath | |
Expand-Archive -Path $zipTempPath -DestinationPath $InstallPath -Force | |
$cliFileName = if ($IsWindows) { 'code.exe' } else { 'code' } | |
Move-Item (Join-Path $InstallPath $cliFileName) $OutBinPath -Force | |
} finally { | |
Remove-Item $zipTempPath -ErrorAction Ignore | |
} | |
if (-not $isWindows) { | |
& chmod +x $OutBinPath | |
} | |
if ($IsWindows) { | |
$ProgressPreference = $lastProgressPreference | |
} | |
Write-Verbose "Downloaded code server to $OutBinPath" | |
if (-not $NoUpdatePath) { | |
$Paths = [Environment]::GetEnvironmentVariable('Path', 'User') -split [io.path]::PathSeparator | |
if ($InstallPath -notin $Paths) { | |
Write-Verbose "PATH variable already contains $InstallPath, skipping..." | |
} else { | |
Write-Verbose "Updating PATH to include $InstallPath" | |
} | |
[string]$newPathVar = "$InstallPath" + [io.path]::PathSeparator + [Environment]::GetEnvironmentVariable('Path', 'User') | |
[Environment]::SetEnvironmentVariable('Path', $newPathVar, 'User') | |
} | |
} | |
if (-not (Test-Path $OutBinPath)) { | |
throw [InvalidOperationException]'Failed to find or install vscode binary' | |
} | |
} | |
if (-not $InstallOnly) { | |
Write-Verbose "Starting $OutBinPath in current path $PWD" | |
if ($UseMicrosoftLogin) { | |
Write-Verbose "-UseMicrosoftLogin specified, starting $OutBinPath with --auth-provider=Microsoft" | |
$codeCliParams = @( | |
'tunnel' | |
'login' | |
'--provider' | |
'microsoft' | |
) | |
& $OutBinPath @codeCliParams | |
if ((& $OutBinPath tunnel user show) -ne 'logged in') { | |
throw [InvalidOperationException]'Failed to log in to Microsoft' | |
} | |
} | |
$codeCliParams = @( | |
'tunnel' | |
'--accept-server-license-terms' | |
) | |
& $OutBinPath @codeCliParams @ArgumentList | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment