1+ name : Build WinPython for 2026-01 Cycle
2+
3+ on :
4+ workflow_dispatch :
5+ inputs :
6+ python_versionf :
7+ description : ' Python version to build (3.13, 3.14, 3.14F or 3.15)'
8+ required : true
9+ default : ' 3.14'
10+ type : choice
11+ options :
12+ - ' 3.13'
13+ - ' 3.14'
14+ - ' 3.14F'
15+ - ' 3.15'
16+ - ' 3.15F'
17+
18+ env :
19+ # === Global Configuration ===
20+ WINPYARCH : " 64"
21+ my_cycle : " winpython/portable/cycle_2026_02"
22+ my_release_level : " b0"
23+ dotwheelhouse : " dotpython\\ wheelhouse\\ included.wheels"
24+ pandoc_source : " https://github.com/jgm/pandoc/releases/download/3.1.9/pandoc-3.1.9-windows-x86_64.zip"
25+ pandoc_sha256 : " 11eb6dbe5286c9e5edb0cca4412e7d99ec6578ec04158b0b7fe11f7fd96688e5"
26+
27+ jobs :
28+ build-winpython :
29+ runs-on : windows-latest
30+ strategy :
31+ fail-fast : true
32+ matrix :
33+ flavor :
34+ - name : " dot"
35+ formats : { zip: true, 7z: false, exe: true }
36+ PANDOC : " 0"
37+ WINPYARCHDET : " 64"
38+ - name : " slim"
39+ formats : { zip: false, 7z: true, exe: true }
40+ PANDOC : " 1"
41+ WINPYARCHDET : " 64"
42+ - name : " whl"
43+ formats : { zip: false, 7z: true, exe: false }
44+ PANDOC : " 0"
45+ WINPYARCHDET : " 64"
46+ - name : " free"
47+ formats : { zip: true, 7z: false, exe: true }
48+ PANDOC : " 0"
49+ WINPYARCHDET : " 64F"
50+ - name : " slimf"
51+ formats : { zip: false, 7z: true, exe: true }
52+ PANDOC : " 1"
53+ WINPYARCHDET : " 64F"
54+
55+ env :
56+ PYTHON_VERSIONF : ${{ github.event.inputs.python_versionf }}
57+ WINPYFLAVOR : ${{ matrix.flavor.name }}
58+ PANDOC : ${{ matrix.flavor.PANDOC }}
59+ WINPYARCHDET : ${{ matrix.flavor.WINPYARCHDET }}
60+
61+ steps :
62+ - name : Checkout repository
63+ uses : actions/checkout@v4
64+
65+ - name : Set Python version configuration
66+ id : python_config
67+ shell : pwsh
68+ run : |
69+ switch ($env:PYTHON_VERSIONF) {
70+ '3.13' {
71+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'ver2=3.13.12.1'
72+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'src=https://github.com/astral-sh/python-build-standalone/releases/download/20260211/cpython-3.13.12+20260211-x86_64-pc-windows-msvc-install_only_stripped.tar.gz'
73+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'sha=b73415a86dcf298a2f4a585c5371fb1cf003576d2bdc2b80a34d5321284b2ed4'
74+ }
75+ '3.14' {
76+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'ver2=3.14.3.1'
77+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'src=https://github.com/astral-sh/python-build-standalone/releases/download/20260211/cpython-3.14.3+20260211-x86_64-pc-windows-msvc-install_only_stripped.tar.gz'
78+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'sha=dc5feea0e16807e7c7b2d20af3f2c18c7153f9cbd4b54063172553fda60c5a1f'
79+ }
80+ '3.14F' {
81+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'ver2=3.14.3.1'
82+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'src=https://github.com/astral-sh/python-build-standalone/releases/download/20260211/cpython-3.14.3+20260211-x86_64-pc-windows-msvc-freethreaded+pgo-full.tar.zst'
83+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'sha=dac2dc871cc9d170a9930985269b6f3e9e2fc364a6c8eb3c2e8b61f204a67f2c'
84+ }
85+ '3.15' {
86+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'ver2=3.15.0.2'
87+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'src=https://github.com/astral-sh/python-build-standalone/releases/download/20260325/cpython-3.15.0a7+20260325-x86_64-pc-windows-msvc-install_only_stripped.tar.gz'
88+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'sha=821afdd65034ddd053bf0dacd4b26a098d2907da013dd0adeb42570585fb427d'
89+ }
90+ '3.15F' {
91+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'ver2=3.15.0.2'
92+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'src=https://github.com/astral-sh/python-build-standalone/releases/download/20260325/cpython-3.15.0a7+20260325-x86_64-pc-windows-msvc-freethreaded-install_only_stripped.tar.gz'
93+ Add-Content -Path $env:GITHUB_OUTPUT -Value 'sha=fe650dd998ee9c1a23624fc1607032b8b46efc68c8d6e8d5ba50509f349fdcad'
94+ }
95+ }
96+
97+ - name : Set static and matrix variables based on selected Python version
98+ shell : pwsh
99+ env :
100+ PYTHON_VERSIONF : ${{ env.PYTHON_VERSIONF }}
101+ WINPYARCHDET : ${{ env.WINPYARCHDET }}
102+ WINPYVER2 : ${{ steps.python_config.outputs.ver2 }}
103+ my_cycle : ${{ env.my_cycle }}
104+ my_release_level : ${{ env.my_release_level }}
105+ FLAVOR_NAME : ${{ matrix.flavor.name }}
106+ python_source : ${{ steps.python_config.outputs.src }}
107+ run : |
108+ # Normalize PYTHON_VERSION by removing trailing 'F' if present
109+ $PYTHON_VERSION = $env:PYTHON_VERSIONF -replace 'F$',''
110+ Add-Content -Path $env:GITHUB_ENV -Value "PYTHON_VERSION=$PYTHON_VERSION"
111+
112+ # Detect architecture (64 or 64F)
113+ $detected_arch = if ($env:PYTHON_VERSIONF -like '*F') { '64F' } else { '64' }
114+
115+ $WINPYVER2 = $env:WINPYVER2
116+ $BUILD_LOCATION = "WPy64-" + ($WINPYVER2 -replace '\\.', '')
117+ Add-Content -Path $env:GITHUB_ENV -Value "build_location=$BUILD_LOCATION"
118+
119+ # check consistency of parametrizing:
120+ $python_version=([version]$WINPYVER2).ToString(3)
121+ if ($env:python_source.Contains($python_version)) {
122+ Write-Host "Success: Found '$python_version' in $env:python_source"
123+ } else {
124+ Write-Error "Error: '$python_version' not found in $env:python_source !"
125+ exit 1
126+ }
127+
128+ $WINPYREQUIREMENTS = ''
129+ $WINPYREQUIREMENTSwhl = ''
130+
131+ # 2. Generate requirement files expected names dynamically
132+ $V_TAG = $env:WINPYVER2 -replace '\.', '_'
133+ $testreq = "$($env:my_cycle)/requir.64-$($V_TAG)$($env:FLAVOR_NAME)$($env:my_release_level).txt"
134+ $testwhl = "$($env:my_cycle)/requir.64-$($V_TAG)$($env:FLAVOR_NAME)$($env:my_release_level)_wheels.txt"
135+
136+ Write-Host "Checking for requirements files: $testreq and $testwhl (expected arch $detected_arch)"
137+
138+ if ($env:WINPYARCHDET -eq $detected_arch -and (Test-Path $testreq)) {
139+ $WINPYREQUIREMENTS = $testreq
140+ Write-Host "Found $WINPYREQUIREMENTS"
141+ if (Test-Path $testwhl) {
142+ $WINPYREQUIREMENTSwhl = $testwhl
143+ Write-Host "Found also $WINPYREQUIREMENTSwhl"
144+ }
145+ }
146+
147+ Add-Content -Path $env:GITHUB_ENV -Value "WINPYREQUIREMENTS=$WINPYREQUIREMENTS"
148+ Add-Content -Path $env:GITHUB_ENV -Value "WINPYREQUIREMENTSwhl=$WINPYREQUIREMENTSwhl"
149+
150+ $ARTIFACT_NAME = "publish_${PYTHON_VERSION}$($env:FLAVOR_NAME)"
151+ Add-Content -Path $env:GITHUB_ENV -Value "ARTIFACT_NAME=$ARTIFACT_NAME"
152+
153+ $destwheelhouse = "$BUILD_LOCATION\wheelhouse\included.wheels"
154+ Add-Content -Path $env:GITHUB_ENV -Value "destwheelhouse=$destwheelhouse"
155+
156+ $WINPYVER = "${WINPYVER2}$($env:FLAVOR_NAME)$($env:my_release_level)"
157+ Add-Content -Path $env:GITHUB_ENV -Value "WINPYVER=$WINPYVER"
158+
159+ # Store WINPYVER2 in env for later steps
160+ Add-Content -Path $env:GITHUB_ENV -Value "WINPYVER2=$WINPYVER2"
161+
162+ - name : Download, verify and extract python standalone
163+ if : env.WINPYREQUIREMENTS != ''
164+ uses : ./.github/actions/python-setup
165+ with :
166+ python_source : ${{ steps.python_config.outputs.src }}
167+ python_sha256 : ${{ steps.python_config.outputs.sha }}
168+ build_location : ${{ env.build_location }}
169+
170+ - name : Download, checking hash and integrating pandoc binary
171+ if : env.WINPYREQUIREMENTS != '' && env.PANDOC == '1'
172+ uses : ./.github/actions/pandoc-setup
173+ with :
174+ pandoc_source : ${{ env.pandoc_source }}
175+ pandoc_sha256 : ${{ env.pandoc_sha256 }}
176+ build_location : ${{ env.build_location }}
177+
178+ - name : Upgrade pip and patch launchers
179+ if : env.WINPYREQUIREMENTS != ''
180+ shell : pwsh
181+ run : |
182+ & "$env:build_location\python\python.exe" -m pip install --upgrade --force-reinstall pip
183+ & "$env:build_location\python\python.exe" -m pip install packaging
184+ & "$env:build_location\python\python.exe" -c "from wppm import wppm;dist=wppm.Distribution();dist.patch_standard_packages('pip', to_movable=True)"
185+
186+ - name : Download all requirements
187+ if : ${{ env.WINPYREQUIREMENTS != '' }}
188+ shell : pwsh
189+ run : |
190+ $py = "$env:build_location\python\python.exe"
191+ & $py -m pip download --dest $env:dotwheelhouse --no-deps --require-hashes -r $env:WINPYREQUIREMENTS
192+ if ($env:WINPYREQUIREMENTSwhl -ne '') {
193+ & $py -m pip download --dest $env:destwheelhouse --no-deps --require-hashes -r $env:WINPYREQUIREMENTSwhl
194+ }
195+
196+ - name : Install requirements
197+ if : env.WINPYREQUIREMENTS != ''
198+ shell : pwsh
199+ run : |
200+ & "$env:build_location\python\python.exe" -m pip install --no-deps --no-index --trusted-host=None --find-links=$env:dotwheelhouse --require-hashes -r $env:WINPYREQUIREMENTS
201+
202+ - name : Generate Assets and Hashes
203+ if : env.WINPYREQUIREMENTS != ''
204+ uses : ./.github/actions/publish-winpython
205+ with :
206+ build_location : ${{ env.build_location }}
207+ winpy_flavor : ${{ env.WINPYFLAVOR }}
208+ winpy_arch : ${{ env.WINPYARCH }}
209+ winpy_ver : ${{ env.WINPYVER }}
210+ winpy_ver2 : ${{ env.WINPYVER2 }}
211+ dotwheelhouse : ${{ env.dotwheelhouse }}
212+ winpy_requirements_whl : ${{ env.WINPYREQUIREMENTSwhl }}
213+ format_zip : ${{ matrix.flavor.formats.zip }}
214+ format_7z : ${{ matrix.flavor.formats['7z'] }}
215+ format_exe : ${{ matrix.flavor.formats.exe }}
216+
217+ - name : Upload artifacts
218+ if : env.WINPYREQUIREMENTS != ''
219+ uses : actions/upload-artifact@v4
220+ with :
221+ name : ${{ env.ARTIFACT_NAME }}
222+ path : publish_output
223+ retention-days : 66 # keeps artifact for 66 days
0 commit comments