meilibridge 0.1.6

High-performance PostgreSQL to Meilisearch connector
Documentation
name: Release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write
  packages: write
  pull-requests: write

jobs:
  # Validate version format
  validate-version:
    name: Validate Version
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.version }}
      version_without_v: ${{ steps.version.outputs.version_without_v }}
    steps:
    - name: Determine version
      id: version
      run: |
        VERSION="${{ github.ref_name }}"
        
        # Validate version format
        if ! [[ "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
          echo "Invalid version format: $VERSION"
          echo "Expected format: v1.0.0, v1.0.0-beta.1, etc."
          exit 1
        fi
        
        echo "version=$VERSION" >> $GITHUB_OUTPUT
        echo "version_without_v=${VERSION#v}" >> $GITHUB_OUTPUT


  # Build release artifacts
  build-artifacts:
    name: Build Release Artifacts
    needs: [validate-version]
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            asset_name: meilibridge-linux-amd64
          # ARM64 Linux cross-compilation removed due to complexity
          # Can be re-added with cross tool or native runners
          - os: macos-latest
            target: x86_64-apple-darwin
            asset_name: meilibridge-darwin-amd64
          - os: macos-latest
            target: aarch64-apple-darwin
            asset_name: meilibridge-darwin-arm64
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            asset_name: meilibridge-windows-amd64.exe
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Update version in Cargo.toml
      shell: bash
      run: |
        VERSION="${{ needs.validate-version.outputs.version_without_v }}"
        if [[ "${{ matrix.os }}" == "macos-latest" ]]; then
          # macOS requires backup extension for sed -i
          sed -i.bak "s/^version = .*/version = \"$VERSION\"/" Cargo.toml
          rm -f Cargo.toml.bak
        else
          # Linux and Windows (Git Bash) don't require backup extension
          sed -i "s/^version = .*/version = \"$VERSION\"/" Cargo.toml
        fi
        echo "Updated Cargo.toml version to: $VERSION"
    
    - name: Install Rust
      uses: dtolnay/rust-toolchain@stable
      with:
        targets: ${{ matrix.target }}
    
    - name: Build release binary
      run: |
        cargo build --release --target ${{ matrix.target }}
        
    - name: Package binary
      shell: bash
      run: |
        cd target/${{ matrix.target }}/release
        if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
          7z a -tzip "../../../${{ matrix.asset_name }}.zip" meilibridge.exe
        else
          tar czf "../../../${{ matrix.asset_name }}.tar.gz" meilibridge
        fi
    
    - name: Upload artifacts
      uses: actions/upload-artifact@v4
      with:
        name: ${{ matrix.asset_name }}
        path: |
          *.tar.gz
          *.zip


  # Create GitHub release
  create-release:
    name: Create GitHub Release
    needs: [validate-version, build-artifacts]
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0
    
    - name: Download artifacts
      uses: actions/download-artifact@v4
      with:
        path: ./artifacts
    
    - name: Generate changelog
      id: changelog
      run: |
        # Get the previous tag
        PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
        
        if [[ -z "$PREV_TAG" ]]; then
          echo "No previous tag found, including all commits"
          RANGE=""
        else
          echo "Previous tag: $PREV_TAG"
          RANGE="$PREV_TAG.."
        fi
        
        # Generate changelog
        {
          echo "## What's Changed"
          echo ""
          
          # Features
          echo "### 🚀 Features"
          git log $RANGE --pretty=format:"* %s (%h) - %an" --grep="^feat" | head -20 || echo "* No new features"
          echo ""
          
          # Bug fixes
          echo "### 🐛 Bug Fixes"
          git log $RANGE --pretty=format:"* %s (%h) - %an" --grep="^fix" | head -20 || echo "* No bug fixes"
          echo ""
          
          # Other changes
          echo "### 📚 Documentation & Other Changes"
          git log $RANGE --pretty=format:"* %s (%h) - %an" --grep="^docs\|^chore\|^refactor\|^style\|^test" | head -20 || echo "* No other changes"
          echo ""
          
          # Contributors
          echo "### 👥 Contributors"
          git log $RANGE --pretty=format:"%an" | sort -u | sed 's/^/* /' | head -20
          echo ""
          
          echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG:-${{ needs.validate-version.outputs.version }}}...${{ needs.validate-version.outputs.version }}"
        } > CHANGELOG_RELEASE.md
        
        # Read changelog for output
        EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
        echo "body<<$EOF" >> $GITHUB_OUTPUT
        cat CHANGELOG_RELEASE.md >> $GITHUB_OUTPUT
        echo "$EOF" >> $GITHUB_OUTPUT
    
    - name: Create release
      uses: softprops/action-gh-release@v1
      with:
        tag_name: ${{ needs.validate-version.outputs.version }}
        name: Release ${{ needs.validate-version.outputs.version }}
        body: ${{ steps.changelog.outputs.body }}
        draft: false
        prerelease: ${{ contains(needs.validate-version.outputs.version, '-') }}
        files: |
          artifacts/**/*.tar.gz
          artifacts/**/*.zip
        generate_release_notes: true

  # Publish to crates.io
  publish-crates:
    name: Publish to crates.io
    needs: [validate-version]
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Install Rust
      uses: dtolnay/rust-toolchain@stable
    
    - name: Update version in Cargo.toml
      run: |
        VERSION="${{ needs.validate-version.outputs.version_without_v }}"
        sed -i "s/^version = .*/version = \"$VERSION\"/" Cargo.toml
    
    - name: Verify package
      run: cargo package --allow-dirty
    
    - name: Publish to crates.io
      env:
        CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
      run: |
        cargo publish --allow-dirty --token $CARGO_REGISTRY_TOKEN

  # Build and push Docker images
  docker-release:
    name: Docker Release
    needs: [validate-version]
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Update version in Cargo.toml
      run: |
        VERSION="${{ needs.validate-version.outputs.version_without_v }}"
        sed -i "s/^version = .*/version = \"$VERSION\"/" Cargo.toml
        echo "Updated Cargo.toml version to: $VERSION"
    
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3
    
    - name: Log in to Docker Hub
      uses: docker/login-action@v3
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}
    
    - name: Build and push Docker image
      uses: docker/build-push-action@v5
      with:
        context: .
        file: ./docker/Dockerfile
        platforms: linux/amd64
        # Add linux/arm64 when needed - note this significantly increases build time
        push: true
        tags: |
          ${{ secrets.DOCKERHUB_USERNAME }}/meilibridge:${{ needs.validate-version.outputs.version_without_v }}
          ${{ secrets.DOCKERHUB_USERNAME }}/meilibridge:latest
        build-args: |
          VERSION=${{ needs.validate-version.outputs.version_without_v }}
        cache-from: type=gha
        cache-to: type=gha,mode=max

  # Update changelog on main branch
  update-changelog:
    name: Update Changelog
    needs: [validate-version, create-release]
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
    - uses: actions/checkout@v4
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        persist-credentials: true
        ref: main
    
    - name: Update CHANGELOG.md
      run: |
        VERSION="${{ needs.validate-version.outputs.version_without_v }}"
        DATE=$(date +%Y-%m-%d)
        
        # Update CHANGELOG.md only
        sed -i "s/## \[Unreleased\]/## [Unreleased]\n\n## [$VERSION] - $DATE/" CHANGELOG.md
    
    - name: Configure Git
      run: |
        git config --global user.name "Github Actions[bot]"
        git config --global user.email "github-actions[bot]@users.noreply.github.com"
    
    - name: Commit and push changes
      run: |
        git add CHANGELOG.md
        if git diff --staged --quiet; then
          echo "No changes to commit"
        else
          git commit -m "chore: update CHANGELOG.md for ${{ needs.validate-version.outputs.version }} release

        Updates CHANGELOG.md with release date for version ${{ needs.validate-version.outputs.version }}.
        [skip ci]"
          git push
        fi