rivet-cli 0.2.0-beta.2

CLI tool to export PostgreSQL and MySQL to Parquet/CSV (local, S3, GCS) with tuning, preflight checks, and SQLite-backed state.
Documentation
name: Release

# Creates a GitHub Release with prebuilt binaries when EITHER:
#   1) You push a version tag:  git tag v0.2.0-beta.1 && git push origin v0.2.0-beta.1
#   2) You run this workflow manually (Actions → Release → Run workflow) after the tag exists on GitHub.
on:
  push:
    tags:
      - "v*"
  workflow_dispatch:
    inputs:
      tag:
        description: "Existing tag to build (e.g. v0.2.0-beta.1) — create & push the tag first"
        required: true
        type: string

permissions:
  contents: write
  packages: write

env:
  CARGO_TERM_COLOR: always

jobs:
  build:
    name: Build ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    env:
      # Correct tag in tarball names when workflow is started manually (GITHUB_REF is then a branch).
      RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}
    strategy:
      fail-fast: false
      matrix:
        include:
          # Linux (glibc) — most servers and desktops
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-latest
            cross: true
          # macOS — Apple Silicon + Intel (GitHub-hosted)
          - target: aarch64-apple-darwin
            os: macos-latest
          - target: x86_64-apple-darwin
            os: macos-15-intel

    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', github.event.inputs.tag) || github.ref }}

      - uses: dtolnay/rust-toolchain@master
        with:
          toolchain: "1.94"
          targets: ${{ matrix.target }}

      - uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}

      - name: Install cross
        if: matrix.cross
        run: cargo install cross --git https://github.com/cross-rs/cross

      - name: Build (native)
        if: ${{ !matrix.cross }}
        run: cargo build --release --target ${{ matrix.target }}

      - name: Build (cross)
        if: matrix.cross
        run: cross build --release --target ${{ matrix.target }}

      - name: Package binary
        shell: bash
        run: |
          tag="${RELEASE_TAG}"
          bin="rivet"
          dir="rivet-${tag}-${{ matrix.target }}"
          mkdir "$dir"
          cp "target/${{ matrix.target }}/release/${bin}" "$dir/"
          cp README.md LICENSE* CHANGELOG.md "$dir/" 2>/dev/null || true
          tar czf "${dir}.tar.gz" "$dir"
          echo "ASSET=${dir}.tar.gz" >> "$GITHUB_ENV"

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: rivet-${{ matrix.target }}
          path: ${{ env.ASSET }}

  release:
    name: Create GitHub Release
    needs: build
    runs-on: ubuntu-latest
    env:
      RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}
      HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts
          merge-multiple: true

      - name: Generate checksums
        run: |
          cd artifacts
          sha256sum *.tar.gz > SHA256SUMS.txt

      - name: Create release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ env.RELEASE_TAG }}
          name: ${{ env.RELEASE_TAG }}
          generate_release_notes: true
          files: |
            artifacts/*.tar.gz
            artifacts/SHA256SUMS.txt

      # Homebrew tap: https://github.com/<owner>/homebrew-rivet (create empty repo once).
      # Add repo secret HOMEBREW_TAP_GITHUB_TOKEN (fine-grained or classic PAT) with Contents: Read and write
      # on homebrew-rivet only.
      - name: Generate Homebrew formula
        env:
          RELEASE_TAG: ${{ env.RELEASE_TAG }}
        run: |
          chmod +x dev/update_homebrew_formula.sh
          GITHUB_REPOSITORY="${{ github.repository }}" \
            ./dev/update_homebrew_formula.sh --tag "${RELEASE_TAG}" --sums-file artifacts/SHA256SUMS.txt

      - name: Push formula to Homebrew tap
        if: env.HOMEBREW_TAP_GITHUB_TOKEN != ''
        env:
          RELEASE_TAG: ${{ env.RELEASE_TAG }}
          TAP_OWNER: ${{ github.repository_owner }}
        run: |
          set -euo pipefail
          git clone "https://x-access-token:${HOMEBREW_TAP_GITHUB_TOKEN}@github.com/${TAP_OWNER}/homebrew-rivet.git" homebrew-tap
          mkdir -p homebrew-tap/Formula
          cp packaging/homebrew/rivet.rb homebrew-tap/Formula/rivet.rb
          cd homebrew-tap
          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git add Formula/rivet.rb
          if git diff --cached --quiet; then
            echo "No changes to formula"
            exit 0
          fi
          git commit -m "rivet ${RELEASE_TAG}"
          git push

  docker:
    name: Build and push Docker image
    needs: release
    runs-on: ubuntu-latest
    env:
      RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}
      REGISTRY: ghcr.io
      IMAGE: ${{ github.repository_owner }}/rivet
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', github.event.inputs.tag) || github.ref }}

      - name: Log in to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          platforms: linux/amd64,linux/arm64
          tags: |
            ghcr.io/${{ env.IMAGE }}:${{ env.RELEASE_TAG }}
            ghcr.io/${{ env.IMAGE }}:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max