vor 0.2.1

Cross-platform performance instrumentation with an in-app egui panel and live system and GPU metrics.
Documentation
# Build the Python bindings (bindings/python) into wheels + sdist and,
# on a `v*` tag, publish to PyPI via trusted publishing (OIDC) - PyPI
# trusts this repo/workflow, so no token is stored on GitHub. The same
# tag also publishes the Rust crates (see crates.yml), since the crate
# and the PyPI package share one version. Wheels are abi3-py39, so one
# wheel per platform covers all CPython >= 3.9. A tag only publishes
# after the version-sync + smoke jobs pass.
#
# Wheels carry GPU rows: macOS builds with `--features mac` (sudo-free
# IOKit/IOReport), Linux with `--features cuda` (NVML, loaded from the
# driver at run time). NVML init degrades gracefully when no NVIDIA
# driver is present, so the Linux wheel is safe on CPU-only boxes - the
# gpu_* rows just read zero there.
name: python

on:
  push:
    tags: ["v*"]
  pull_request:
    paths:
      - "bindings/python/**"
      - "src/**"
      - ".github/workflows/python.yml"
  workflow_dispatch:

permissions:
  contents: read

jobs:
  wheels:
    name: wheels (${{ matrix.platform.target }})
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      fail-fast: false
      matrix:
        platform:
          - { runner: macos-14, target: aarch64-apple-darwin, args: "--features mac" }
          - { runner: ubuntu-latest, target: x86_64, args: "--features cuda" }
    steps:
      - uses: actions/checkout@v4
      - uses: PyO3/maturin-action@v1
        with:
          working-directory: bindings/python
          # vor's MSRV is 1.96; the action's pinned default lags it.
          rust-toolchain: stable
          target: ${{ matrix.platform.target }}
          manylinux: auto
          args: --release --out dist ${{ matrix.platform.args }}
      - uses: actions/upload-artifact@v4
        with:
          name: wheels-${{ matrix.platform.target }}
          path: bindings/python/dist

  sdist:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: PyO3/maturin-action@v1
        with:
          working-directory: bindings/python
          rust-toolchain: stable
          command: sdist
          args: --out dist
      - uses: actions/upload-artifact@v4
        with:
          name: sdist
          path: bindings/python/dist

  versions:
    name: versions in sync
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # The Rust crate and the PyPI package share one version; a release
      # tag must not ship a drifted pair.
      - run: |
          rust=$(grep -m1 '^version = ' Cargo.toml | cut -d'"' -f2)
          py=$(grep -m1 '^version = ' bindings/python/Cargo.toml | cut -d'"' -f2)
          echo "rust=$rust pypi=$py"
          test "$rust" = "$py"

  smoke:
    name: smoke (capture from Python, read back in Rust)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable # for the cargo-run read-back (MSRV 1.96)
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - uses: PyO3/maturin-action@v1
        with:
          working-directory: bindings/python
          rust-toolchain: stable
          command: build
          manylinux: auto
          args: --release --out dist --features cuda
      - name: install the wheel
        run: pip install bindings/python/dist/*.whl
      - name: capture a run from Python
        env:
          VOR_RECORD: /tmp/smoke.vor
        run: |
          python - <<'PY'
          import vor

          vor.record_metric_unit("loss", "")
          vor.enable()  # no NVIDIA driver here: NVML degrades, no crash

          @vor.profile
          def step(i):
              return i * 2

          for i in range(64):
              step(i)
              vor.record_metric("loss", 1.0 / (i + 1))
              vor.frame_mark()
          vor.flush()
          print("captured 64 frames")
          PY
      - name: read the capture back with the Rust reader
        run: |
          cargo run --quiet --example headless -- /tmp/smoke.vor | tee out.txt
          grep -Eq "frames: [1-9][0-9]*" out.txt

  publish:
    name: publish to PyPI
    if: startsWith(github.ref, 'refs/tags/v')
    needs: [versions, smoke, wheels, sdist]
    runs-on: ubuntu-latest
    # One-time PyPI setup (project settings -> Publishing): add a trusted
    # publisher for owner SConsul, repo vor, workflow python.yml,
    # environment pypi. No secret is stored on GitHub.
    environment: pypi
    permissions:
      id-token: write # OIDC token minted per run; PyPI verifies it
    steps:
      - uses: actions/download-artifact@v4
        with:
          path: dist
          merge-multiple: true
      - uses: pypa/gh-action-pypi-publish@release/v1
        with:
          packages-dir: dist