mirror of
https://github.com/Tencent/BrowserSkill.git
synced 2026-09-10 13:01:23 +08:00
fix(installer): correct Windows paths and release checks
This commit is contained in:
+29
-22
@@ -3,7 +3,7 @@
|
|||||||
install.ps1 — install the bsk CLI on Windows from GitHub Releases.
|
install.ps1 — install the bsk CLI on Windows from GitHub Releases.
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Downloads the latest (or pinned) bsk release for Windows x64 or ARM64,
|
Downloads the latest (or pinned) bsk release for Windows x64,
|
||||||
extracts bsk.exe to a user-local directory, and adds it to PATH.
|
extracts bsk.exe to a user-local directory, and adds it to PATH.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
@@ -73,25 +73,21 @@ function Add-ToUserPath {
|
|||||||
|
|
||||||
$currentUserPath = @([Environment]::GetEnvironmentVariable("PATH", "User") -split ";" | Where-Object { $_ })
|
$currentUserPath = @([Environment]::GetEnvironmentVariable("PATH", "User") -split ";" | Where-Object { $_ })
|
||||||
|
|
||||||
if ($currentUserPath -contains $Dir) {
|
$newUserPath = (@($Dir) + @($currentUserPath | Where-Object { $_ -ine $Dir })) -join ";"
|
||||||
Write-Log "$Dir is already in your user PATH"
|
if (($currentUserPath -join ";") -ceq $newUserPath) {
|
||||||
|
Write-Log "$Dir is already first in your user PATH"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$newUserPath = ($currentUserPath + $Dir) -join ";"
|
|
||||||
[Environment]::SetEnvironmentVariable("PATH", $newUserPath, "User")
|
[Environment]::SetEnvironmentVariable("PATH", $newUserPath, "User")
|
||||||
Write-Log "added ${Dir} to user PATH"
|
Write-Log "placed ${Dir} first in user PATH"
|
||||||
}
|
}
|
||||||
|
|
||||||
function Add-ToSessionPath {
|
function Add-ToSessionPath {
|
||||||
param([string]$Dir)
|
param([string]$Dir)
|
||||||
|
|
||||||
$pathEntries = $env:PATH -split ";" | Where-Object { $_ }
|
$pathEntries = @($env:PATH -split ";" | Where-Object { $_ -and $_ -ine $Dir })
|
||||||
if ($pathEntries -contains $Dir) {
|
$env:PATH = (@($Dir) + $pathEntries) -join ";"
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
$env:PATH = "$Dir;$env:PATH"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Git Bash (bash environment) PATH helper ──────────────────────────────────
|
# ── Git Bash (bash environment) PATH helper ──────────────────────────────────
|
||||||
@@ -173,14 +169,20 @@ function Main {
|
|||||||
Write-Log "latest version is ${version}"
|
Write-Log "latest version is ${version}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$platformKey = $platform.PlatformKey
|
||||||
|
$asset = $null
|
||||||
|
if ($manifest -and $manifest.assets) {
|
||||||
|
$asset = $manifest.assets.$platformKey
|
||||||
|
}
|
||||||
|
# ARM64 is not in the current release matrix. Require a published entry
|
||||||
|
# before attempting it, while preserving legacy x64 installs without a manifest.
|
||||||
|
if ($platform.ArchId -eq "arm64" -and -not $asset) {
|
||||||
|
Write-Die "version.json does not list a Windows ARM64 package for bsk $version"
|
||||||
|
}
|
||||||
|
|
||||||
$archiveName = "bsk-v${version}-$($platform.TargetTriple).zip"
|
$archiveName = "bsk-v${version}-$($platform.TargetTriple).zip"
|
||||||
$downloadUrl = "${GitHub}/releases/download/${tag}/${archiveName}"
|
$downloadUrl = "${GitHub}/releases/download/${tag}/${archiveName}"
|
||||||
|
$expectedSha = if ($asset) { $asset.sha256 } else { $null }
|
||||||
$expectedSha = $null
|
|
||||||
$platformKey = $platform.PlatformKey
|
|
||||||
if ($manifest -and $manifest.assets) {
|
|
||||||
$expectedSha = $manifest.assets.$platformKey.sha256
|
|
||||||
}
|
|
||||||
if (-not $expectedSha) {
|
if (-not $expectedSha) {
|
||||||
if (-not $manifest) {
|
if (-not $manifest) {
|
||||||
Write-Log "warning: could not fetch version.json; skipping checksum verification"
|
Write-Log "warning: could not fetch version.json; skipping checksum verification"
|
||||||
@@ -201,7 +203,7 @@ function Main {
|
|||||||
|
|
||||||
if ($expectedSha) {
|
if ($expectedSha) {
|
||||||
Write-Log "verifying checksum"
|
Write-Log "verifying checksum"
|
||||||
$actualSha = (Get-FileHash -Algorithm SHA256 -Path $archivePath).Hash
|
$actualSha = (Get-FileHash -Algorithm SHA256 -LiteralPath $archivePath).Hash
|
||||||
if ($actualSha -ieq $expectedSha) {
|
if ($actualSha -ieq $expectedSha) {
|
||||||
Write-Log "checksum OK"
|
Write-Log "checksum OK"
|
||||||
}
|
}
|
||||||
@@ -211,13 +213,13 @@ function Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Write-Log "extracting ${archiveName}"
|
Write-Log "extracting ${archiveName}"
|
||||||
Expand-Archive -Path $archivePath -DestinationPath $tempDir -Force
|
Expand-Archive -LiteralPath $archivePath -DestinationPath $tempDir -Force
|
||||||
|
|
||||||
if (-not (Test-Path (Join-Path $tempDir "bsk.exe"))) {
|
if (-not (Test-Path -LiteralPath (Join-Path $tempDir "bsk.exe"))) {
|
||||||
Write-Die "bsk.exe not found in archive"
|
Write-Die "bsk.exe not found in archive"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $InstallDir)) {
|
if (-not (Test-Path -LiteralPath $InstallDir)) {
|
||||||
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,12 +241,17 @@ function Main {
|
|||||||
& $bskPath --version
|
& $bskPath --version
|
||||||
if ($LASTEXITCODE -ne 0) { throw "installed bsk failed verification" }
|
if ($LASTEXITCODE -ne 0) { throw "installed bsk failed verification" }
|
||||||
|
|
||||||
|
$command = Get-Command bsk -ErrorAction SilentlyContinue
|
||||||
|
if (-not $command -or $command.CommandType -ne "Application" -or $command.Source -ine $bskPath) {
|
||||||
|
Write-Log "warning: 'bsk' does not resolve to $bskPath; check Get-Command bsk -All for a conflicting command"
|
||||||
|
}
|
||||||
|
|
||||||
Write-Log "done"
|
Write-Log "done"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "Open a new terminal (PowerShell / Git Bash) for PATH changes to take full effect."
|
Write-Host "Open a new terminal (PowerShell / Git Bash) for PATH changes to take full effect."
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
|
Remove-Item -LiteralPath $tempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#Requires -Version 5.1
|
#Requires -Version 5.1
|
||||||
param(
|
param(
|
||||||
[string]$BskPath = (Join-Path $PSScriptRoot "../target/debug/bsk.exe"),
|
[string]$BskPath = (Join-Path $PSScriptRoot "../target/debug/bsk.exe"),
|
||||||
[switch]$ArchitectureOnly
|
[switch]$HelpersOnly
|
||||||
)
|
)
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
# Load definitions, never Main: no downloads or changes to the real user PATH.
|
# Load definitions without running Main. Registry PATH writes are isolated below.
|
||||||
$installer = Join-Path $PSScriptRoot "../install.ps1"
|
$installer = Join-Path $PSScriptRoot "../install.ps1"
|
||||||
$tokens = $null
|
$tokens = $null
|
||||||
$errors = $null
|
$errors = $null
|
||||||
@@ -69,22 +69,38 @@ function Assert-Fails([scriptblock]$Action) {
|
|||||||
$env:PROCESSOR_ARCHITEW6432 = $oldNativeArch
|
$env:PROCESSOR_ARCHITEW6432 = $oldNativeArch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($ArchitectureOnly) { return }
|
|
||||||
|
|
||||||
$dir = 'C:\Users\Alice\.local\bin'
|
$dir = 'C:\Users\Alice\.local\bin'
|
||||||
foreach ($existing in @('', 'C:\WindowsApps', 'C:\A;C:\B')) {
|
$pathCases = @(
|
||||||
$script:UserPath = $existing
|
@{ Existing = ''; Expected = $dir }
|
||||||
Add-ToUserPath $dir
|
@{ Existing = 'C:\WindowsApps'; Expected = "$dir;C:\WindowsApps" }
|
||||||
$expected = if ($existing) { "$existing;$dir" } else { $dir }
|
@{ Existing = 'C:\A;C:\B'; Expected = "$dir;C:\A;C:\B" }
|
||||||
Assert-Equal $script:UserPath $expected
|
@{ Existing = "C:\old-bsk;$dir;C:\B;$($dir.ToUpperInvariant())"; Expected = "$dir;C:\old-bsk;C:\B" }
|
||||||
Add-ToUserPath $dir
|
)
|
||||||
Assert-Equal $script:UserPath $expected
|
$oldPath = $env:PATH
|
||||||
|
try {
|
||||||
|
foreach ($case in $pathCases) {
|
||||||
|
$script:UserPath = $case.Existing
|
||||||
|
$env:PATH = $case.Existing
|
||||||
|
foreach ($attempt in 1..2) {
|
||||||
|
Add-ToUserPath $dir
|
||||||
|
Add-ToSessionPath $dir
|
||||||
|
Assert-Equal $script:UserPath $case.Expected
|
||||||
|
Assert-Equal $env:PATH $case.Expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally { $env:PATH = $oldPath }
|
||||||
|
if ($HelpersOnly) {
|
||||||
|
Write-Host "Windows installer helper regressions passed ($($PSVersionTable.PSVersion))"
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$root = Join-Path ([IO.Path]::GetTempPath()) ("bsk-install-test-" + [Guid]::NewGuid().ToString('N'))
|
$root = Join-Path ([IO.Path]::GetTempPath()) ("bsk-install-test-" + [Guid]::NewGuid().ToString('N'))
|
||||||
[IO.Directory]::CreateDirectory($root) | Out-Null
|
[IO.Directory]::CreateDirectory($root) | Out-Null
|
||||||
$oldBskHome = $env:BSK_HOME
|
$oldBskHome = $env:BSK_HOME
|
||||||
$oldAutoUpdate = $env:BSK_AUTO_UPDATE
|
$oldAutoUpdate = $env:BSK_AUTO_UPDATE
|
||||||
|
$oldVersion = $env:BSK_VERSION
|
||||||
|
$oldProcessArch = $env:PROCESSOR_ARCHITECTURE
|
||||||
|
$oldNativeArch = $env:PROCESSOR_ARCHITEW6432
|
||||||
$daemon = $null
|
$daemon = $null
|
||||||
try {
|
try {
|
||||||
$utf8 = New-Object System.Text.UTF8Encoding($false)
|
$utf8 = New-Object System.Text.UTF8Encoding($false)
|
||||||
@@ -180,6 +196,84 @@ try {
|
|||||||
try { Assert-Fails { Install-Binary $source $target } } finally { $lock.Dispose() }
|
try { Assert-Fails { Install-Binary $source $target } } finally { $lock.Dispose() }
|
||||||
Assert-Equal (Get-FileHash -LiteralPath $target).Hash $before
|
Assert-Equal (Get-FileHash -LiteralPath $target).Hash $before
|
||||||
if (@(Get-ChildItem -LiteralPath $targetDir -Filter "*.install-*").Count) { throw "staging files leaked" }
|
if (@(Get-ChildItem -LiteralPath $targetDir -Filter "*.install-*").Count) { throw "staging files leaked" }
|
||||||
|
|
||||||
|
# Exercise Main with real ZIPs/executables, isolating network and user state.
|
||||||
|
& {
|
||||||
|
$fixtureTemp = Join-Path $root 'temp [literal]'
|
||||||
|
[IO.Directory]::CreateDirectory($fixtureTemp) | Out-Null
|
||||||
|
$mainDefinition = ($ast.EndBlock.Statements | Where-Object {
|
||||||
|
$_ -is [System.Management.Automation.Language.FunctionDefinitionAst] -and $_.Name -eq 'Main'
|
||||||
|
}).Extent.Text.Replace('[System.IO.Path]::GetTempPath()', '$fixtureTemp')
|
||||||
|
Invoke-Expression $mainDefinition
|
||||||
|
function Write-Die([string]$Message) { throw $Message }
|
||||||
|
$bashProfile = (Get-Command Add-ToBashProfile).ScriptBlock
|
||||||
|
function Add-ToBashProfile([string]$Dir) {
|
||||||
|
& $bashProfile $Dir (Join-Path $root 'flow.bashrc')
|
||||||
|
}
|
||||||
|
$fixtureArchive = Join-Path $root 'release.zip'
|
||||||
|
Compress-Archive -LiteralPath $source -DestinationPath $fixtureArchive -CompressionLevel Fastest
|
||||||
|
$asset = @{ sha256 = (Get-FileHash -LiteralPath $fixtureArchive).Hash }
|
||||||
|
$fixtureManifest = @{ version = '9.8.7'; assets = @{ 'windows-x64' = $asset } }
|
||||||
|
$downloads = New-Object 'System.Collections.Generic.List[string]'
|
||||||
|
function Invoke-RestMethod([string]$Uri) {
|
||||||
|
if (-not $fixtureManifest) { throw 'fixture manifest unavailable' }
|
||||||
|
return $fixtureManifest
|
||||||
|
}
|
||||||
|
function Invoke-WebRequest {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param([string]$Uri, [string]$OutFile, [switch]$UseBasicParsing)
|
||||||
|
$downloads.Add($Uri)
|
||||||
|
[IO.File]::Copy($fixtureArchive, $OutFile)
|
||||||
|
}
|
||||||
|
$GitHub = 'https://example.invalid/fixture'
|
||||||
|
$InstallDir = Join-Path $root 'installed [literal]'
|
||||||
|
$installed = Join-Path $InstallDir 'bsk.exe'
|
||||||
|
$env:BSK_VERSION = $null
|
||||||
|
$env:PROCESSOR_ARCHITECTURE = 'AMD64'
|
||||||
|
$env:PROCESSOR_ARCHITEW6432 = $null
|
||||||
|
$script:UserPath = "$targetDir;$InstallDir;$($InstallDir.ToUpperInvariant())"
|
||||||
|
$env:PATH = "$targetDir;$InstallDir;$oldPath"
|
||||||
|
Assert-Equal (Get-Command bsk -CommandType Application).Source $target
|
||||||
|
Main
|
||||||
|
Assert-Equal $downloads.Count 1
|
||||||
|
Assert-Equal (Get-Command bsk -CommandType Application).Source $installed
|
||||||
|
Assert-Equal $script:UserPath "$InstallDir;$targetDir"
|
||||||
|
Assert-Equal (Get-FileHash -LiteralPath $installed).Hash (Get-FileHash -LiteralPath $source).Hash
|
||||||
|
Assert-Equal @(Get-ChildItem -LiteralPath $fixtureTemp -Force).Count 0
|
||||||
|
|
||||||
|
# ARM64 must be listed in the manifest before any archive is requested.
|
||||||
|
$env:PROCESSOR_ARCHITECTURE = 'ARM64'
|
||||||
|
$downloads.Clear()
|
||||||
|
$message = $null
|
||||||
|
try { Main } catch { $message = $_.Exception.Message }
|
||||||
|
Assert-Equal $message 'version.json does not list a Windows ARM64 package for bsk 9.8.7'
|
||||||
|
Assert-Equal $downloads.Count 0
|
||||||
|
$env:BSK_VERSION = '9.8.7'
|
||||||
|
$fixtureManifest = $null
|
||||||
|
$message = $null
|
||||||
|
try { Main } catch { $message = $_.Exception.Message }
|
||||||
|
Assert-Equal $message 'version.json does not list a Windows ARM64 package for bsk 9.8.7'
|
||||||
|
Assert-Equal $downloads.Count 0
|
||||||
|
|
||||||
|
# Keep pinned x64 installs compatible with older releases without manifests.
|
||||||
|
$env:PROCESSOR_ARCHITECTURE = 'AMD64'
|
||||||
|
Main
|
||||||
|
Assert-Equal $downloads.Count 1
|
||||||
|
Assert-Equal @(Get-ChildItem -LiteralPath $fixtureTemp -Force).Count 0
|
||||||
|
|
||||||
|
# A listed ARM64 archive remains selectable (the fixture uses the host EXE).
|
||||||
|
$fixtureManifest = @{ version = '9.8.7'; assets = @{ 'windows-arm64' = $asset } }
|
||||||
|
$env:PROCESSOR_ARCHITECTURE = 'ARM64'
|
||||||
|
Main
|
||||||
|
Assert-Equal $downloads[$downloads.Count - 1] "$GitHub/releases/download/cli-v9.8.7/bsk-v9.8.7-aarch64-pc-windows-msvc.zip"
|
||||||
|
|
||||||
|
# A checksum failure must clean the bracketed temp path and preserve the install.
|
||||||
|
$before = (Get-FileHash -LiteralPath $installed).Hash
|
||||||
|
$fixtureManifest.assets['windows-arm64'] = @{ sha256 = '0' * 64 }
|
||||||
|
Assert-Fails { Main }
|
||||||
|
Assert-Equal (Get-FileHash -LiteralPath $installed).Hash $before
|
||||||
|
Assert-Equal @(Get-ChildItem -LiteralPath $fixtureTemp -Force).Count 0
|
||||||
|
}
|
||||||
Write-Host "Windows installer regressions passed ($($PSVersionTable.PSVersion))"
|
Write-Host "Windows installer regressions passed ($($PSVersionTable.PSVersion))"
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
@@ -194,6 +288,10 @@ finally {
|
|||||||
}
|
}
|
||||||
$env:BSK_HOME = $oldBskHome
|
$env:BSK_HOME = $oldBskHome
|
||||||
$env:BSK_AUTO_UPDATE = $oldAutoUpdate
|
$env:BSK_AUTO_UPDATE = $oldAutoUpdate
|
||||||
|
$env:BSK_VERSION = $oldVersion
|
||||||
|
$env:PROCESSOR_ARCHITECTURE = $oldProcessArch
|
||||||
|
$env:PROCESSOR_ARCHITEW6432 = $oldNativeArch
|
||||||
|
$env:PATH = $oldPath
|
||||||
Remove-Item Env:BSK_TEST_RC -ErrorAction SilentlyContinue
|
Remove-Item Env:BSK_TEST_RC -ErrorAction SilentlyContinue
|
||||||
# Resolve and verify before recursive cleanup; only this fixture is removed.
|
# Resolve and verify before recursive cleanup; only this fixture is removed.
|
||||||
$resolvedRoot = [IO.Path]::GetFullPath($root)
|
$resolvedRoot = [IO.Path]::GetFullPath($root)
|
||||||
|
|||||||
Reference in New Issue
Block a user