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"