-
Notifications
You must be signed in to change notification settings - Fork 552
Expand file tree
/
Copy pathinstall.ps1
More file actions
267 lines (218 loc) · 10.9 KB
/
Copy pathinstall.ps1
File metadata and controls
267 lines (218 loc) · 10.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
<#
.SYNOPSIS
install.ps1 — install the bsk CLI on Windows from GitHub Releases.
.DESCRIPTION
Downloads the latest (or pinned) bsk release for Windows x64,
extracts bsk.exe to a user-local directory, and adds it to PATH.
Usage:
irm https://raw.githubusercontent.com/Tencent/BrowserSkill/main/install.ps1 | iex
Environment overrides:
$env:BSK_REPO GitHub owner/repo (default: Tencent/BrowserSkill)
$env:BSK_VERSION Pin CLI version (default: latest from version.json)
$env:BSK_INSTALL_DIR Install directory (default: $HOME\.local\bin)
#>
#Requires -Version 5.1
$ErrorActionPreference = "Stop"
$Repo = if ($env:BSK_REPO) { $env:BSK_REPO } else { "Tencent/BrowserSkill" }
$InstallDir = if ($env:BSK_INSTALL_DIR) { $env:BSK_INSTALL_DIR } else { Join-Path $HOME ".local\bin" }
$InstallDir = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($InstallDir)
$GitHub = "https://github.com/${Repo}"
function Write-Log {
param([string]$Message)
Write-Host "==> $Message" -ForegroundColor Cyan
}
function Write-Die {
param([string]$Message)
Write-Host "error: $Message" -ForegroundColor Red
exit 1
}
# ── Platform / architecture detection ─────────────────────────────────────────
function Get-PlatformTriple {
# RuntimeInformation.ProcessArchitecture can be unavailable in Windows PowerShell 5.1.
# WOW64 exposes the native architecture separately from the 32-bit process.
$arch = $env:PROCESSOR_ARCHITEW6432
if (-not $arch) { $arch = $env:PROCESSOR_ARCHITECTURE }
if (-not $arch) {
Write-Die "could not detect Windows architecture: PROCESSOR_ARCHITEW6432 and PROCESSOR_ARCHITECTURE are empty"
}
switch ($arch) {
"AMD64" { $archId = "x64" }
"ARM64" { $archId = "arm64" }
default { Write-Die "unsupported architecture: $arch (x64 and ARM64 only)" }
}
$windowsArch = switch ($archId) {
"x64" { "x86_64-pc-windows-msvc" }
"arm64" { "aarch64-pc-windows-msvc" }
}
return @{
ArchId = $archId
TargetTriple = $windowsArch
PlatformKey = "windows-$archId"
}
}
# ── Version resolution ────────────────────────────────────────────────────────
# ── PATH helpers ──────────────────────────────────────────────────────────────
function Add-ToUserPath {
param([string]$Dir)
$currentUserPath = @([Environment]::GetEnvironmentVariable("PATH", "User") -split ";" | Where-Object { $_ })
$newUserPath = (@($Dir) + @($currentUserPath | Where-Object { $_ -ine $Dir })) -join ";"
if (($currentUserPath -join ";") -ceq $newUserPath) {
Write-Log "$Dir is already first in your user PATH"
return
}
[Environment]::SetEnvironmentVariable("PATH", $newUserPath, "User")
Write-Log "placed ${Dir} first in user PATH"
}
function Add-ToSessionPath {
param([string]$Dir)
$pathEntries = @($env:PATH -split ";" | Where-Object { $_ -and $_ -ine $Dir })
$env:PATH = (@($Dir) + $pathEntries) -join ";"
}
# ── Git Bash (bash environment) PATH helper ──────────────────────────────────
function Add-ToBashProfile {
param([string]$Dir, [string]$BashRc = (Join-Path $HOME ".bashrc"))
# Convert Windows path (e.g. C:\Users\foo\.local\bin) to Git-Bash Unix-style (/c/Users/foo/.local/bin)
$unixPath = $Dir -replace '\\', '/'
if ($unixPath -match '^([A-Z]):(.*)$') {
$unixPath = '/' + $matches[1].ToLower() + $matches[2]
}
# Single-quote the literal directory; only the existing PATH is expanded.
$shellQuote = "'" + [char]34 + "'" + [char]34 + "'"
$quotedPath = "'" + $unixPath.Replace("'", $shellQuote) + "'"
$exportLine = "export PATH=${quotedPath}:`"`$PATH`" # bsk CLI"
if (Test-Path -LiteralPath $BashRc) {
$content = [System.IO.File]::ReadAllText($BashRc)
if ($content.Contains($exportLine)) {
Write-Log "$unixPath is already in ~/.bashrc"
return
}
}
# Explicit BOM-less UTF-8 also works in Windows PowerShell 5.1.
[System.IO.File]::AppendAllText($BashRc, "`n$exportLine`n", (New-Object System.Text.UTF8Encoding($false)))
Write-Log "added ${unixPath} to ~/.bashrc"
}
# ── Main ──────────────────────────────────────────────────────────────────────
# Stage on the destination volume before stopping the daemon. Never truncate
# the installed executable: failed replacement must leave it usable.
function Install-Binary {
param([string]$Source, [string]$Target)
$staged = "$Target.install-$([Guid]::NewGuid().ToString('N'))"
try {
[System.IO.File]::Copy($Source, $staged)
# The running daemon may come from another installation directory.
# Use the downloaded CLI: older versions have broken Windows liveness checks.
# Stop verifies daemon identity and uses the current BSK_HOME.
# Fail closed for both new installs and replacements; never discard daemon metadata here.
& $Source daemon stop
if ($LASTEXITCODE -ne 0) {
$daemonHome = if ($env:BSK_HOME) { $env:BSK_HOME } else { Join-Path $HOME ".bsk" }
$daemonInfoPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath((Join-Path $daemonHome "daemon.json"))
throw "could not stop bsk daemon; installation was not changed. Stop any running bsk daemon, remove '$daemonInfoPath', then retry the installer."
}
if ([System.IO.File]::Exists($Target)) {
# PowerShell 5.1 converts $null to an empty path for string parameters.
[System.IO.File]::Replace($staged, $Target, [NullString]::Value)
}
else {
[System.IO.File]::Move($staged, $Target)
}
}
finally {
if ([System.IO.File]::Exists($staged)) { [System.IO.File]::Delete($staged) }
}
}
function Main {
$platform = Get-PlatformTriple
if ($env:BSK_VERSION) {
$version = $env:BSK_VERSION -replace '^v', ''
$tag = "cli-v${version}"
$manifestUrl = "${GitHub}/releases/download/${tag}/version.json"
Write-Log "using pinned version ${version}"
# Best-effort manifest fetch for the checksum (missing manifest
# only skips verification; a mismatch is fatal below).
try { $manifest = Invoke-RestMethod -Uri $manifestUrl } catch { $manifest = $null }
}
else {
$manifestUrl = "${GitHub}/releases/latest/download/version.json"
Write-Log "fetching latest version from ${manifestUrl}"
$manifest = Invoke-RestMethod -Uri $manifestUrl
$version = $manifest.version
if (-not $version) { Write-Die "could not parse version from version.json" }
$tag = "cli-v${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"
$downloadUrl = "${GitHub}/releases/download/${tag}/${archiveName}"
$expectedSha = if ($asset) { $asset.sha256 } else { $null }
if (-not $expectedSha) {
if (-not $manifest) {
Write-Log "warning: could not fetch version.json; skipping checksum verification"
}
else {
Write-Log "warning: no checksum published for $($platform.PlatformKey); skipping checksum verification"
}
}
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.IO.Path]::GetRandomFileName())
[System.IO.Directory]::CreateDirectory($tempDir) | Out-Null
try {
$archivePath = Join-Path $tempDir $archiveName
Write-Log "downloading ${downloadUrl}"
# PowerShell 5.1's -OutFile treats brackets as wildcards. Write raw HTTP bytes literally.
$response = Invoke-WebRequest -Uri $downloadUrl -UseBasicParsing -ErrorAction Stop
try {
[System.IO.File]::WriteAllBytes($archivePath, $response.RawContentStream.ToArray())
} finally { $response.RawContentStream.Dispose() }
if ($expectedSha) {
Write-Log "verifying checksum"
$actualSha = (Get-FileHash -Algorithm SHA256 -LiteralPath $archivePath).Hash
if ($actualSha -ieq $expectedSha) {
Write-Log "checksum OK"
}
else {
Write-Die "checksum mismatch: expected $expectedSha, got $actualSha"
}
}
Write-Log "extracting ${archiveName}"
# PowerShell 5.1's Expand-Archive treats the destination as a wildcard path.
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($archivePath, $tempDir)
if (-not (Test-Path -LiteralPath (Join-Path $tempDir "bsk.exe"))) {
Write-Die "bsk.exe not found in archive"
}
[System.IO.Directory]::CreateDirectory($InstallDir) | Out-Null
Install-Binary -Source (Join-Path $tempDir "bsk.exe") -Target (Join-Path $InstallDir "bsk.exe")
Write-Log "installed bsk to $InstallDir\bsk.exe"
# Add to session PATH (current shell)
Add-ToSessionPath $InstallDir
# Add to user PATH (persistent, for PowerShell / cmd)
Add-ToUserPath $InstallDir
# Add to Git Bash PATH (persistent, for bash-based shells / agents)
Add-ToBashProfile $InstallDir
# Verify
$bskPath = Join-Path $InstallDir "bsk.exe"
& $bskPath --version
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 in this session; check Get-Command bsk -All for a conflicting command"
}
Write-Log "done"
Write-Host ""
Write-Host "This PATH check covers the current session only; a new terminal may prefer a Machine PATH entry or alias."
Write-Host "In a new PowerShell terminal, run Get-Command bsk -All and confirm the first result is $bskPath."
}
finally {
Remove-Item -LiteralPath $tempDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
Main