diff --git a/.github/workflows/cli-release.yml b/.github/workflows/cli-release.yml index 0cc223ba7..b42dc346b 100644 --- a/.github/workflows/cli-release.yml +++ b/.github/workflows/cli-release.yml @@ -31,10 +31,10 @@ jobs: target: aarch64-apple-darwin artifact_name: buster-cli-darwin-arm64.tar.gz use_tar: true - # - os: windows-latest - # target: x86_64-pc-windows-msvc - # artifact_name: buster-cli-windows-x86_64.zip - # use_tar: false + - os: windows-2022 + target: x86_64-pc-windows-msvc + artifact_name: buster-cli-windows-x86_64.zip + use_tar: false runs-on: ${{ matrix.os }} steps: - name: Checkout code @@ -53,6 +53,17 @@ jobs: - name: Cache Rust dependencies uses: Swatinem/rust-cache@v2 + - name: Cache vcpkg (Windows) + if: runner.os == 'Windows' + uses: actions/cache@v4 + with: + path: | + ${{ runner.workspace }}/vcpkg + ${{ env.VCPKG_INSTALLATION_ROOT }}/installed + key: ${{ runner.os }}-vcpkg-${{ hashFiles('**/*.vcpkg') }} + restore-keys: | + ${{ runner.os }}-vcpkg- + - name: Install libpq (macOS and Linux) if: runner.os != 'Windows' run: | @@ -71,6 +82,20 @@ jobs: env: HOMEBREW_NO_INSTALL_CLEANUP: 1 # Recommended for CI to speed up + - name: Install libpq (Windows) + if: runner.os == 'Windows' + shell: powershell + run: | + # Use vcpkg for faster, more reliable PostgreSQL installation + vcpkg install libpq:x64-windows-static + + # Set environment variables for pq-sys + $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT + echo "PQ_LIB_DIR=$vcpkgRoot\installed\x64-windows-static\lib" >> $env:GITHUB_ENV + echo "PQ_LIB_STATIC=1" >> $env:GITHUB_ENV + echo "VCPKGRS_DYNAMIC=0" >> $env:GITHUB_ENV + echo "RUSTFLAGS=-L $vcpkgRoot\installed\x64-windows-static\lib" >> $env:GITHUB_ENV + - name: Configure Cargo for optimized build run: | mkdir -p .cargo @@ -80,9 +105,17 @@ jobs: echo 'panic = "abort"' >> .cargo/config.toml echo 'opt-level = 3' >> .cargo/config.toml echo 'strip = true' >> .cargo/config.toml + shell: bash - name: Build optimized release working-directory: ./cli - run: cargo build --release --target ${{ matrix.target }} + run: | + if [[ "${{ runner.os }}" == "Windows" ]]; then + # Use parallel compilation on Windows + cargo build --release --target ${{ matrix.target }} --jobs $(nproc) + else + cargo build --release --target ${{ matrix.target }} + fi + shell: bash - name: Compress binary (Unix) if: matrix.use_tar @@ -95,14 +128,15 @@ jobs: else sha256sum ${{ matrix.artifact_name }} > ${{ matrix.artifact_name }}.sha256 fi - # - name: Compress binary (Windows) - # if: matrix.use_tar == false - # working-directory: ./cli - # shell: pwsh - # run: | - # cd target/${{ matrix.target }}/release - # Compress-Archive -Path buster-cli.exe -DestinationPath ${{ matrix.artifact_name }} - # Get-FileHash -Algorithm SHA256 ${{ matrix.artifact_name }} | Select-Object -ExpandProperty Hash > ${{ matrix.artifact_name }}.sha256 + + - name: Compress binary (Windows) + if: matrix.use_tar == false + working-directory: ./cli + shell: pwsh + run: | + cd target/${{ matrix.target }}/release + Compress-Archive -Path buster-cli.exe -DestinationPath ${{ matrix.artifact_name }} + Get-FileHash -Algorithm SHA256 ${{ matrix.artifact_name }} | Select-Object -ExpandProperty Hash > ${{ matrix.artifact_name }}.sha256 - name: Upload artifacts uses: actions/upload-artifact@v4 with: @@ -146,8 +180,8 @@ jobs: **/buster-cli-darwin-x86_64.tar.gz.sha256 **/buster-cli-darwin-arm64.tar.gz **/buster-cli-darwin-arm64.tar.gz.sha256 - # **/buster-cli-windows-x86_64.zip - # **/buster-cli-windows-x86_64.zip.sha256 + **/buster-cli-windows-x86_64.zip + **/buster-cli-windows-x86_64.zip.sha256 draft: false prerelease: false generate_release_notes: true @@ -184,14 +218,17 @@ jobs: SHA_ARM64=$(cat buster-cli-darwin-arm64.tar.gz.sha256 | awk '{print $1}') SHA_INTEL=$(cat buster-cli-darwin-x86_64.tar.gz.sha256 | awk '{print $1}') SHA_LINUX=$(cat buster-cli-linux-x86_64.tar.gz.sha256 | awk '{print $1}') + SHA_WINDOWS=$(cat buster-cli-windows-x86_64.zip.sha256 | awk '{print $1}') echo "SHA_ARM64=$SHA_ARM64" >> $GITHUB_ENV echo "SHA_INTEL=$SHA_INTEL" >> $GITHUB_ENV echo "SHA_LINUX=$SHA_LINUX" >> $GITHUB_ENV + echo "SHA_WINDOWS=$SHA_WINDOWS" >> $GITHUB_ENV echo "ARM64 SHA: $SHA_ARM64" echo "Intel SHA: $SHA_INTEL" echo "Linux SHA: $SHA_LINUX" + echo "Windows SHA: $SHA_WINDOWS" - name: Checkout Homebrew tap repository uses: actions/checkout@v4 diff --git a/scripts/install.ps1 b/scripts/install.ps1 new file mode 100644 index 000000000..be5e9e126 --- /dev/null +++ b/scripts/install.ps1 @@ -0,0 +1,178 @@ +# Buster CLI Installation Script for Windows PowerShell +# Usage: iwr -useb https://raw.githubusercontent.com/buster-so/buster/main/scripts/install.ps1 | iex + +param( + [string]$Version = "latest" +) + +$ErrorActionPreference = "Stop" + +# Configuration +$REPO = "buster-so/buster" +$BINARY_NAME = "buster-cli" +$INSTALL_NAME = "buster" + +# Colors for output +function Write-Info { + param([string]$Message) + Write-Host "[INFO] $Message" -ForegroundColor Blue +} + +function Write-Success { + param([string]$Message) + Write-Host "[SUCCESS] $Message" -ForegroundColor Green +} + +function Write-Warning { + param([string]$Message) + Write-Host "[WARNING] $Message" -ForegroundColor Yellow +} + +function Write-Error { + param([string]$Message) + Write-Host "[ERROR] $Message" -ForegroundColor Red +} + +function Get-Architecture { + $arch = [System.Environment]::GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") + switch ($arch) { + "AMD64" { return "x86_64" } + "ARM64" { return "arm64" } + default { + Write-Error "Unsupported architecture: $arch" + exit 1 + } + } +} + +function Get-LatestVersion { + try { + $response = Invoke-RestMethod -Uri "https://api.github.com/repos/$REPO/releases/latest" + return $response.tag_name + } + catch { + Write-Error "Failed to fetch latest version: $_" + exit 1 + } +} + +function Install-BusterCLI { + $arch = Get-Architecture + Write-Info "Detected architecture: $arch" + + # Get version if not specified + if ($Version -eq "latest") { + Write-Info "Fetching latest version..." + $Version = Get-LatestVersion + Write-Info "Latest version: $Version" + } + + # Construct download URL + $filename = "$BINARY_NAME-windows-$arch.zip" + $downloadUrl = "https://github.com/$REPO/releases/download/$Version/$filename" + + Write-Info "Downloading from: $downloadUrl" + + # Create temporary directory + $tempDir = New-TemporaryFile | ForEach-Object { Remove-Item $_; New-Item -ItemType Directory -Path $_ } + $zipPath = Join-Path $tempDir $filename + + try { + # Download the binary + Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath + Write-Success "Downloaded binary successfully" + + # Extract the archive + Write-Info "Extracting archive..." + Expand-Archive -Path $zipPath -DestinationPath $tempDir -Force + + # Determine install directory + $installDir = "$env:LOCALAPPDATA\Microsoft\WindowsApps" + + # Create install directory if it doesn't exist + if (!(Test-Path $installDir)) { + New-Item -ItemType Directory -Path $installDir -Force | Out-Null + } + + # Move binary to install directory + $binaryPath = Join-Path $tempDir "$BINARY_NAME.exe" + $targetPath = Join-Path $installDir "$INSTALL_NAME.exe" + + if (!(Test-Path $binaryPath)) { + Write-Error "Binary not found after extraction: $binaryPath" + exit 1 + } + + # Remove existing binary if it exists + if (Test-Path $targetPath) { + Remove-Item $targetPath -Force + } + + Move-Item $binaryPath $targetPath + Write-Success "Installed $INSTALL_NAME to $targetPath" + + # Verify installation + Write-Info "Verifying installation..." + Start-Sleep -Seconds 1 + + try { + $versionOutput = & $INSTALL_NAME --version 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Success "Installation verified! $versionOutput" + } else { + Write-Success "Installation successful! Binary is available as '$INSTALL_NAME'" + } + } + catch { + Write-Warning "Binary installed but verification failed. You may need to restart your terminal." + } + + Write-Success "🎉 Installation complete!" + Write-Info "You can now use the '$INSTALL_NAME' command to interact with the Buster CLI" + Write-Info "Try running: $INSTALL_NAME --help" + + } + finally { + # Clean up temporary directory + if (Test-Path $tempDir) { + Remove-Item $tempDir -Recurse -Force + } + } +} + +function Show-Help { + Write-Host @" +Buster CLI Installation Script for Windows PowerShell + +Usage: + .\install.ps1 [-Version ] + iwr -useb https://raw.githubusercontent.com/buster-so/buster/main/scripts/install.ps1 | iex + +Parameters: + -Version Install specific version (default: latest) + +Examples: + .\install.ps1 # Install latest version + .\install.ps1 -Version v1.0.0 # Install specific version + +"@ +} + +# Main execution +if ($args -contains "--help" -or $args -contains "-h") { + Show-Help + exit 0 +} + +Write-Host "" +Write-Info "🚀 Buster CLI Installation Script for Windows" +Write-Info "This script will download and install the latest Buster CLI binary" +Write-Host "" + +try { + Install-BusterCLI +} +catch { + Write-Error "Installation failed: $_" + exit 1 +} \ No newline at end of file diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100644 index 000000000..2020f8da5 --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,324 @@ +#!/bin/bash +set -e + +# Buster CLI Installation Script +# Usage: curl -fsSL https://raw.githubusercontent.com/buster-so/buster/main/scripts/install.sh | bash + +REPO="buster-so/buster" +BINARY_NAME="buster-cli" +INSTALL_NAME="buster" +VERSION="latest" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Print colored output +print_status() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Detect OS and architecture +detect_platform() { + local os="" + local arch="" + local ext="" + + # Detect OS + case "$(uname -s)" in + Darwin*) + os="darwin" + ;; + Linux*) + os="linux" + ;; + CYGWIN*|MINGW*|MSYS*) + os="windows" + ;; + *) + print_error "Unsupported operating system: $(uname -s)" + exit 1 + ;; + esac + + # Detect architecture + case "$(uname -m)" in + x86_64|amd64) + arch="x86_64" + ;; + arm64|aarch64) + if [[ "$os" == "darwin" ]]; then + arch="arm64" + else + arch="aarch64" + fi + ;; + *) + print_error "Unsupported architecture: $(uname -m)" + exit 1 + ;; + esac + + # Set file extension + if [[ "$os" == "windows" ]]; then + ext="zip" + else + ext="tar.gz" + fi + + echo "${os}-${arch}.${ext}" +} + +# Get the latest release version +get_latest_version() { + if command -v curl >/dev/null 2>&1; then + curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/' + elif command -v wget >/dev/null 2>&1; then + wget -qO- "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/' + else + print_error "Neither curl nor wget is available. Please install one of them." + exit 1 + fi +} + +# Download and install +install_cli() { + local platform_suffix=$(detect_platform) + local os=$(echo "$platform_suffix" | cut -d'-' -f1) + local arch=$(echo "$platform_suffix" | cut -d'-' -f2 | cut -d'.' -f1) + + print_status "Detected platform: $os ($arch)" + + # Get version if not specified + if [[ "$VERSION" == "latest" ]]; then + print_status "Fetching latest version..." + VERSION=$(get_latest_version) + if [[ -z "$VERSION" ]]; then + print_error "Failed to fetch latest version" + exit 1 + fi + print_status "Latest version: $VERSION" + fi + + # Construct download URL + local filename="${BINARY_NAME}-${platform_suffix}" + local download_url="https://github.com/${REPO}/releases/download/${VERSION}/${filename}" + + print_status "Downloading from: $download_url" + + # Create temporary directory + local tmp_dir=$(mktemp -d) + trap "rm -rf $tmp_dir" EXIT + + # Download the binary + if command -v curl >/dev/null 2>&1; then + if ! curl -fsSL "$download_url" -o "$tmp_dir/$filename"; then + print_error "Failed to download binary" + exit 1 + fi + elif command -v wget >/dev/null 2>&1; then + if ! wget -q "$download_url" -O "$tmp_dir/$filename"; then + print_error "Failed to download binary" + exit 1 + fi + else + print_error "Neither curl nor wget is available" + exit 1 + fi + + print_success "Downloaded binary successfully" + + # Extract and install based on OS + if [[ "$os" == "windows" ]]; then + install_windows "$tmp_dir/$filename" + else + install_unix "$tmp_dir/$filename" "$os" + fi +} + +# Install on Unix-like systems (macOS, Linux) +install_unix() { + local archive_path="$1" + local os="$2" + + print_status "Extracting archive..." + + # Extract the archive + if ! tar -xzf "$archive_path" -C "$(dirname "$archive_path")"; then + print_error "Failed to extract archive" + exit 1 + fi + + # Determine install directory + local install_dir="$HOME/.local/bin" + + # Create install directory if it doesn't exist + mkdir -p "$install_dir" + + # Move binary to install directory + local binary_path="$(dirname "$archive_path")/$BINARY_NAME" + if [[ ! -f "$binary_path" ]]; then + print_error "Binary not found after extraction: $binary_path" + exit 1 + fi + + if ! mv "$binary_path" "$install_dir/$INSTALL_NAME"; then + print_error "Failed to move binary to $install_dir" + exit 1 + fi + + # Make binary executable + chmod +x "$install_dir/$INSTALL_NAME" + + print_success "Installed $INSTALL_NAME to $install_dir/$INSTALL_NAME" + + # Check if install directory is in PATH + if [[ ":$PATH:" != *":$install_dir:"* ]]; then + print_warning "$install_dir is not in your PATH" + print_status "Add the following line to your shell configuration file (~/.bashrc, ~/.zshrc, etc.):" + echo + echo " export PATH=\"\$HOME/.local/bin:\$PATH\"" + echo + print_status "Then restart your terminal or run: source ~/.bashrc (or ~/.zshrc)" + else + print_success "$install_dir is already in your PATH" + fi +} + +# Install on Windows (using Git Bash/MSYS2/Cygwin) +install_windows() { + local archive_path="$1" + + print_status "Extracting archive..." + + # Extract zip file + if ! unzip -q "$archive_path" -d "$(dirname "$archive_path")"; then + print_error "Failed to extract archive" + exit 1 + fi + + # Determine install directory (use Windows-friendly location) + local install_dir="$LOCALAPPDATA/Microsoft/WindowsApps" + + # Create install directory if it doesn't exist + mkdir -p "$install_dir" + + # Move binary to install directory + local binary_path="$(dirname "$archive_path")/${BINARY_NAME}.exe" + if [[ ! -f "$binary_path" ]]; then + print_error "Binary not found after extraction: $binary_path" + exit 1 + fi + + if ! mv "$binary_path" "$install_dir/${INSTALL_NAME}.exe"; then + print_error "Failed to move binary to $install_dir" + exit 1 + fi + + print_success "Installed $INSTALL_NAME to $install_dir/${INSTALL_NAME}.exe" + print_status "The binary should be available in your PATH automatically" + print_status "You may need to restart your terminal for changes to take effect" +} + +# Verify installation +verify_installation() { + print_status "Verifying installation..." + + # Wait a moment for PATH changes to take effect + sleep 1 + + if command -v "$INSTALL_NAME" >/dev/null 2>&1; then + local version_output + if version_output=$("$INSTALL_NAME" --version 2>/dev/null); then + print_success "Installation verified! $version_output" + else + print_success "Installation successful! Binary is available as '$INSTALL_NAME'" + fi + else + print_warning "Binary installed but not found in PATH. You may need to:" + print_status "1. Restart your terminal" + print_status "2. Add the install directory to your PATH" + print_status "3. Run 'source ~/.bashrc' (or ~/.zshrc)" + fi +} + +# Main execution +main() { + echo + print_status "🚀 Buster CLI Installation Script" + print_status "This script will download and install the latest Buster CLI binary" + echo + + # Check for required tools + if ! command -v tar >/dev/null 2>&1 && [[ "$(uname -s)" != "CYGWIN"* && "$(uname -s)" != "MINGW"* ]]; then + print_error "tar is required but not installed" + exit 1 + fi + + if [[ "$(uname -s)" == "CYGWIN"* || "$(uname -s)" == "MINGW"* ]]; then + if ! command -v unzip >/dev/null 2>&1; then + print_error "unzip is required but not installed" + exit 1 + fi + fi + + # Install the CLI + install_cli + + # Verify installation + verify_installation + + echo + print_success "🎉 Installation complete!" + print_status "You can now use the 'buster' command to interact with the Buster CLI" + print_status "Try running: buster --help" + echo +} + +# Handle script arguments +while [[ $# -gt 0 ]]; do + case $1 in + --version) + VERSION="$2" + shift 2 + ;; + --help) + echo "Buster CLI Installation Script" + echo + echo "Usage: $0 [OPTIONS]" + echo + echo "Options:" + echo " --version VERSION Install specific version (default: latest)" + echo " --help Show this help message" + echo + echo "Examples:" + echo " $0 # Install latest version" + echo " $0 --version v1.0.0 # Install specific version" + echo + exit 0 + ;; + *) + print_error "Unknown option: $1" + echo "Use --help for usage information" + exit 1 + ;; + esac +done + +# Run main function +main \ No newline at end of file