rcf3 0.3.0

A Rust implementation of the Random Cut Forest algorithm for anomaly detection.
Documentation
name: Release

on:
  push:
    tags:
      - "v*"
  workflow_dispatch:

jobs:
  sdist:
    name: Build sdist
    runs-on: ubuntu-slim
    defaults:
      run:
        shell: nu {0}

    steps:
      - uses: hustcer/setup-nu@v3
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - uses: astral-sh/setup-uv@v8.1.0

      - name: Build sdist
        run: uv build --sdist

      - run: ls dist

      - uses: actions/upload-artifact@v7
        with:
          name: sdist
          path: ./dist/*.tar.gz
          if-no-files-found: error

  wheel:
    name: Build wheel (${{ matrix.os }}, ${{ matrix.target }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            args: --out dist --interpreter 3.11 3.14t pypy3.11
            manylinux: manylinux_2_28
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-gnu
            args: --out dist --interpreter 3.11 3.14t pypy3.11
            manylinux: manylinux_2_28
          - os: ubuntu-24.04-riscv
            target: riscv64gc-unknown-linux-gnu
            args: --out dist --interpreter 3.11 3.14t
            manylinux: auto
          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            args: --out dist --interpreter 3.11 3.14t
            manylinux: musllinux_1_2
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-musl
            args: --out dist --interpreter 3.11 3.14t
            manylinux: musllinux_1_2
          - os: ubuntu-24.04-riscv
            target: riscv64gc-unknown-linux-musl
            args: --out dist --interpreter 3.11 3.14t
            manylinux: auto
          - os: macos-latest
            target: aarch64-apple-darwin
            args: --out dist --interpreter 3.11 3.14t pypy3.11
            manylinux: auto
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            args: --out dist --interpreter 3.11 3.14t pypy3.11
            manylinux: auto
          - os: windows-11-arm
            target: aarch64-pc-windows-msvc
            args: --out dist --interpreter 3.11 3.14t
            manylinux: auto

    defaults:
      run:
        shell: nu {0}

    steps:
      - uses: hustcer/setup-nu@v3
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - uses: astral-sh/setup-uv@v8.1.0

      - name: Build wheel
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.target }}
          manylinux: ${{ matrix.manylinux }}
          args: ${{ matrix.args }}

      - run: ls dist

      - uses: actions/upload-artifact@v7
        with:
          name: wheels-${{ matrix.os }}-${{ matrix.target }}-${{ strategy.job-index }}
          path: ./dist/*.whl
          if-no-files-found: error

  publish:
    name: Publish
    runs-on: ubuntu-latest
    needs: [wheel, sdist]
    environment: publish
    permissions:
      id-token: write
      attestations: write
      artifact-metadata: write

    defaults:
      run:
        shell: nu {0}

    steps:
      - uses: hustcer/setup-nu@v3
      - uses: actions/checkout@v6
      - uses: astral-sh/setup-uv@v8.1.0
      - uses: dtolnay/rust-toolchain@stable
      - uses: actions/download-artifact@v8
        with:
          path: dist
          merge-multiple: true

      - run: ls dist

      - name: Generate artifact attestation
        id: attest
        uses: actions/attest@v4
        with:
          subject-path: "dist/*"

      - name: Generate PyPI attestation
        run: uvx pypi-attestations sign dist/*

      - name: Publish to PyPI
        if: ${{ startsWith(github.ref, 'refs/tags/') }}
        run: uv publish -v

      - name: Publish to PyPI dry-run
        if: ${{ !startsWith(github.ref, 'refs/tags/') }}
        run: uv publish -v --dry-run

      - uses: rust-lang/crates-io-auth-action@v1
        id: auth

      - name: Publish to crates.io
        if: ${{ startsWith(github.ref, 'refs/tags/') }}
        run: cargo publish -v
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}

      - name: Publish to crates.io dry-run
        if: ${{ !startsWith(github.ref, 'refs/tags/') }}
        run: cargo publish -v --dry-run
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}