quiver-dsp 0.1.0

A modular audio synthesis library using Arrow-style combinators and graph-based patching
Documentation
name: Release

on:
  push:
    tags:
      - 'v[0-9]+.*'
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to release (e.g., v0.2.0)'
        required: true
        type: string

# Only one release at a time
concurrency:
  group: release
  cancel-in-progress: false

env:
  CARGO_TERM_COLOR: always

jobs:
  # Validate and test in parallel where possible
  validate:
    name: Validate Release
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.version }}
    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/}"
          fi
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          echo "Releasing version: $VERSION"

      - name: Validate version format
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          if ! echo "$VERSION" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then
            echo "Invalid version format: $VERSION"
            echo "Expected format: v0.0.0 or v0.0.0-alpha.1"
            exit 1
          fi

      - uses: dtolnay/rust-toolchain@stable

      - name: Check Cargo.toml version matches tag
        run: |
          CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
          TAG_VERSION="${{ steps.version.outputs.version }}"
          TAG_VERSION="${TAG_VERSION#v}"  # Remove 'v' prefix

          if [ "$CARGO_VERSION" != "$TAG_VERSION" ]; then
            echo "Version mismatch!"
            echo "Cargo.toml: $CARGO_VERSION"
            echo "Git tag: $TAG_VERSION"
            exit 1
          fi
          echo "Version match confirmed: $CARGO_VERSION"

  # Run full test suite (can start immediately, runs in parallel with validate)
  test:
    name: Test Suite
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy
      - uses: Swatinem/rust-cache@v2

      # Run all checks in parallel
      - name: Run all checks
        run: |
          cargo fmt --all -- --check &
          cargo clippy --all-features -- -D warnings &
          cargo test --all-features &
          wait

  # Generate changelog (needs validation to pass)
  changelog:
    name: Generate Changelog
    needs: validate
    runs-on: ubuntu-latest
    outputs:
      changelog: ${{ steps.changelog.outputs.changelog }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Install git-cliff
        uses: taiki-e/install-action@git-cliff

      - name: Generate changelog
        id: changelog
        run: |
          # Generate changelog for this release only
          CHANGELOG=$(git cliff --current --strip header)

          # Handle multiline output
          echo "changelog<<EOF" >> $GITHUB_OUTPUT
          echo "$CHANGELOG" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Update CHANGELOG.md
        run: git cliff --output .github/CHANGELOG.md

      - name: Upload changelog artifact
        uses: actions/upload-artifact@v4
        with:
          name: changelog
          path: .github/CHANGELOG.md

  # Create GitHub Release (needs both validation and tests to pass)
  release:
    name: Create Release
    needs: [validate, test, changelog]
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4

      - name: Download changelog
        uses: actions/download-artifact@v4
        with:
          name: changelog
          path: .github/

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.validate.outputs.version }}
          name: ${{ needs.validate.outputs.version }}
          body: ${{ needs.changelog.outputs.changelog }}
          draft: false
          prerelease: ${{ contains(needs.validate.outputs.version, '-') }}
          generate_release_notes: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  # Publish to crates.io (optional - requires CARGO_REGISTRY_TOKEN secret)
  # publish:
  #   name: Publish to crates.io
  #   needs: [validate, test, release]
  #   runs-on: ubuntu-latest
  #   steps:
  #     - uses: actions/checkout@v4
  #     - uses: dtolnay/rust-toolchain@stable
  #
  #     - name: Publish to crates.io
  #       run: cargo publish
  #       env:
  #         CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}