name: Build PGO wheel
description: Builds a PGO-optimized wheel
inputs:
  interpreter:
    description: 'Interpreter to build the wheel for'
    required: true
  rust-toolchain:
    description: 'Rust toolchain to use'
    required: true
  working-directory:
    description: 'Working directory to run the action in'
    required: false
    default: ${{ github.workspace }}
outputs:
  wheel:
    description: 'Path to the built wheel'
    value: ${{ steps.find_wheel.outputs.path }}
runs:
  using: composite
  steps:
    - name: Prepare profiling directory
      shell: bash
      # making this ahead of the compile ensures that the local user can write to this
      # directory; the maturin action (on linux) runs in docker so would create as root
      run: mkdir -p ${{ github.workspace }}/profdata

    - name: Build initial wheel
      uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
      with:
        working-directory: ${{ inputs.working-directory }}
        manylinux: auto
        args: >
          --release
          --out initial-wheel
          --interpreter ${{ inputs.interpreter }}
        rust-toolchain: ${{ inputs.rust-toolchain }}
        docker-options: -e CI
      env:
        RUSTFLAGS: '-Cprofile-generate=${{ github.workspace }}/profdata'

    - name: Generate pgo data
      # Until we move all dev dependencies to the main `pydantic` package, use this workaround:
      # Sync the pydantic-core workspace to get the dev dependencies (without the actual `pydantic-core` package),
      # and then sync the parent workspace:
      run: |
        export RUST_HOST=$(rustc --print host-tuple)
        uv sync --directory pydantic-core --group testing-extra --no-install-package pydantic-core
        uv sync --group testing-extra --no-install-package pydantic-core --inexact
        uv pip install pydantic-core --no-index --no-deps --find-links pydantic-core/initial-wheel
        uv run --no-sync pytest tests/pydantic_core/benchmarks
        rustup run ${INPUTS_RUST_TOOLCHAIN} bash -c 'echo LLVM_PROFDATA=$RUSTUP_HOME/toolchains/$RUSTUP_TOOLCHAIN/lib/rustlib/$RUST_HOST/bin/llvm-profdata >> "$GITHUB_ENV"'
      shell: bash
      env:
        INPUTS_RUST_TOOLCHAIN: ${{ inputs.rust-toolchain }}

    - name: Merge pgo data
      run: ${{ env.LLVM_PROFDATA }} merge -o ${{ github.workspace }}/merged.profdata ${{ github.workspace }}/profdata # zizmor: ignore[template-injection]
      shell: pwsh # because it handles paths on windows better, and works well enough on unix for this step

    - name: Build pgo-optimized wheel
      uses: PyO3/maturin-action@04ac600d27cdf7a9a280dadf7147097c42b757ad # v1.50.1
      with:
        working-directory: ${{ inputs.working-directory }}
        manylinux: auto
        args: >
          --release
          --out dist
          --interpreter ${{ inputs.interpreter }}
        rust-toolchain: ${{inputs.rust-toolchain}}
        docker-options: -e CI
      env:
        RUSTFLAGS: '-Cprofile-use=${{ github.workspace }}/merged.profdata'

    - name: Find built wheel
      id: find_wheel
      working-directory: pydantic-core
      run: echo "path=$(ls dist/*.whl)" | tee -a "$GITHUB_OUTPUT"
      shell: bash
