# Release - Publish to crates.io
# Triggered by version tags (v*)

name: Release

on:
  push:
    tags:
      - 'v*'
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to release (e.g., v0.9.6)'
        required: true
      dry_run:
        description: 'Dry run (no actual publish)'
        type: boolean
        default: false

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  validate:
    name: Validate Release
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.version }}
      version_number: ${{ steps.version.outputs.version_number }}
      is_prerelease: ${{ steps.version.outputs.is_prerelease }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Extract version
        id: version
        run: |
          if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
            VERSION="${{ github.event.inputs.version }}"
          else
            VERSION="${GITHUB_REF#refs/tags/}"
          fi
          echo "version=$VERSION" >> $GITHUB_OUTPUT

          # Extract version number without 'v' prefix
          VERSION_NUMBER="${VERSION#v}"
          echo "version_number=$VERSION_NUMBER" >> $GITHUB_OUTPUT

          # Check if pre-release
          if [[ "$VERSION" =~ -(alpha|beta|rc) ]]; then
            echo "is_prerelease=true" >> $GITHUB_OUTPUT
          else
            echo "is_prerelease=false" >> $GITHUB_OUTPUT
          fi

          echo "Version: $VERSION (number: $VERSION_NUMBER)"

      - name: Validate version format
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          VERSION_REGEX="^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+(\.[0-9]+)?)?$"
          if ! [[ "$VERSION" =~ $VERSION_REGEX ]]; then
            echo "::error::Invalid version format: $VERSION"
            exit 1
          fi

      - name: Check Cargo.toml version
        run: |
          CARGO_VERSION=$(grep "^version" Cargo.toml | head -1 | cut -d'"' -f2)
          EXPECTED="${{ steps.version.outputs.version_number }}"
          if [[ "$CARGO_VERSION" != "$EXPECTED" ]]; then
            echo "::error::Cargo.toml version mismatch"
            echo "::error::Expected $EXPECTED but found $CARGO_VERSION"
            exit 1
          fi

  publish-crate:
    name: Publish to crates.io
    needs: [validate]
    runs-on: ubuntu-latest
    if: github.event.inputs.dry_run != 'true'
    steps:
      - uses: actions/checkout@v4

      - name: Free disk space
        run: |
          sudo rm -rf /usr/share/dotnet
          sudo rm -rf /opt/ghc
          sudo rm -rf /usr/local/share/boost

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Install system dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y pkg-config libssl-dev build-essential protobuf-compiler

      - name: Cache cargo
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-cargo-publish-${{ hashFiles('**/Cargo.lock') }}

      - name: Verify crate
        run: cargo publish --dry-run --allow-dirty

      - name: Publish to crates.io
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
        run: cargo publish --no-verify --allow-dirty

  release:
    name: Create GitHub Release
    needs: [validate, publish-crate]
    runs-on: ubuntu-latest
    permissions:
      contents: write
    if: github.event.inputs.dry_run != 'true'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Generate changelog
        id: changelog
        run: |
          PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")

          if [ -z "$PREVIOUS_TAG" ]; then
            echo "No previous tag found"
            CHANGELOG="Initial release"
          else
            echo "Generating changelog from $PREVIOUS_TAG to HEAD"
            CHANGELOG=$(git log --oneline "$PREVIOUS_TAG"..HEAD | head -50)
          fi

          {
            echo 'changelog<<EOF'
            echo "$CHANGELOG"
            echo 'EOF'
          } >> $GITHUB_OUTPUT

      - name: Create Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.validate.outputs.version }}
          draft: false
          prerelease: ${{ needs.validate.outputs.is_prerelease }}
          generate_release_notes: true
          body: |
            ## saorsa-core ${{ needs.validate.outputs.version }}

            ### Installation

            Add to your `Cargo.toml`:
            ```toml
            [dependencies]
            saorsa-core = "${{ needs.validate.outputs.version_number }}"
            ```

            Or install via cargo:
            ```bash
            cargo add saorsa-core
            ```

            ### What's Changed

            ${{ steps.changelog.outputs.changelog }}

            ---

            See [crates.io](https://crates.io/crates/saorsa-core) for full documentation.
