market-data-source 0.3.0

High-performance synthetic market data generator with financial precision. Generate unlimited OHLC candles, tick data, and realistic trading scenarios for backtesting and research.
Documentation
name: Release Validation

on:
  push:
    tags:
      - 'v*'
      - '[0-9]+.[0-9]+.[0-9]+'
  workflow_dispatch:

permissions:
  contents: read
  id-token: write

jobs:
  validate-version:
    name: Validate Version Consistency
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Get tag version
        id: tag
        run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
      
      - name: Check Cargo.toml version
        run: |
          cargo_version=$(grep "^version" Cargo.toml | head -1 | cut -d'"' -f2)
          tag_version="${{ steps.tag.outputs.version }}"
          tag_version=${tag_version#v}  # Remove 'v' prefix if present
          
          if [ "$cargo_version" != "$tag_version" ]; then
            echo "Version mismatch: Cargo.toml has $cargo_version but tag is $tag_version"
            exit 1
          fi
          echo "Version check passed: $cargo_version"
      
      - name: Check pyproject.toml version
        run: |
          py_version=$(grep "^version" pyproject.toml | head -1 | cut -d'"' -f2)
          tag_version="${{ steps.tag.outputs.version }}"
          tag_version=${tag_version#v}  # Remove 'v' prefix if present
          
          if [ "$py_version" != "$tag_version" ]; then
            echo "Version mismatch: pyproject.toml has $py_version but tag is $tag_version"
            exit 1
          fi
          echo "Python version check passed: $py_version"
  
  full-test-suite:
    name: Complete Test Suite
    needs: validate-version
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: dtolnay/rust-toolchain@stable
      
      - uses: Swatinem/rust-cache@v2
      
      - name: Run all tests
        run: cargo test --all-features --verbose
        env:
          CARGO_BUILD_JOBS: ${{ runner.os == 'Windows' && '1' || '4' }}
      
      - name: Run benchmarks (smoke test)
        run: cargo bench --no-run --all-features
  
  quality-gates:
    name: Quality Gates
    needs: validate-version
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy, rustfmt
      
      - name: Check formatting
        run: cargo fmt --all -- --check
      
      - name: Run clippy
        run: cargo clippy --all-features --all-targets -- -D warnings
      
      - name: Build documentation
        run: cargo doc --no-deps --all-features
        env:
          RUSTDOCFLAGS: -D warnings
  
  build-artifacts:
    name: Build Release Artifacts
    needs: [full-test-suite, quality-gates]
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
          - os: windows-latest
            target: x86_64-pc-windows-msvc
          - os: macos-latest
            target: x86_64-apple-darwin
          - os: macos-latest
            target: aarch64-apple-darwin
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      
      - name: Build release binary
        run: cargo build --release --all-features --target ${{ matrix.target }}
      
      - name: Package binary
        run: |
          cd target/${{ matrix.target }}/release
          if [ "${{ runner.os }}" = "Windows" ]; then
            7z a ../../../market-data-source-${{ matrix.target }}.zip market_data_source.exe
          else
            tar czf ../../../market-data-source-${{ matrix.target }}.tar.gz market_data_source
          fi
        shell: bash
      
      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: binaries-${{ matrix.target }}
          path: |
            market-data-source-*.tar.gz
            market-data-source-*.zip
  
  build-python-wheels:
    name: Build Python Wheels
    needs: [full-test-suite, quality-gates]
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
      
      - uses: dtolnay/rust-toolchain@stable
      
      - name: Install system dependencies (Linux)
        if: runner.os == 'Linux'
        run: |
          sudo apt-get update
          sudo apt-get install -y fontconfig libfontconfig1-dev
      
      - name: Install maturin
        run: pip install maturin
      
      - name: Build wheels
        run: |
          cd market-data-source-python
          maturin build --release --out ../dist
      
      - name: Test wheel installation
        run: |
          pip install dist/*.whl
          python -c "import market_data_source; print(market_data_source.__version__)"
      
      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: python-wheels-${{ matrix.os }}-py${{ matrix.python-version }}
          path: dist/*.whl
  
  dry-run-publish:
    name: Dry Run Publication
    needs: [build-artifacts, build-python-wheels]
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - uses: dtolnay/rust-toolchain@stable
      
      - name: Check crates.io publish (dry run)
        run: cargo publish --dry-run --all-features
      
      - name: Download Python wheels
        uses: actions/download-artifact@v3
        with:
          pattern: python-wheels-*
          merge-multiple: true
          path: dist/
      
      - name: Check wheel contents
        run: |
          pip install twine
          twine check dist/*.whl
      
      - name: List publishable artifacts
        run: |
          echo "=== Rust Package ==="
          cargo package --list
          echo ""
          echo "=== Python Wheels ==="
          ls -la dist/
  
  create-release-notes:
    name: Generate Release Notes
    needs: dry-run-publish
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
    
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: Get version
        id: version
        run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
      
      - name: Extract changelog entry
        id: changelog
        run: |
          version="${{ steps.version.outputs.version }}"
          version=${version#v}  # Remove 'v' prefix if present
          
          # Extract the section for this version from CHANGELOG.md
          awk -v ver="$version" '
            /^## \[.*\]/ {
              if (found) exit
              if (index($0, ver) > 0) found=1
              next
            }
            found { print }
          ' CHANGELOG.md > release_notes.md
          
          if [ ! -s release_notes.md ]; then
            echo "No release notes found for version $version"
            echo "This is release $version of market-data-source." > release_notes.md
          fi
      
      - name: Upload release notes
        uses: actions/upload-artifact@v4
        with:
          name: release-notes
          path: release_notes.md