p2o 0.1.1

A PaddlePaddle New IR (PIR) to ONNX model converter.
Documentation
name: Publish

on:
  push:
    tags:
      - 'v*'

env:
  CARGO_TERM_COLOR: always

permissions:
  contents: read

concurrency:
  group: publish-${{ github.ref }}
  cancel-in-progress: false

jobs:
  # Stage 1: Validate
  validate:
    name: Validate
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install protoc
        run: sudo apt-get update && sudo apt-get install -y protobuf-compiler

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

      - name: Cache Cargo dependencies
        uses: Swatinem/rust-cache@v2

      - name: Check formatting
        run: cargo fmt --all --check

      - name: Run Clippy
        run: cargo clippy --all-targets --all-features -- -D warnings

      - name: Run tests
        run: cargo test --all-targets --verbose

      - name: Verify version consistency
        run: |
          TAG_VERSION=${GITHUB_REF#refs/tags/v}
          CARGO_VERSION=$(cargo metadata --no-deps --format-version 1 \
            | jq -r '.packages[] | select(.name == "p2o") | .version')
          echo "Tag version: $TAG_VERSION"
          echo "Cargo.toml version: $CARGO_VERSION"
          if [ "$CARGO_VERSION" != "$TAG_VERSION" ]; then
            echo "::error::Cargo.toml version ($CARGO_VERSION) does not match Git tag ($TAG_VERSION)."
            exit 1
          fi

  # Stage 2: Publish to crates.io
  publish-crates:
    name: Publish to crates.io
    needs: validate
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install protoc
        run: sudo apt-get update && sudo apt-get install -y protobuf-compiler

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable

      - name: Cache Cargo dependencies
        uses: Swatinem/rust-cache@v2

      - name: Publish
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo publish

  # Stage 3: Build & publish PyPI wheels
  pypi-linux:
    name: PyPI wheels (linux-${{ matrix.target }})
    needs: publish-crates
    runs-on: ${{ matrix.runner }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64
            runner: ubuntu-latest
          - target: aarch64
            runner: ubuntu-24.04-arm
    steps:
      - uses: actions/checkout@v6
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.target }}
          args: --release --out dist
          sccache: 'true'
          manylinux: auto
          before-script-linux: |
            set -eux
            PROTOC_VERSION=28.3
            case "$(uname -m)" in
              x86_64) PROTOC_ARCH=x86_64 ;;
              aarch64) PROTOC_ARCH=aarch_64 ;;
              *) echo "Unsupported host arch: $(uname -m)"; exit 1 ;;
            esac
            if command -v apt-get >/dev/null 2>&1; then
              apt-get update && apt-get install -y curl unzip
            elif command -v yum >/dev/null 2>&1; then
              yum install -y curl unzip
            elif command -v apk >/dev/null 2>&1; then
              apk add --no-cache curl unzip
            fi
            curl -fL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${PROTOC_ARCH}.zip" -o /tmp/protoc.zip
            unzip -o /tmp/protoc.zip -d /usr/local
            rm /tmp/protoc.zip
            protoc --version
      - uses: actions/upload-artifact@v7
        with:
          name: wheels-linux-${{ matrix.target }}
          path: dist

  pypi-musllinux:
    name: PyPI wheels (musllinux-${{ matrix.target }})
    needs: publish-crates
    runs-on: ${{ matrix.runner }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64
            runner: ubuntu-latest
          - target: aarch64
            runner: ubuntu-24.04-arm
    steps:
      - uses: actions/checkout@v6
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.target }}
          args: --release --out dist
          sccache: 'true'
          manylinux: musllinux_1_2
          before-script-linux: |
            set -eux
            PROTOC_VERSION=28.3
            case "$(uname -m)" in
              x86_64) PROTOC_ARCH=x86_64 ;;
              aarch64) PROTOC_ARCH=aarch_64 ;;
              *) echo "Unsupported host arch: $(uname -m)"; exit 1 ;;
            esac
            if command -v apt-get >/dev/null 2>&1; then
              apt-get update && apt-get install -y curl unzip
            elif command -v yum >/dev/null 2>&1; then
              yum install -y curl unzip
            elif command -v apk >/dev/null 2>&1; then
              apk add --no-cache curl unzip
            fi
            curl -fL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${PROTOC_ARCH}.zip" -o /tmp/protoc.zip
            unzip -o /tmp/protoc.zip -d /usr/local
            rm /tmp/protoc.zip
            protoc --version
      - uses: actions/upload-artifact@v7
        with:
          name: wheels-musllinux-${{ matrix.target }}
          path: dist

  pypi-windows:
    name: PyPI wheels (windows-x64)
    needs: publish-crates
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v6
      - name: Install protoc
        run: choco install protoc
      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: x64
          args: --release --out dist
          sccache: 'true'
          rust-toolchain: stable
      - uses: actions/upload-artifact@v7
        with:
          name: wheels-windows-x64
          path: dist

  pypi-macos:
    name: PyPI wheels (macos-${{ matrix.platform.target }})
    needs: publish-crates
    runs-on: ${{ matrix.platform.runner }}
    strategy:
      fail-fast: false
      matrix:
        platform:
          - runner: macos-13
            target: x86_64
          - runner: macos-latest
            target: aarch64
    steps:
      - uses: actions/checkout@v6
      - name: Install protoc
        run: brew install protobuf
      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: ${{ matrix.platform.target }}
          args: --release --out dist
          sccache: 'true'
      - uses: actions/upload-artifact@v7
        with:
          name: wheels-macos-${{ matrix.platform.target }}
          path: dist

  pypi-sdist:
    name: PyPI sdist
    needs: publish-crates
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Build sdist
        uses: PyO3/maturin-action@v1
        with:
          command: sdist
          args: --out dist
      - uses: actions/upload-artifact@v7
        with:
          name: wheels-sdist
          path: dist

  publish-pypi:
    name: Publish to PyPI
    needs: [pypi-linux, pypi-musllinux, pypi-windows, pypi-macos, pypi-sdist]
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    steps:
      - uses: actions/download-artifact@v8
        with:
          pattern: wheels-*
          path: dist
          merge-multiple: true
      - name: Publish to PyPI via Trusted Publisher (OIDC)
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          skip-existing: true

  # Stage 4: Build & publish GitHub Release binaries
  build-binaries:
    name: Build binary (${{ matrix.target }})
    needs: publish-pypi
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            artifact: p2o-linux-x86_64
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-gnu
            artifact: p2o-linux-aarch64
          - os: macos-latest
            target: aarch64-apple-darwin
            artifact: p2o-macos-aarch64
          - os: macos-13
            target: x86_64-apple-darwin
            artifact: p2o-macos-x86_64
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact: p2o-windows-x86_64
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Install protoc (Ubuntu)
        if: runner.os == 'Linux'
        run: sudo apt-get update && sudo apt-get install -y protobuf-compiler

      - name: Install protoc (macOS)
        if: runner.os == 'macOS'
        run: brew install protobuf

      - name: Install protoc (Windows)
        if: runner.os == 'Windows'
        run: choco install protoc

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Cache Cargo dependencies
        uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}

      - name: Build
        run: cargo build --release --target ${{ matrix.target }}

      - name: Package (Unix)
        if: runner.os != 'Windows'
        run: |
          mkdir -p staging
          cp target/${{ matrix.target }}/release/p2o staging/
          tar czf ${{ matrix.artifact }}.tar.gz -C staging p2o

      - name: Package (Windows)
        if: runner.os == 'Windows'
        shell: pwsh
        run: |
          New-Item -ItemType Directory -Force -Path staging
          Copy-Item "target/${{ matrix.target }}/release/p2o.exe" -Destination staging/
          Compress-Archive -Path staging/p2o.exe -DestinationPath ${{ matrix.artifact }}.zip

      - uses: actions/upload-artifact@v7
        with:
          name: ${{ matrix.artifact }}
          path: |
            ${{ matrix.artifact }}.tar.gz
            ${{ matrix.artifact }}.zip

  github-release:
    name: GitHub Release
    needs: build-binaries
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - uses: actions/download-artifact@v8
        with:
          path: artifacts

      - name: Create release
        uses: softprops/action-gh-release@v2
        with:
          generate_release_notes: true
          files: |
            artifacts/**/*.tar.gz
            artifacts/**/*.zip