name: release

on:
  push:
    tags: ['v[0-9]+.*']
  workflow_dispatch:
    inputs:
      dry-run:
        description: 'Skip actual publishing (test build only)'
        required: false
        type: boolean
        default: true

env:
  CARGO_TERM_COLOR: always

jobs:

  initialize:
    uses: ./.github/workflows/core--initializer.yaml

  test:
    needs: [initialize]
    strategy:
      fail-fast: false
      matrix:
        platform: ${{ fromJSON(needs.initialize.outputs.platforms) }}
        exclude: ${{ fromJSON(needs.initialize.outputs.matrix-exclusions) }}
    runs-on: ${{ matrix.platform }}
    steps:

      - name: Checkout
        uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

      - name: Check Formatting
        if: matrix.platform == 'ubuntu-latest'
        run: cargo fmt --all -- --check

      - name: Run Clippy
        if: matrix.platform == 'ubuntu-latest'
        run: cargo clippy --all-targets --all-features -- -D warnings

      - name: Build
        run: cargo build --release

      - name: Test
        run: cargo test --release

  build-binaries:
    needs: [initialize, test]
    strategy:
      fail-fast: false
      matrix:
        platform: ${{ fromJSON(needs.initialize.outputs.platforms) }}
        exclude: ${{ fromJSON(needs.initialize.outputs.matrix-exclusions) }}
    runs-on: ${{ matrix.platform }}
    steps:

      - name: Checkout
        uses: actions/checkout@v4

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

      - name: Build Release Binary
        run: cargo build --release

      - name: Determine Binary Name
        id: binary
        shell: bash
        run: |
          target="${{ fromJSON(needs.initialize.outputs.rust-targets)[matrix.platform] }}"
          if [[ "${{ matrix.platform }}" == "windows-latest" ]]; then
            binary_name="nb-mcp-${target}.exe"
            cp target/release/nb-mcp.exe "${binary_name}"
          else
            binary_name="nb-mcp-${target}"
            cp target/release/nb-mcp "${binary_name}"
          fi
          echo "name=${binary_name}" >>${GITHUB_OUTPUT}

      - name: Upload Binary Artifact
        uses: actions/upload-artifact@v4
        with:
          name: binary-${{ matrix.platform }}
          path: ${{ steps.binary.outputs.name }}

  publish-crates-io:
    if: ${{ !inputs.dry-run && startsWith(github.ref, 'refs/tags/') }}
    needs: [test]
    runs-on: ubuntu-latest
    environment: crates-io
    permissions:
      id-token: write  # Required for OIDC token exchange
    steps:

      - name: Checkout
        uses: actions/checkout@v4

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

      - name: Authenticate with crates.io
        uses: rust-lang/crates-io-auth-action@v1
        id: auth

      - name: Publish to crates.io
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
        run: cargo publish

  publish-github:
    if: ${{ !inputs.dry-run && startsWith(github.ref, 'refs/tags/') }}
    needs: [initialize, build-binaries]
    runs-on: ubuntu-latest
    permissions:
      attestations: write
      contents: write
      id-token: write
    steps:

      - name: Checkout
        uses: actions/checkout@v4

      - name: Download All Binaries
        uses: actions/download-artifact@v4
        with:
          path: artifacts
          pattern: binary-*
          merge-multiple: true

      - name: Generate Checksums
        working-directory: artifacts
        run: |
          sha256sum nb-mcp-* >SHA256SUMS.txt

      - name: Attest Build Provenance
        uses: actions/attest-build-provenance@v2
        with:
          subject-path: |
            artifacts/SHA256SUMS.txt
            artifacts/nb-mcp-*

      - name: Create Release
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: |
          gh release create '${{ github.ref_name }}' \
            --repo '${{ github.repository }}' \
            --generate-notes

      - name: Upload Release Artifacts
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: |
          gh release upload '${{ github.ref_name }}' \
            artifacts/* \
            --repo '${{ github.repository }}'
