name: numba_win-64_wheel_builder

on:
  schedule:
    - cron: '0 8 * * 6'  # Saturday 8:00 AM UTC - win-64 wheel
  pull_request:
    paths:
      - .github/workflows/numba_win-64_wheel_builder.yml
      - .github/workflows/wheel_workflow_matrix.json
      - setup.py
  workflow_dispatch:
    inputs:
      llvmlite_wheel_runid:
        description: 'llvmlite wheel workflow run ID (optional)'
        required: false
        type: string

# Add concurrency control
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

env:
  ARTIFACT_RETENTION_DAYS: 7
  WHEELS_INDEX_URL: https://pypi.anaconda.org/numba/label/dev/simple

jobs:
  load-matrix:
    runs-on: ubuntu-latest
    outputs:
      build-matrix-json: ${{ steps.load_matrix_json.outputs.build-matrix-json }}
      test-matrix-json: ${{ steps.load_matrix_json.outputs.test-matrix-json }}
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
      - id: load_matrix_json
        name: Load Workflow Matrix JSON
        run: |
          BUILD_MATRIX_JSON=$(jq -c .wheel_build_matrix .github/workflows/wheel_workflow_matrix.json)
          TEST_MATRIX_JSON=$(jq -c .wheel_test_matrix .github/workflows/wheel_workflow_matrix.json)

          # Add canonical python versions to both matrices
          BUILD_MATRIX_EXTENDED=$(echo "$BUILD_MATRIX_JSON" | jq -c '
            map(. + {"python_canonical": (.["python-version"] | split(".") | .[:2] | join("."))})
          ')

          TEST_MATRIX_EXTENDED=$(echo "$TEST_MATRIX_JSON" | jq -c '
            map(. + {"python_canonical": (.["python-version"] | split(".") | .[:2] | join("."))})
          ')

          echo "Build Matrix JSON: $BUILD_MATRIX_EXTENDED"
          echo "Test Matrix JSON: $TEST_MATRIX_EXTENDED"
          echo "build-matrix-json=$BUILD_MATRIX_EXTENDED" >> $GITHUB_OUTPUT
          echo "test-matrix-json=$TEST_MATRIX_EXTENDED" >> $GITHUB_OUTPUT

  win-64-build:
    name: win-64-build-wheel (py ${{ matrix.python-version }}, np ${{ matrix.numpy_build }})
    needs: load-matrix
    runs-on: windows-2025
    defaults:
      run:
        shell: bash -el {0}
    strategy:
      matrix:
        include: ${{ fromJson(needs.load-matrix.outputs.build-matrix-json) }}
      fail-fast: false

    steps:
      - name: Clone repository
        uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
        with:
          fetch-depth: 0

      - name: Setup Python
        uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
        with:
          python-version: ${{ matrix.python-version }}
          allow-prereleases: true

      - name: Download llvmlite wheel
        if: inputs.llvmlite_wheel_runid != ''
        uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
        with:
          name: llvmlite-win-64-py${{ matrix.python_canonical }}
          path: llvmlite_wheels
          run-id: ${{ inputs.llvmlite_wheel_runid }}
          repository: numba/llvmlite
          github-token: ${{ secrets.GITHUB_TOKEN }}

      - name: Install build dependencies
        run: |
          if [ "${{ inputs.llvmlite_wheel_runid }}" != "" ]; then
              python -m pip install llvmlite_wheels/*.whl
          else
              python -m pip install -i ${{ env.WHEELS_INDEX_URL }} llvmlite
          fi
          python -m pip install build numpy==${{ matrix.numpy_build }} setuptools wheel tbb==2021.6 tbb-devel==2021.6

      - name: Build wheel
        run: python -m build --wheel --no-isolation

      - name: Upload numba wheel
        uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
        with:
          name: numba_win-64_wheel_py${{ matrix.python_canonical }}
          path: dist/*.whl
          compression-level: 0
          retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }}
          if-no-files-found: error

  win-64-test:
    name: win-64-test-wheel (py ${{ matrix.python-version }}, np ${{ matrix.numpy_test }})
    needs: [load-matrix, win-64-build]
    runs-on: windows-2025
    defaults:
      run:
        shell: bash -el {0}
    strategy:
      matrix:
        include: ${{ fromJson(needs.load-matrix.outputs.test-matrix-json) }}
      fail-fast: false

    steps:
      - name: Setup Python
        uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
        with:
          python-version: ${{ matrix.python-version }}
          allow-prereleases: true

      - name: Download Numba wheel artifact
        uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
        with:
          name: numba_win-64_wheel_py${{ matrix.python_canonical }}
          path: dist

      - name: Download llvmlite wheel
        if: inputs.llvmlite_wheel_runid != ''
        uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
        with:
          name: llvmlite-win-64-py${{ matrix.python_canonical }}
          path: llvmlite_wheels
          run-id: ${{ inputs.llvmlite_wheel_runid }}
          repository: numba/llvmlite
          github-token: ${{ secrets.GITHUB_TOKEN }}

      - name: Validate and test wheel
        env:
          NUMBA_CPU_NAME: generic
          _NUMBA_REDUCED_TESTING: 1
        run: |
          python -m pip install --upgrade pip twine
          python -m pip install numpy==${{ matrix.numpy_test }} tbb==2021.6 tbb-devel==2021.6
          if [ "${{ inputs.llvmlite_wheel_runid }}" != "" ]; then
              python -m pip install llvmlite_wheels/*.whl
          else
              python -m pip install --pre -i ${{ env.WHEELS_INDEX_URL }} llvmlite
          fi
          python -m twine check dist/*.whl
          python -m pip install dist/*.whl

          # Disable NumPy dispatching to AVX512_SKX feature extensions if the chip is
          # reported to support the feature and NumPy >= 1.22 as this results in the use
          # of low accuracy SVML libm replacements in ufunc loops.
          _NPY_CMD='from numba.misc import numba_sysinfo;\
                    sysinfo=numba_sysinfo.get_sysinfo();\
                    print(sysinfo["NumPy AVX512_SKX detected"] and
                          sysinfo["NumPy Version"]>="1.22")'
          NUMPY_DETECTS_AVX512_SKX_NP_GT_122=$(python -c "$_NPY_CMD")
          echo "NumPy >= 1.22 with AVX512_SKX detected: $NUMPY_DETECTS_AVX512_SKX_NP_GT_122"

          if [[ "$NUMPY_DETECTS_AVX512_SKX_NP_GT_122" == "True" ]]; then
              export NPY_DISABLE_CPU_FEATURES="AVX512_SKX"
          fi

          # print Numba system information
          python -m numba -s

          # run tests
          python -m numba.runtests -m 4 -v
