This is an automated email from the ASF dual-hosted git repository.

hubcio pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git


The following commit(s) were added to refs/heads/master by this push:
     new 59a9508cd ci(python): restore Windows wheels for the PyPI release 
(#4049)
59a9508cd is described below

commit 59a9508cd58ec63e8a7dc78899f3f54e48fdacd3
Author: Hubert Gruszecki <[email protected]>
AuthorDate: Sat Sep 5 12:46:10 2026 +0200

    ci(python): restore Windows wheels for the PyPI release (#4049)
---
 .github/workflows/_build_python_wheels.yml    | 78 ++++++++++++++++++++++--
 scripts/ci/sync-python-interpreter-version.sh | 87 ++++++++++++++++++++++++++-
 2 files changed, 159 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/_build_python_wheels.yml 
b/.github/workflows/_build_python_wheels.yml
index ae066bb24..2a0cafc27 100644
--- a/.github/workflows/_build_python_wheels.yml
+++ b/.github/workflows/_build_python_wheels.yml
@@ -184,8 +184,17 @@ jobs:
           retention-days: 7
 
   windows:
-    if: false # TODO(hubcio): temporarily disabled
     runs-on: windows-latest
+    strategy:
+      fail-fast: false
+      # Windows exposes no `python3.X` on PATH and maturin's py-launcher
+      # fallback does not see setup-python tool-cache installs, so one
+      # job cannot target several interpreters. One job per version
+      # instead, each falling through to maturin's default of the
+      # interpreter on PATH. 3.10 is Windows-only excluded, see
+      # WHEEL_MATRIX_SKIP in scripts/ci/sync-python-interpreter-version.sh.
+      matrix:
+        python-version: ["3.11", "3.12", "3.13"]
     steps:
       - name: Download latest copy script from master
         if: inputs.use_latest_ci
@@ -209,22 +218,51 @@ jobs:
       - name: Setup Python
         uses: actions/[email protected]
         with:
-          python-version: "3.10"
+          python-version: ${{ matrix.python-version }}
           architecture: x64
 
+      - name: Setup Rust with cache
+        uses: ./.github/actions/utils/setup-rust-with-cache
+        with:
+          shared-key: python-wheels-windows
+
+      # aws-lc-sys, reached through quinn's default rustls provider,
+      # assembles its x86_64 crypto with NASM. The runner image ships
+      # CMake but not NASM, and Chocolatey leaves it off PATH.
+      - name: Install NASM
+        shell: pwsh
+        run: |
+          $nasmDir = "C:\Program Files\NASM"
+          choco install nasm --no-progress -y
+          Add-Content -Path $env:GITHUB_PATH -Value $nasmDir
+          # GITHUB_PATH only reaches later steps, so prove the install
+          # landed where expected here rather than in a linker error.
+          $env:PATH = "$nasmDir;$env:PATH"
+          nasm -v
+
+      - name: Generate third-party license manifest
+        shell: bash
+        run: |
+          TARGET="x86_64-pc-windows-msvc"
+          # HOME is Windows-style here, which MSYS tar mishandles as -C.
+          CARGO_BIN="$(cygpath -u "$HOME")/.cargo/bin"
+          curl -sSfL 
"https://github.com/EmbarkStudios/cargo-about/releases/download/0.9.0/cargo-about-0.9.0-${TARGET}.tar.gz";
 \
+            | tar -xz -C "$CARGO_BIN" --strip-components=1 
"cargo-about-0.9.0-${TARGET}/cargo-about.exe"
+          ./scripts/ci/third-party-licenses.sh --generate --manifest 
foreign/python/Cargo.toml --output foreign/python/LICENSE-binary
+
       - name: Build wheels
         uses: PyO3/maturin-action@v1
         with:
           target: x86_64
           working-directory: foreign/python
-          args: --release --out dist --interpreter python3.10 python3.11 
python3.12 python3.13
+          args: --release --out dist
           sccache: "true"
 
       - name: Upload wheels
         if: inputs.upload_artifacts
         uses: actions/upload-artifact@v7
         with:
-          name: wheels-windows-x64
+          name: wheels-windows-x64-py${{ matrix.python-version }}
           path: foreign/python/dist
           retention-days: 7
 
@@ -265,7 +303,7 @@ jobs:
 
   collect:
     name: Collect all wheels
-    needs: [linux, macos, sdist] # TODO(hubcio): add windows back when 
re-enabled
+    needs: [linux, macos, windows, sdist]
     if: ${{ !cancelled() }}
     runs-on: ubuntu-latest
     outputs:
@@ -312,3 +350,33 @@ jobs:
 
       - id: output
         run: echo "artifact_name=python-wheels-all" >> $GITHUB_OUTPUT
+
+      # Runs last so the artifact and the summary survive for inspection
+      # when a leg is missing. A failed build job uploads nothing, so a
+      # short count means one did not contribute. These counts are not
+      # derived from the matrices above - update them together.
+      - name: Verify wheel coverage
+        run: |
+          EXPECTED_LINUX=16   # 4 build variants x 4 interpreters
+          EXPECTED_MACOS=8    # 2 targets x 4 interpreters
+          EXPECTED_WINDOWS=3  # 1 interpreter per job, 3.10 excluded
+          EXPECTED_SDIST=1
+
+          missing=0
+          check() {
+            local label="$1" pattern="$2" expected="$3" actual
+            actual=$(find dist -maxdepth 1 -name "$pattern" | wc -l)
+            if [ "$actual" -ne "$expected" ]; then
+              echo "::error::${label}: expected ${expected}, found ${actual}"
+              missing=1
+            else
+              echo "${label}: ${actual}"
+            fi
+          }
+
+          check Linux '*linux*.whl' "$EXPECTED_LINUX"
+          check macOS '*macosx*.whl' "$EXPECTED_MACOS"
+          check Windows '*win*.whl' "$EXPECTED_WINDOWS"
+          check sdist '*.tar.gz' "$EXPECTED_SDIST"
+
+          exit "$missing"
diff --git a/scripts/ci/sync-python-interpreter-version.sh 
b/scripts/ci/sync-python-interpreter-version.sh
index cc3ced1a3..8c074be73 100755
--- a/scripts/ci/sync-python-interpreter-version.sh
+++ b/scripts/ci/sync-python-interpreter-version.sh
@@ -24,8 +24,15 @@ source "$(dirname "${BASH_SOURCE[0]}")/lib/init.sh"
 # Colors for output
 RED='\033[0;31m'
 GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
 NC='\033[0m' # No Color
 
+# Minor versions deliberately not built as Windows wheels. Every other
+# version in the pyproject classifiers must appear in the wheel job
+# matrix, so adding a new supported version still fails this check
+# until the matrix is updated.
+WHEEL_MATRIX_SKIP=("3.10")
+
 # Default mode
 MODE=""
 
@@ -266,6 +273,12 @@ ensure_lock_python_requirement() {
     fi
 }
 
+# Every supported minor version, oldest first, as declared by the
+# pyproject classifiers.
+read_classifier_versions() {
+    sed -nE 's/^    "Programming Language :: Python :: 
([0-9]+\.[0-9]+)",$/\1/p' "$SOURCE_FILE"
+}
+
 ensure_wheel_interpreters() {
     local file="$1"
     local classifier_versions=()
@@ -284,7 +297,7 @@ ensure_wheel_interpreters() {
     fi
 
     classifier_versions=()
-    while IFS= read -r _py_cls_tmp; do classifier_versions+=("$_py_cls_tmp"); 
done < <(sed -nE 's/^    "Programming Language :: Python :: 
([0-9]+\.[0-9]+)",$/\1/p' "$SOURCE_FILE")
+    while IFS= read -r _py_cls_tmp; do classifier_versions+=("$_py_cls_tmp"); 
done < <(read_classifier_versions)
 
     if [ "${#classifier_versions[@]}" -eq 0 ]; then
         echo -e "${RED}✗${NC} $SOURCE_FILE: could not find Python version 
classifiers"
@@ -327,6 +340,77 @@ ensure_wheel_interpreters() {
     fi
 }
 
+# The Windows wheel job builds one interpreter per matrix entry rather
+# than passing --interpreter, so its version list needs its own check.
+ensure_wheel_matrix() {
+    local file="$1"
+    local expected=""
+    local current
+    local version
+    local skipped
+    local seen=0
+
+    TOTAL_CHECKS=$((TOTAL_CHECKS + 1))
+
+    if [ ! -f "$file" ]; then
+        echo -e "${RED}✗${NC} $file: file does not exist"
+        FAILED=1
+        return
+    fi
+
+    while IFS= read -r version; do
+        seen=$((seen + 1))
+        for skipped in "${WHEEL_MATRIX_SKIP[@]}"; do
+            [ "$version" = "$skipped" ] && continue 2
+        done
+        expected+=", \"${version}\""
+    done < <(read_classifier_versions)
+
+    if [ "$seen" -eq 0 ]; then
+        echo -e "${RED}✗${NC} $SOURCE_FILE: could not find Python version 
classifiers"
+        FAILED=1
+        return
+    fi
+
+    if [ -z "$expected" ]; then
+        echo -e "${RED}✗${NC} $SOURCE_FILE: WHEEL_MATRIX_SKIP excludes every 
classifier version"
+        FAILED=1
+        return
+    fi
+    expected="[${expected#, }]"
+
+    current=$(sed -nE 's/^[[:space:]]*python-version: (\[.*\])$/\1/p' "$file")
+
+    if [ -z "$current" ]; then
+        echo -e "${RED}✗${NC} $file: could not find wheel matrix 
python-version list"
+        FAILED=1
+        return
+    fi
+
+    # --fix rewrites every match, so refuse to touch a file that grew a
+    # second list rather than collapsing both onto the same versions.
+    if [ "$(printf '%s\n' "$current" | wc -l)" -gt 1 ]; then
+        echo -e "${RED}✗${NC} $file: multiple python-version lists, cannot 
pick one"
+        FAILED=1
+        return
+    fi
+
+    if [ "$current" = "$expected" ]; then
+        echo -e "${GREEN}✓${NC} $file: wheel matrix Python versions"
+        return
+    fi
+
+    if [ "$MODE" = "fix" ]; then
+        sed -i.bak -E "s|^([[:space:]]*python-version: 
)\[.*\]$|\\1${expected}|" "$file"
+        rm -f "$file.bak"
+        FIXED_CHECKS=$((FIXED_CHECKS + 1))
+        echo -e "${GREEN}Fixed${NC} $file: wheel matrix Python versions"
+    else
+        echo -e "${RED}✗${NC} $file: wheel matrix Python versions are not 
$expected"
+        FAILED=1
+    fi
+}
+
 ensure_classifiers "$SOURCE_FILE"
 
 PYTHON_VERSION_FILES=(
@@ -401,6 +485,7 @@ ensure_line \
     "wheel workflow setup-python versions"
 
 ensure_wheel_interpreters ".github/workflows/_build_python_wheels.yml"
+ensure_wheel_matrix ".github/workflows/_build_python_wheels.yml"
 
 PYLOCK_FILES=(
     "foreign/python/pylock.toml"

Reply via email to