name: Release

on:
  push:
    tags:
      - 'v*'

env:
  CARGO_TERM_COLOR: never

jobs:
  create-release:
    name: Create Release
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v6

    - name: Get version from tag
      id: get_version
      run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

    - name: Read changelog
      id: changelog
      run: |
        # Extract the latest version's changelog
        VERSION="${{ steps.get_version.outputs.VERSION }}"
        VERSION_NO_V="${VERSION#v}"
        CHANGELOG=$(awk -v ver="## \\[$VERSION_NO_V\\]" '
          $0 ~ ver {p=1; next}
          /^## \[/ && p {exit}
          p {print}
        ' CHANGELOG.md)
        echo "CHANGELOG<<EOF" >> $GITHUB_OUTPUT
        echo "$CHANGELOG" >> $GITHUB_OUTPUT
        echo "EOF" >> $GITHUB_OUTPUT

    - name: Create Release
      id: create_release
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        # Check if release already exists
        if gh release view "${{ steps.get_version.outputs.VERSION }}" &>/dev/null; then
          echo "Release ${{ steps.get_version.outputs.VERSION }} already exists, skipping creation"
          echo "RELEASE_EXISTS=true" >> $GITHUB_OUTPUT
        else
          gh release create "${{ steps.get_version.outputs.VERSION }}" \
            --title "${{ steps.get_version.outputs.VERSION }}" \
            --notes "${{ steps.changelog.outputs.CHANGELOG }}" \
            --verify-tag
          echo "RELEASE_EXISTS=false" >> $GITHUB_OUTPUT
        fi

  publish-crates:
    name: Publish to crates.io
    runs-on: ubuntu-latest
    needs: create-release
    steps:
    - uses: actions/checkout@v6

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

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

    # Publish order: leaf dependencies first, then dependents.
    # pmcp-widget-utils (no deps) -> pmcp (depends on widget-utils)
    # -> mcp-tester (depends on pmcp) -> mcp-preview (depends on widget-utils)
    # -> cargo-pmcp (depends on pmcp, mcp-tester, mcp-preview)

    - name: Publish pmcp-widget-utils
      env:
        CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
      run: |
        echo "Publishing pmcp-widget-utils..."
        OUTPUT=$(cargo publish -p pmcp-widget-utils 2>&1) && echo "$OUTPUT" || {
          echo "$OUTPUT"
          if echo "$OUTPUT" | grep -q "already exists"; then
            echo "pmcp-widget-utils already published, continuing..."
          else
            echo "::error::Failed to publish pmcp-widget-utils"
            exit 1
          fi
        }

    - name: Wait for crates.io to index pmcp-widget-utils
      run: sleep 30

    - name: Publish pmcp (core SDK)
      env:
        CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
      run: |
        echo "Publishing pmcp..."
        OUTPUT=$(cargo publish -p pmcp 2>&1) && echo "$OUTPUT" || {
          echo "$OUTPUT"
          if echo "$OUTPUT" | grep -q "already exists"; then
            echo "pmcp already published, continuing..."
          else
            echo "::error::Failed to publish pmcp"
            exit 1
          fi
        }

    - name: Wait for crates.io to index pmcp
      run: sleep 30

    - name: Publish mcp-tester
      env:
        CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
      run: |
        echo "Publishing mcp-tester..."
        OUTPUT=$(cargo publish -p mcp-tester 2>&1) && echo "$OUTPUT" || {
          echo "$OUTPUT"
          if echo "$OUTPUT" | grep -q "already exists"; then
            echo "mcp-tester already published, continuing..."
          else
            echo "::error::Failed to publish mcp-tester"
            exit 1
          fi
        }

    - name: Publish mcp-preview
      env:
        CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
      run: |
        echo "Publishing mcp-preview..."
        OUTPUT=$(cargo publish -p mcp-preview 2>&1) && echo "$OUTPUT" || {
          echo "$OUTPUT"
          if echo "$OUTPUT" | grep -q "already exists"; then
            echo "mcp-preview already published, continuing..."
          else
            echo "::error::Failed to publish mcp-preview"
            exit 1
          fi
        }

    - name: Wait for crates.io to index mcp-tester and mcp-preview
      run: sleep 30

    - name: Publish cargo-pmcp
      env:
        CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
      run: |
        echo "Publishing cargo-pmcp..."
        OUTPUT=$(cargo publish -p cargo-pmcp 2>&1) && echo "$OUTPUT" || {
          echo "$OUTPUT"
          if echo "$OUTPUT" | grep -q "already exists"; then
            echo "cargo-pmcp already published, continuing..."
          else
            echo "::error::Failed to publish cargo-pmcp"
            exit 1
          fi
        }

  publish-mcp:
    name: Publish to MCP Registry
    runs-on: ubuntu-latest
    needs: publish-crates
    permissions:
      id-token: write  # Required for OIDC authentication
      contents: read
    steps:
    - uses: actions/checkout@v6

    - name: Wait for crates.io availability
      run: |
        echo "Waiting 60 seconds for crates.io to index all packages..."
        sleep 60

    - name: Install MCP Publisher
      run: |
        PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]')
        ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
        curl -sL "https://github.com/modelcontextprotocol/registry/releases/download/v1.2.3/mcp-publisher_1.2.3_${PLATFORM}_${ARCH}.tar.gz" | tar xz
        chmod +x mcp-publisher

    - name: Login to MCP Registry
      run: ./mcp-publisher login github-oidc

    - name: Publish to MCP Registry
      run: ./mcp-publisher publish
