Files
diodeinc__pcb/install.ps1
Lenny Khazan 6efd247cae feat(pcb): add native KiCad URL launcher (#983)
* feat(pcb): add native KiCad URL launcher

* fix(pcb): harden launcher recovery choices

* fix(pcb): prevent concurrent recovery sessions

* fix(pcb): guard restored editor sessions

* refactor(pcb): extract shared pcb-diode-uri and pcb-native-dialog crates

pcb-launcher's URI validation re-implemented pcb-diode-api's SandboxFileUri
parsing; move that parser into a tiny pcb-diode-uri crate both can use, and
give the trusted-host allowlist a single home there. Likewise collapse the
duplicated osascript/zenity/kdialog/PowerShell dialog machinery from
pcb-launcher and pcbc's recovery dialog into a pcb-native-dialog crate.
Also drop the launcher's redundant staged-app cleanup (the Drop guard
covers it), the duplicate log chmod, the Debug-formatted log header, and
a clippy for_kv_map lint in the interposer pattern test.

* fix(pcb): block recovery while a recoverable session's editor is open

A recoverable stop now deliberately leaves KiCad running, so the
still-open-editor guard must cover Recoverable sessions too — otherwise
Restore reuses the same local layout dir while the first KiCad instance
still has it open. Also match the tracked pid's process name (open /
pcbnew / kicad) instead of bare liveness, so a recycled pid cannot
permanently wedge the board.

* refactor(pcb): simplify launcher install and open plumbing

Split install_shim_launcher into fetch / stage / replace helpers so the
Windows backup-rename dance is a reusable replace_executable_with_backup,
fold pcb-kicad's duplicated per-OS pcbnew command construction into one
builder, share a single Download-style helper in install.ps1 the way
install.sh already does, dedupe the recovery-cancel wind-down, and fix
the README's launcher wording.

* refactor(pcb): re-export diode URI types without a module alias

Nothing consumed the pcb_diode_api::diode_uri path; re-export the types
directly from pcb-diode-uri instead of aliasing the whole crate.

* refactor(pcb): trust *.diode.computer in release, all hosts in debug

Replaces the enumerated host allowlist: release launchers accept any
*.diode.computer subdomain (portless, so preview and gov endpoints work
without listing them), while debug builds trust every host so local API
stacks need no special-casing.
2026-08-26 10:46:19 -04:00

121 lines
4.3 KiB
PowerShell

$ErrorActionPreference = "Stop"
$baseUrl = "https://pcb.api.diode.computer/pcb"
$installDir = $env:PCB_INSTALL_DIR
if (-not $installDir) {
$installDir = Join-Path $env:USERPROFILE ".pcb\bin"
}
if ($env:PROCESSOR_ARCHITECTURE -ne "AMD64") {
throw "unsupported platform: Windows $env:PROCESSOR_ARCHITECTURE"
}
function Add-InstallDirToPath($dir) {
if ($env:GITHUB_PATH) {
Add-Content -Path $env:GITHUB_PATH -Value $dir
}
$registry = "registry::HKEY_CURRENT_USER\Environment"
$current = (Get-Item -LiteralPath $registry).GetValue("Path", "", "DoNotExpandEnvironmentNames")
$entries = $current -split ";" | Where-Object { $_ }
if ($entries -contains $dir) {
return
}
$newPath = (@($dir) + $entries) -join ";"
Set-ItemProperty -Type ExpandString -LiteralPath $registry Path $newPath
$name = "pcb-path-update-" + [guid]::NewGuid().ToString()
[Environment]::SetEnvironmentVariable($name, "1", "User")
[Environment]::SetEnvironmentVariable($name, $null, "User")
Write-Host "Added $dir to PATH. Restart your terminal or run: `$env:Path = `"$dir;`$env:Path`""
}
$latest = Invoke-RestMethod "$baseUrl/pcb-latest.json"
$zstd = Get-Command zstd -ErrorAction SilentlyContinue
$tmp = New-Item -ItemType Directory -Path (Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName()))
# Download and checksum-verify one release binary into $tmp, preferring the
# zstd-compressed artifact when zstd is available. Returns the local path.
function Get-ReleaseBinary($name) {
$artifact = "$name-x86_64-pc-windows-msvc.exe"
$binary = Join-Path $tmp "$name.exe"
$sum = Join-Path $tmp "$name.exe.sha256"
Invoke-WebRequest "$baseUrl/$($latest.tag)/$artifact.sha256" -OutFile $sum
$downloadedCompressed = $false
if ($zstd) {
$compressedPath = Join-Path $tmp "$name.exe.zst"
try {
Invoke-WebRequest "$baseUrl/$($latest.tag)/$artifact.zst" -OutFile $compressedPath
$downloadedCompressed = $true
} catch {
$downloadedCompressed = $false
}
}
if ($downloadedCompressed) {
& $zstd.Source -q -d -f $compressedPath -o $binary
if ($LASTEXITCODE -ne 0) {
Remove-Item -Force -ErrorAction SilentlyContinue $binary
Invoke-WebRequest "$baseUrl/$($latest.tag)/$artifact" -OutFile $binary
}
} else {
Invoke-WebRequest "$baseUrl/$($latest.tag)/$artifact" -OutFile $binary
}
$expected = ((Get-Content $sum -Raw) -split "\s+")[0].ToLowerInvariant()
$actual = (Get-FileHash -Algorithm SHA256 $binary).Hash.ToLowerInvariant()
if ($actual -ne $expected) {
throw "$name checksum mismatch"
}
return $binary
}
try {
$binary = Get-ReleaseBinary "pcb"
$launcherBinary = $null
try {
$launcherBinary = Get-ReleaseBinary "pcb-launcher"
} catch {
Write-Warning "Skipping optional pcb-launcher for $($latest.tag): $_"
}
New-Item -ItemType Directory -Force $installDir | Out-Null
$installedPcb = Join-Path $installDir "pcb.exe"
$installedLauncher = Join-Path $installDir "pcb-launcher.exe"
Move-Item -Force $binary $installedPcb
if ($launcherBinary) {
try {
Move-Item -Force $launcherBinary $installedLauncher
} catch {
$launcherBinary = $null
Write-Warning "Installed pcb, but could not install the Diode URL launcher: $_"
}
}
if ($launcherBinary) {
# pcb-launcher uses the Windows GUI subsystem, so invoke it through a
# process handle to wait for registration and read the correct exit code.
try {
$launcherInstall = Start-Process -FilePath $installedLauncher -ArgumentList "--install --toolchain latest" -Wait -PassThru
if ($launcherInstall.ExitCode -ne 0) {
Write-Warning "Installed pcb, but could not register the Diode URL launcher. See $HOME\.pcb\pcb-launcher.log for details"
}
} catch {
Write-Warning "Installed pcb, but could not register the Diode URL launcher: $_"
}
}
Add-InstallDirToPath $installDir
Write-Host "Installed pcb to $installedPcb"
if ($launcherBinary) {
Write-Host "Installed Diode URL launcher to $installedLauncher"
}
} finally {
Remove-Item -Recurse -Force $tmp -ErrorAction SilentlyContinue
}