midstream 0.2.0

Real-time LLM streaming with inflight analysis
Documentation
name: Release

on:
  push:
    tags:
      - 'v*.*.*'
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to release (e.g., 1.0.0)'
        required: true
        type: string

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  # Create GitHub release
  create-release:
    name: Create Release
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.version }}
      upload_url: ${{ steps.create_release.outputs.upload_url }}

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

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

      - name: Generate changelog
        id: changelog
        run: |
          # Install git-cliff if needed
          if ! command -v git-cliff &> /dev/null; then
            cargo install git-cliff
          fi

          # Generate changelog
          git-cliff --latest --strip all > CHANGELOG.md

          echo "Generated changelog:"
          cat CHANGELOG.md

      - name: Create GitHub release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: v${{ steps.version.outputs.version }}
          release_name: Release v${{ steps.version.outputs.version }}
          body_path: CHANGELOG.md
          draft: false
          prerelease: false

  # Build release binaries
  build-release:
    name: Build Release (${{ matrix.target }})
    needs: create-release
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            artifact_name: midstream-linux-x86_64
          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            artifact_name: midstream-linux-aarch64
          - os: macos-latest
            target: x86_64-apple-darwin
            artifact_name: midstream-macos-x86_64
          - os: macos-latest
            target: aarch64-apple-darwin
            artifact_name: midstream-macos-aarch64
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact_name: midstream-windows-x86_64

    steps:
      - uses: actions/checkout@v4

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Setup cache
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: "release-${{ matrix.target }}"

      - name: Install cross-compilation tools (Linux ARM)
        if: matrix.target == 'aarch64-unknown-linux-gnu'
        run: |
          sudo apt-get update
          sudo apt-get install -y gcc-aarch64-linux-gnu

      - name: Build release binary
        run: cargo build --release --target ${{ matrix.target }} --all-features

      - name: Package binary (Unix)
        if: matrix.os != 'windows-latest'
        run: |
          cd target/${{ matrix.target }}/release
          tar czf ${{ matrix.artifact_name }}.tar.gz midstream
          mv ${{ matrix.artifact_name }}.tar.gz ../../../

      - name: Package binary (Windows)
        if: matrix.os == 'windows-latest'
        run: |
          cd target/${{ matrix.target }}/release
          7z a ${{ matrix.artifact_name }}.zip midstream.exe
          move ${{ matrix.artifact_name }}.zip ../../../

      - name: Upload release asset
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ needs.create-release.outputs.upload_url }}
          asset_path: ./${{ matrix.artifact_name }}.${{ matrix.os == 'windows-latest' && 'zip' || 'tar.gz' }}
          asset_name: ${{ matrix.artifact_name }}.${{ matrix.os == 'windows-latest' && 'zip' || 'tar.gz' }}
          asset_content_type: application/octet-stream

  # Publish crates to crates.io
  publish-crates:
    name: Publish to crates.io
    needs: create-release
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')

    steps:
      - uses: actions/checkout@v4

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

      - name: Setup cache
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: "publish"

      - name: Update crate versions
        run: |
          VERSION="${{ needs.create-release.outputs.version }}"

          # Update workspace crate versions
          for crate in temporal-compare nanosecond-scheduler temporal-attractor-studio temporal-neural-solver strange-loop; do
            sed -i "s/^version = \".*\"/version = \"$VERSION\"/" crates/$crate/Cargo.toml
          done

          # Update main crate version
          sed -i "s/^version = \".*\"/version = \"$VERSION\"/" Cargo.toml

      - name: Verify build after version update
        run: cargo build --workspace --all-features

      - name: Publish crates in dependency order
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: |
          # Publish in order of dependencies
          cargo publish -p temporal-compare --allow-dirty
          sleep 10

          cargo publish -p nanosecond-scheduler --allow-dirty
          sleep 10

          cargo publish -p temporal-attractor-studio --allow-dirty
          sleep 10

          cargo publish -p temporal-neural-solver --allow-dirty
          sleep 10

          cargo publish -p strange-loop --allow-dirty
          sleep 10

          # Finally publish main crate
          cargo publish --allow-dirty

  # Update documentation
  update-docs:
    name: Update Documentation
    needs: [create-release, publish-crates]
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

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

      - name: Setup cache
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: "docs-release"

      - name: Build documentation
        run: cargo doc --workspace --all-features --no-deps

      - name: Add version badge to docs
        run: |
          VERSION="${{ needs.create-release.outputs.version }}"
          echo "<div style='padding: 1em; background: #4CAF50; color: white;'>Version: $VERSION</div>" \
            > target/doc/version.html

      - name: Deploy documentation
        uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./target/doc
          destination_dir: docs/v${{ needs.create-release.outputs.version }}

      - name: Update latest docs symlink
        run: |
          git checkout gh-pages
          ln -sfn v${{ needs.create-release.outputs.version }} docs/latest
          git add docs/latest
          git commit -m "Update latest docs to v${{ needs.create-release.outputs.version }}"
          git push

  # Notify on completion
  release-complete:
    name: Release Complete
    needs: [create-release, build-release, publish-crates, update-docs]
    runs-on: ubuntu-latest
    if: always()

    steps:
      - name: Check release status
        run: |
          if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then
            echo "❌ Release process encountered errors"
            exit 1
          fi
          echo "✅ Release v${{ needs.create-release.outputs.version }} completed successfully!"
          echo "📦 Crates published to crates.io"
          echo "📚 Documentation updated"
          echo "🎉 Binaries available on GitHub Releases"