name: CLI Release on: push: branches: - main paths: - 'cli/**' - '.github/workflows/cli-release.yml' workflow_dispatch: # Add permissions for creating releases permissions: contents: write pull-requests: write jobs: build: strategy: matrix: include: - os: ubuntu-latest target: x86_64-unknown-linux-gnu artifact_name: buster-cli-linux-x86_64.tar.gz use_tar: true - os: macos-latest target: x86_64-apple-darwin artifact_name: buster-cli-darwin-x86_64.tar.gz use_tar: true - os: macos-latest target: aarch64-apple-darwin artifact_name: buster-cli-darwin-arm64.tar.gz use_tar: true - 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 uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: stable target: ${{ matrix.target }} profile: minimal override: true - 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: | if [[ "${{ runner.os }}" == "macOS" ]]; then brew install libpq echo "PKG_CONFIG_PATH=$(brew --prefix libpq)/lib/pkgconfig" >> $GITHUB_ENV echo "LIBRARY_PATH=$(brew --prefix libpq)/lib" >> $GITHUB_ENV echo "LD_LIBRARY_PATH=$(brew --prefix libpq)/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV # For macOS, we might need to explicitly tell rustc where to find the library. # Adding common libpq paths to rustflags echo "RUSTFLAGS=-L $(brew --prefix libpq)/lib" >> $GITHUB_ENV elif [[ "${{ runner.os }}" == "Linux" ]]; then sudo apt-get update -y sudo apt-get install -y libpq-dev fi 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 echo '[profile.release]' > .cargo/config.toml echo 'lto = true' >> .cargo/config.toml echo 'codegen-units = 1' >> .cargo/config.toml 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: | 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 working-directory: ./cli run: | cd target/${{ matrix.target }}/release tar czf ${{ matrix.artifact_name }} buster-cli if [[ "${{ runner.os }}" == "macOS" ]]; then shasum -a 256 ${{ matrix.artifact_name }} > ${{ matrix.artifact_name }}.sha256 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: Upload artifacts uses: actions/upload-artifact@v4 with: name: buster-cli-${{ matrix.target }} path: | cli/target/${{ matrix.target }}/release/${{ matrix.artifact_name }} cli/target/${{ matrix.target }}/release/${{ matrix.artifact_name }}.sha256 retention-days: 1 release: needs: build runs-on: ubuntu-latest outputs: cli_version: ${{ steps.get_version.outputs.version }} cli_tag_name: ${{ steps.create_the_release.outputs.tag_name }} steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Download all artifacts uses: actions/download-artifact@v4 - name: Extract version from Cargo.toml id: get_version run: | VERSION=$(awk -F'"' '/^version =/ {print $2}' cli/cli/Cargo.toml) echo "version=$VERSION" >> $GITHUB_OUTPUT echo "Extracted version: $VERSION" - name: Create Release id: create_the_release uses: softprops/action-gh-release@v2.0.0 with: tag_name: v${{ steps.get_version.outputs.version }} name: Release v${{ steps.get_version.outputs.version }} files: | **/buster-cli-linux-x86_64.tar.gz **/buster-cli-linux-x86_64.tar.gz.sha256 **/buster-cli-darwin-x86_64.tar.gz **/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 draft: false prerelease: false generate_release_notes: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} update_homebrew_tap: name: Update Homebrew Tap needs: release runs-on: ubuntu-latest if: needs.release.outputs.cli_tag_name != '' && needs.release.outputs.cli_version != '' steps: - name: Get release version and tag from previous job id: release_info run: | echo "RELEASE_VERSION=${{ needs.release.outputs.cli_version }}" >> $GITHUB_ENV echo "RELEASE_TAG=${{ needs.release.outputs.cli_tag_name }}" >> $GITHUB_ENV echo "Using version: ${{ needs.release.outputs.cli_version }} from tag: ${{ needs.release.outputs.cli_tag_name }}" - name: Set up GitHub CLI uses: actions/setup-node@v4 with: node-version: '20' - name: Download SHA256 sums from GitHub Release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} run: | gh release download ${{ env.RELEASE_TAG }} --pattern '*.sha256' -R $GH_REPO --clobber echo "Downloaded SHA256 files:" ls -la *.sha256 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 with: repository: buster-so/buster-homebrew token: ${{ secrets.HOMEBREW_TAP_TOKEN }} path: buster-homebrew - name: Configure Git working-directory: ./buster-homebrew run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - name: Update Homebrew Formula working-directory: ./buster-homebrew env: VERSION: ${{ env.RELEASE_VERSION }} TAG: ${{ env.RELEASE_TAG }} # This will be vX.Y.Z SHA_ARM64: ${{ env.SHA_ARM64 }} SHA_INTEL: ${{ env.SHA_INTEL }} SHA_LINUX: ${{ env.SHA_LINUX }} REPO_OWNER: ${{ github.repository_owner }} # Needed for URLs run: | FORMULA_FILE="Formula/buster.rb" TEMP_FORMULA_FILE="Formula/buster.rb.tmp" # URLs for artifacts, using REPO_OWNER and TAG URL_BASE="https://github.com/$REPO_OWNER/buster/releases/download/$TAG" URL_ARM64="$URL_BASE/buster-cli-darwin-arm64.tar.gz" URL_INTEL="$URL_BASE/buster-cli-darwin-x86_64.tar.gz" URL_LINUX="$URL_BASE/buster-cli-linux-x86_64.tar.gz" echo "Updating $FORMULA_FILE with Version: $VERSION" echo "ARM64 URL: $URL_ARM64, SHA: $SHA_ARM64" echo "Intel URL: $URL_INTEL, SHA: $SHA_INTEL" echo "Linux URL: $URL_LINUX, SHA: $SHA_LINUX" # Update version sed "s/^ version .*/ version \\"$VERSION\\"/" "$FORMULA_FILE" > "$TEMP_FORMULA_FILE" && mv "$TEMP_FORMULA_FILE" "$FORMULA_FILE" # Update top-level URL and SHA (typically ARM) sed -E "s#^ url .*# url \\"$URL_ARM64\\"#" "$FORMULA_FILE" > "$TEMP_FORMULA_FILE" && mv "$TEMP_FORMULA_FILE" "$FORMULA_FILE" sed "s/^ sha256 .*/ sha256 \\"$SHA_ARM64\\"/" "$FORMULA_FILE" > "$TEMP_FORMULA_FILE" && mv "$TEMP_FORMULA_FILE" "$FORMULA_FILE" # Update on_macos -> on_arm awk ' BEGIN { in_arm_block = 0; } /on_macos do/,/end/ { if (/on_arm do/) { in_arm_block = 1; print; next; } if (in_arm_block && /url /) { print " url \\"\\"" ENVIRON["URL_ARM64"] "\\"\\"" next } if (in_arm_block && /sha256 /) { print " sha256 \\"\\"" ENVIRON["SHA_ARM64"] "\\"\\"" next } if (in_arm_block && /end/) { in_arm_block = 0; } } { print } ' "$FORMULA_FILE" > "$TEMP_FORMULA_FILE" && mv "$TEMP_FORMULA_FILE" "$FORMULA_FILE" # Update on_macos -> on_intel awk ' BEGIN { in_intel_block = 0; } /on_macos do/,/end/ { if (/on_intel do/) { in_intel_block = 1; print; next; } if (in_intel_block && /url /) { print " url \\"\\"" ENVIRON["URL_INTEL"] "\\"\\"" next } if (in_intel_block && /sha256 /) { print " sha256 \\"\\"" ENVIRON["SHA_INTEL"] "\\"\\"" next } if (in_intel_block && /end/) { in_intel_block = 0; } } { print } ' "$FORMULA_FILE" > "$TEMP_FORMULA_FILE" && mv "$TEMP_FORMULA_FILE" "$FORMULA_FILE" # Update on_linux awk ' BEGIN { in_linux_block = 0; } /on_linux do/,/end/ { if (/on_linux do/) { in_linux_block = 1; print; next; } if (in_linux_block && /url /) { print " url \\"\\"" ENVIRON["URL_LINUX"] "\\"\\"" next } if (in_linux_block && /sha256 /) { print " sha256 \\"\\"" ENVIRON["SHA_LINUX"] "\\"\\"" next } if (in_linux_block && /end/) { in_linux_block = 0; } } { print } ' "$FORMULA_FILE" > "$TEMP_FORMULA_FILE" && mv "$TEMP_FORMULA_FILE" "$FORMULA_FILE" echo "--- Formula file after updates ---" cat "$FORMULA_FILE" echo "--- End of formula file ---" - name: Commit and push changes to Homebrew tap working-directory: ./buster-homebrew run: | git add Formula/buster.rb if git diff --staged --quiet; then echo "No changes to commit to Homebrew tap." else git commit -m "Update buster formula to version ${{ env.RELEASE_VERSION }} [skip ci]" git push echo "Pushed updated formula to buster-so/buster-homebrew." fi