name: CI

on:
  push:
    branches:
      - main
    tags:
      - '*'
  pull_request:
  workflow_dispatch:

permissions:
  contents: read

env:
  CARGO_INCREMENTAL: "0"
  CARGO_PROFILE_RELEASE_LTO: ${{ startsWith(github.ref, 'refs/tags/') && 'thin' || 'false' }}
  CARGO_PROFILE_RELEASE_CODEGEN_UNITS: ${{ startsWith(github.ref, 'refs/tags/') && '1' || '16' }}

jobs:
  # Release jobs - Run on Tags AND Push/PR (accelerated via Env vars)
  linux-smoke:
    runs-on: ubuntu-latest
    if: "!startsWith(github.ref, 'refs/tags/')"
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
        with:
          key: linux-smoke-${{ hashFiles('**/Cargo.lock') }}
      - name: Smoke check
        run: cargo check --release --locked

  linux:
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/')
    strategy:
      matrix:
        target: [x86_64, aarch64]
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        with:
          python-version: '3.13'
      - name: Set up QEMU
        if: matrix.target == 'aarch64'
        uses: docker/setup-qemu-action@v3
        with:
          platforms: arm64
      # 缓存 cargo registry 到宿主机，后面挂载进 Docker 容器
      - name: Cache cargo registry
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
          key: cargo-registry-linux-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            cargo-registry-linux-${{ matrix.target }}-
      - name: Prepare cargo dirs
        run: mkdir -p ~/.cargo/registry ~/.cargo/git
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        env:
          CFLAGS_aarch64_unknown_linux_gnu: -D__ARM_ARCH=8
        with:
          target: ${{ matrix.target }}
          args: --release --out dist --find-interpreter
          sccache: 'true'
          manylinux: auto
          # 将宿主机的 cargo registry 挂载进容器
          docker-options: -v /home/runner/.cargo/registry:/root/.cargo/registry -v /home/runner/.cargo/git:/root/.cargo/git
      - name: Upload wheels
        uses: actions/upload-artifact@v6
        with:
          name: wheels-linux-${{ matrix.target }}
          path: dist

  linux-musl:
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/')
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        with:
          python-version: '3.13'
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
        with:
          platforms: arm64
      - name: Cache cargo registry
        uses: actions/cache@v5
        with:
          path: |
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
          key: cargo-registry-linux-musl-aarch64-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            cargo-registry-linux-musl-aarch64-
      - name: Prepare cargo dirs
        run: mkdir -p ~/.cargo/registry ~/.cargo/git
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        env:
          CFLAGS_aarch64_unknown_linux_musl: -D__ARM_ARCH=8
        with:
          target: aarch64-unknown-linux-musl
          args: --release --out dist --find-interpreter
          sccache: 'true'
          manylinux: musllinux_1_2
          docker-options: -v /home/runner/.cargo/registry:/root/.cargo/registry -v /home/runner/.cargo/git:/root/.cargo/git
      - name: Upload wheels
        uses: actions/upload-artifact@v6
        with:
          name: wheels-linux-musllinux-aarch64
          path: dist

  windows:
    runs-on: windows-latest
    strategy:
      matrix:
        target: [x64]
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        if: startsWith(github.ref, 'refs/tags/')
        with:
          python-version: '3.13'
          architecture: ${{ matrix.target }}
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
        with:
          key: windows-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
      - uses: actions/cache@v5
        with:
          path: ~\AppData\Local\Mozilla\sccache
          key: sccache-windows-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            sccache-windows-${{ matrix.target }}-
      - name: Smoke check
        if: "!startsWith(github.ref, 'refs/tags/')"
        run: cargo check --release --locked
      - name: Build wheels
        if: startsWith(github.ref, 'refs/tags/')
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.target }}
          args: --release --out dist --interpreter python
          sccache: 'true'
      - name: Upload wheels
        if: startsWith(github.ref, 'refs/tags/')
        uses: actions/upload-artifact@v6
        with:
          name: wheels-windows-${{ matrix.target }}
          path: dist

  macos:
    runs-on: macos-latest
    strategy:
      matrix:
        target: [aarch64]
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        if: startsWith(github.ref, 'refs/tags/')
        with:
          python-version: '3.13'
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
        with:
          key: macos-${{ matrix.target }}
      - name: Smoke check
        if: "!startsWith(github.ref, 'refs/tags/')"
        run: cargo check --release --locked
      - name: Build wheels
        if: startsWith(github.ref, 'refs/tags/')
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.target }}
          args: --release --out dist --find-interpreter
          sccache: 'true'
      - name: Upload wheels
        if: startsWith(github.ref, 'refs/tags/')
        uses: actions/upload-artifact@v6
        with:
          name: wheels-macos-${{ matrix.target }}
          path: dist

  sdist:
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/')
    steps:
      - uses: actions/checkout@v6
      - name: Build sdist
        uses: PyO3/maturin-action@v1
        with:
          command: sdist
          args: --out dist
      - name: Upload sdist
        uses: actions/upload-artifact@v6
        with:
          name: wheels-sdist
          path: dist

  release:
    name: Release
    runs-on: ubuntu-latest
    if: "startsWith(github.ref, 'refs/tags/')"
    needs: [linux, linux-musl, windows, macos, sdist]
    permissions:
      id-token: write
      contents: write
    steps:
      - uses: actions/download-artifact@v7
        with:
          pattern: wheels-*
          path: dist
          merge-multiple: true

      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
