# {{ .DisplayName }} Credential Helper Installation Script for Windows # Usage: iwr -useb https://{{ .SiteHost }}/static/install.ps1 | iex $ErrorActionPreference = "Stop" # Configuration $BinaryName = "{{ .BinaryName }}.exe" $InstallDir = if ($env:{{ .EnvPrefix }}_INSTALL_DIR) { $env:{{ .EnvPrefix }}_INSTALL_DIR } else { "$env:ProgramFiles\{{ .DisplayName }}" } $TangledRepo = if ($env:{{ .EnvPrefix }}_TANGLED_REPO) { $env:{{ .EnvPrefix }}_TANGLED_REPO } else { "{{ .ReleasesBaseURL }}" } Write-Host "{{ .DisplayName }} Credential Helper Installer for Windows" -ForegroundColor Green Write-Host "" # Detect architecture function Get-Architecture { $arch = (Get-WmiObject Win32_Processor).Architecture switch ($arch) { 9 { return "x86_64" } # x64 12 { return "arm64" } # ARM64 default { Write-Host "Unsupported architecture: $arch" -ForegroundColor Red exit 1 } } } $Arch = Get-Architecture Write-Host "Detected: Windows $Arch" -ForegroundColor Green # Resolve the latest version by following the tangled /tags/latest redirect # chain. Tangled redirects DID→handle first, then handle/tags/latest→handle/tags/vX.Y.Z, # so we follow all redirects and read the final effective URL. function Get-LatestVersion { Write-Host "Resolving latest version..." -ForegroundColor Yellow try { $response = Invoke-WebRequest -Uri "$TangledRepo/tags/latest" -UseBasicParsing -Method Head } catch { Write-Host "Failed to resolve latest version from $TangledRepo/tags/latest" -ForegroundColor Red exit 1 } # PowerShell 7+ exposes the final URI via RequestMessage; PowerShell 5 via ResponseUri. if ($response.BaseResponse.RequestMessage) { $finalUrl = $response.BaseResponse.RequestMessage.RequestUri.ToString() } else { $finalUrl = $response.BaseResponse.ResponseUri.ToString() } if (-not $finalUrl) { Write-Host "Failed to resolve latest version from $TangledRepo/tags/latest" -ForegroundColor Red exit 1 } $tag = $finalUrl.TrimEnd('/').Split('/')[-1] if (-not $tag.StartsWith('v')) { Write-Host "Unexpected redirect location: $finalUrl" -ForegroundColor Red exit 1 } Write-Host "Found latest version: $tag" -ForegroundColor Green return $tag } # Build the download URL from version and platform function Get-DownloadUrl { param([string]$Version, [string]$Arch) $versionClean = $Version.TrimStart('v') $fileName = "{{ .BinaryName }}_${versionClean}_Windows_${Arch}.tar.gz" return "$TangledRepo/tags/$Version/download/$fileName" } # Determine version and download URL if ($env:{{ .EnvPrefix }}_VERSION) { $Version = $env:{{ .EnvPrefix }}_VERSION Write-Host "Using specified version: $Version" -ForegroundColor Yellow } else { $Version = Get-LatestVersion } $DownloadUrl = Get-DownloadUrl -Version $Version -Arch $Arch Write-Host "Installing version: $Version" -ForegroundColor Green # Download and install binary function Install-Binary { param ( [string]$DownloadUrl ) Write-Host "Downloading from: $DownloadUrl" -ForegroundColor Yellow $tempDir = New-Item -ItemType Directory -Path "$env:TEMP\{{ .Name }}-install-$(Get-Random)" -Force $archivePath = Join-Path $tempDir "{{ .BinaryName }}.tar.gz" try { Invoke-WebRequest -Uri $DownloadUrl -OutFile $archivePath -UseBasicParsing } catch { Write-Host "Failed to download release: $_" -ForegroundColor Red exit 1 } Write-Host "Extracting..." -ForegroundColor Yellow # Modern Windows ships tar.exe; use it to handle .tar.gz produced by goreleaser. & tar.exe -xzf $archivePath -C $tempDir if ($LASTEXITCODE -ne 0) { Write-Host "Failed to extract archive" -ForegroundColor Red exit 1 } # Create install directory if (-not (Test-Path $InstallDir)) { New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null } # Install binary $binaryPath = Join-Path $tempDir $BinaryName $destPath = Join-Path $InstallDir $BinaryName Copy-Item -Path $binaryPath -Destination $destPath -Force # Clean up Remove-Item -Path $tempDir -Recurse -Force Write-Host "Installed $BinaryName to $InstallDir" -ForegroundColor Green } # Add to PATH if not already present function Add-ToPath { $currentPath = [Environment]::GetEnvironmentVariable("Path", "Machine") if ($currentPath -notlike "*$InstallDir*") { Write-Host "Adding $InstallDir to system PATH..." -ForegroundColor Yellow # Check if running as administrator $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if ($isAdmin) { [Environment]::SetEnvironmentVariable("Path", "$currentPath;$InstallDir", "Machine") $env:Path = "$env:Path;$InstallDir" Write-Host "Added to PATH successfully" -ForegroundColor Green } else { Write-Host "WARNING: Not running as administrator. Cannot update system PATH." -ForegroundColor Yellow Write-Host "Please add $InstallDir to your PATH manually or re-run as administrator." -ForegroundColor Yellow } } } # Verify installation function Test-Installation { $binaryPath = Join-Path $InstallDir $BinaryName if (Test-Path $binaryPath) { Write-Host "Verification successful!" -ForegroundColor Green # Try to run version command try { & $binaryPath --version } catch { Write-Host "Binary installed but PATH may need to be refreshed." -ForegroundColor Yellow Write-Host "Please restart your terminal or run: refreshenv" -ForegroundColor Yellow } } else { Write-Host "Installation failed: binary not found at $binaryPath" -ForegroundColor Red exit 1 } } # Show configuration instructions function Show-Configuration { Write-Host "" Write-Host "Installation complete!" -ForegroundColor Green Write-Host "" Write-Host "To use {{ .DisplayName }} with Docker, configure Docker to use this credential helper:" -ForegroundColor Yellow Write-Host ' Edit %USERPROFILE%\.docker\config.json and add:' Write-Host ' { "credHelpers": { "{{ .RegistryHost }}": "{{ .Name }}" } }' Write-Host "" Write-Host "Note: You may need to restart your terminal for PATH changes to take effect." -ForegroundColor Yellow } # Main installation flow try { Install-Binary -DownloadUrl $DownloadUrl Add-ToPath Test-Installation Show-Configuration } catch { Write-Host "Installation failed: $_" -ForegroundColor Red exit 1 }