kingfisher/scripts/kingfisher-pre-commit-auto.ps1

179 lines
5.3 KiB
PowerShell

<#
.SYNOPSIS
Kingfisher pre-commit hook with automatic binary download for Windows.
.DESCRIPTION
Downloads and caches the Kingfisher binary, then scans staged changes.
No manual installation required.
.PARAMETER Version
Specific version to download (e.g., "1.76.0" or "v1.76.0").
Defaults to "latest".
.PARAMETER Arch
Optional architecture override. Defaults to auto-detection.
Allowed values: auto, x64, arm64.
.EXAMPLE
./kingfisher-pre-commit-auto.ps1
.EXAMPLE
$env:KINGFISHER_VERSION = "1.76.0"; ./kingfisher-pre-commit-auto.ps1
.EXAMPLE
./kingfisher-pre-commit-auto.ps1 -Arch arm64
#>
[CmdletBinding()]
param(
[ValidateSet('auto', 'x64', 'arm64')]
[string]$Arch = 'auto'
)
$ErrorActionPreference = 'Stop'
$repo = 'mongodb/kingfisher'
$cacheDir = if ($env:KINGFISHER_CACHE_DIR) {
$env:KINGFISHER_CACHE_DIR
} else {
Join-Path $env:LOCALAPPDATA 'kingfisher'
}
$expectedVersion = if ($env:KINGFISHER_VERSION) { $env:KINGFISHER_VERSION } else { 'latest' }
$resolvedArch = $null
$kingfisherBin = $null
$versionFile = $null
function Resolve-ArchSuffix {
param(
[ValidateSet('auto', 'x64', 'arm64')]
[string]$RequestedArch
)
if ($RequestedArch -ne 'auto') {
return $RequestedArch
}
$osArch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture
switch ($osArch) {
'X64' { return 'x64' }
'Arm64' { return 'arm64' }
default { throw "Unsupported Windows architecture '$osArch'. Supported values are x64 and arm64." }
}
}
function Get-AssetName {
param(
[string]$ArchSuffix
)
return "kingfisher-windows-$ArchSuffix.zip"
}
function Download-Kingfisher {
param(
[string]$Version
)
$assetName = Get-AssetName -ArchSuffix $resolvedArch
if (-not (Test-Path $cacheDir)) {
New-Item -ItemType Directory -Path $cacheDir -Force | Out-Null
}
$tempDir = New-Item -ItemType Directory -Path ([System.IO.Path]::GetTempPath()) -Name ([System.Guid]::NewGuid().ToString())
try {
if ($Version -eq 'latest') {
$downloadUrl = "https://github.com/$repo/releases/latest/download/$assetName"
Write-Host "Downloading kingfisher (latest) for Windows $resolvedArch..." -ForegroundColor Cyan
} else {
# Support both "v1.76.0" and "1.76.0" formats
if (-not $Version.StartsWith('v')) {
$Version = "v$Version"
}
$downloadUrl = "https://github.com/$repo/releases/download/$Version/$assetName"
Write-Host "Downloading kingfisher ($Version) for Windows $resolvedArch..." -ForegroundColor Cyan
}
$archivePath = Join-Path $tempDir.FullName $assetName
try {
Invoke-WebRequest -Uri $downloadUrl -OutFile $archivePath -UseBasicParsing
} catch {
Write-Error "Failed to download $downloadUrl : $_"
exit 1
}
Write-Host "Extracting archive..." -ForegroundColor Cyan
Expand-Archive -Path $archivePath -DestinationPath $tempDir.FullName -Force
$extractedBinary = Join-Path $tempDir.FullName 'kingfisher.exe'
if (-not (Test-Path $extractedBinary)) {
Write-Error "Binary not found in downloaded archive"
exit 1
}
Copy-Item -Path $extractedBinary -Destination $kingfisherBin -Force
# Store the version we downloaded
if ($Version -eq 'latest') {
try {
$versionOutput = & $kingfisherBin --version 2>$null | Select-Object -First 1
Set-Content -Path $versionFile -Value $versionOutput -NoNewline
} catch {
Set-Content -Path $versionFile -Value 'latest' -NoNewline
}
} else {
Set-Content -Path $versionFile -Value $Version -NoNewline
}
Write-Host "Kingfisher installed to $kingfisherBin" -ForegroundColor Green
}
finally {
if ($tempDir -and (Test-Path $tempDir.FullName)) {
Remove-Item -Path $tempDir.FullName -Recurse -Force -ErrorAction SilentlyContinue
}
}
}
function Test-NeedsDownload {
# Binary doesn't exist
if (-not (Test-Path $kingfisherBin)) {
return $true
}
# No version tracking - always use existing binary for 'latest'
if ($expectedVersion -eq 'latest') {
return $false
}
# Check if version matches
if (Test-Path $versionFile) {
$installedVersion = Get-Content -Path $versionFile -Raw
# Normalize version format for comparison
$expectedNormalized = $expectedVersion
if (-not $expectedNormalized.StartsWith('v')) {
$expectedNormalized = "v$expectedNormalized"
}
if ($installedVersion -like "*$expectedNormalized*" -or $installedVersion -eq $expectedVersion) {
return $false
}
}
return $true
}
# Main execution
$resolvedArch = Resolve-ArchSuffix -RequestedArch $Arch
$kingfisherBin = Join-Path $cacheDir 'kingfisher.exe'
$versionFile = Join-Path $cacheDir ".version-$resolvedArch"
if (Test-NeedsDownload) {
Download-Kingfisher -Version $expectedVersion
}
# Run kingfisher scan on staged changes
# Pass through any additional arguments
& $kingfisherBin scan . --staged --quiet --no-update-check @args
exit $LASTEXITCODE