Repository navigation
Expand file tree
/
Copy pathinstall.ps1
More file actions
122 lines (106 loc) · 5.34 KB
/
Copy pathinstall.ps1
File metadata and controls
122 lines (106 loc) · 5.34 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
#!/usr/bin/env pwsh
# install.ps1 — thin bootstrap: acquire the axon binary, then hand off to `axon setup`.
# Windows mirror of install.sh. All prerequisite checks happen inside `axon setup`.
#
# Environment controls:
# AXON_INSTALL_REPO GitHub repo (default: dinglebear-ai/axon)
# AXON_VERSION Release version tag, e.g. v5.8.1 (default: latest)
# AXON_INSTALL_PREFIX Install prefix (default: $HOME\.local)
# AXON_INSTALL_DRY_RUN Set to 1 to print what would happen without doing it
# AXON_UPDATE_MINISIGN_PUBKEY Trusted raw public key or .pub contents obtained independently
# AXON_INSTALL_SKIP_SETUP Set to 1 to skip running `axon setup` after install
#
# Usage: download install.ps1 from a reviewed, version-pinned release, inspect
# it locally, then execute the pinned file:
# .\install.ps1
#
# Pinned version:
# $env:AXON_VERSION='v5.8.1'; .\install.ps1
#
# Skip setup (install binary only):
# $env:AXON_INSTALL_SKIP_SETUP='1'; .\install.ps1
[CmdletBinding()]
param()
$ErrorActionPreference = 'Stop'
$Repo = if ($env:AXON_INSTALL_REPO) { $env:AXON_INSTALL_REPO } else { 'dinglebear-ai/axon' }
$Version = if ($env:AXON_VERSION) { $env:AXON_VERSION } else { 'latest' }
$Prefix = if ($env:AXON_INSTALL_PREFIX) { $env:AXON_INSTALL_PREFIX } else { Join-Path $HOME '.local' }
$BinDir = Join-Path $Prefix 'bin'
$Exe = Join-Path $BinDir 'axon.exe'
$DryRun = $env:AXON_INSTALL_DRY_RUN -eq '1'
$SkipSetup = $env:AXON_INSTALL_SKIP_SETUP -eq '1'
function Say { param([string]$Msg) Write-Host $Msg }
function Fail { param([string]$Msg) Write-Error "axon install: $Msg"; exit 1 }
function Get-AssetUrl {
param([string]$Target, [string]$Ext)
if ($Version -eq 'latest') {
"https://github.com/$Repo/releases/latest/download/axon-$Target.$Ext"
} else {
"https://github.com/$Repo/releases/download/$Version/axon-$Target.$Ext"
}
}
if ($DryRun) {
Say "Dry run OK: target=windows-x86_64 prefix=$Prefix repo=$Repo version=$Version"
exit 0
}
$PublicKeyText = $env:AXON_UPDATE_MINISIGN_PUBKEY
if ([string]::IsNullOrWhiteSpace($PublicKeyText)) { Fail 'AXON_UPDATE_MINISIGN_PUBKEY is required to authenticate release downloads' }
$PublicKeyLines = @($PublicKeyText -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_ -and -not $_.StartsWith('untrusted comment:') })
if ($PublicKeyLines.Count -ne 1) { Fail 'AXON_UPDATE_MINISIGN_PUBKEY must contain one raw key or one minisign public-key file' }
$PublicKey = $PublicKeyLines[0]
try {
$DecodedPublicKey = [Convert]::FromBase64String($PublicKey)
} catch {
Fail 'AXON_UPDATE_MINISIGN_PUBKEY is not valid Base64'
}
if ($DecodedPublicKey.Length -ne 42) { Fail 'AXON_UPDATE_MINISIGN_PUBKEY is not a minisign public key' }
$Minisign = Get-Command minisign -CommandType Application -ErrorAction SilentlyContinue
if (-not $Minisign) { Fail 'install minisign from a trusted source before running this installer' }
$Target = 'windows-x86_64'
$ZipUrl = Get-AssetUrl $Target 'zip'
$Sha256Url = "$ZipUrl.sha256"
$TmpDir = Join-Path ([System.IO.Path]::GetTempPath()) "axon-install-$(Get-Random)"
New-Item -ItemType Directory -Path $TmpDir | Out-Null
try {
$ZipPath = Join-Path $TmpDir 'axon.zip'
$Sha256Path = Join-Path $TmpDir 'axon.zip.sha256'
Say "Downloading $ZipUrl"
Invoke-WebRequest -Uri $ZipUrl -OutFile $ZipPath -UseBasicParsing
Say "Downloading $Sha256Url"
Invoke-WebRequest -Uri $Sha256Url -OutFile $Sha256Path -UseBasicParsing
# Verify checksum (release.yml writes lowercase hex; Get-FileHash returns uppercase)
$Expected = ((Get-Content $Sha256Path -Raw).Trim() -split '\s+')[0].ToLower()
if ([string]::IsNullOrEmpty($Expected)) { Fail 'checksum file is empty' }
$Actual = (Get-FileHash $ZipPath -Algorithm SHA256).Hash.ToLower()
if ($Expected -ne $Actual) { Fail "checksum mismatch — expected $Expected, got $Actual" }
$SignaturePath = Join-Path $TmpDir 'axon.zip.minisig'
Invoke-WebRequest -Uri "$ZipUrl.minisig" -OutFile $SignaturePath -UseBasicParsing
& $Minisign.Source -V -P $PublicKey -m $ZipPath -x $SignaturePath
if ($LASTEXITCODE -ne 0) { Fail 'release signature verification failed' }
# Extract only after authenticating the archive with an independently trusted key.
# Extract axon.exe from the zip
Expand-Archive -Path $ZipPath -DestinationPath $TmpDir -Force
$ExtractedExe = Join-Path $TmpDir 'axon.exe'
if (-not (Test-Path $ExtractedExe)) { Fail 'release archive did not contain axon.exe' }
# Install
New-Item -ItemType Directory -Path $BinDir -Force | Out-Null
Copy-Item -Path $ExtractedExe -Destination $Exe -Force
Say "Installed $Exe"
# Add BinDir to user PATH if not already present
$UserPath = [Environment]::GetEnvironmentVariable('Path', 'User')
if (-not $UserPath) { $UserPath = '' }
$PathParts = $UserPath -split ';' | Where-Object { $_ -ne '' }
if ($BinDir -notin $PathParts) {
$NewPath = ($PathParts + $BinDir) -join ';'
[Environment]::SetEnvironmentVariable('Path', $NewPath, 'User')
Say "Added $BinDir to your user PATH (restart your shell to pick it up)"
$env:Path = "$env:Path;$BinDir"
}
if (-not $SkipSetup) {
Say ''
Say 'Running axon setup...'
& $Exe setup
}
} finally {
Remove-Item -Recurse -Force $TmpDir -ErrorAction SilentlyContinue
}