1+ name : Build WinPython Distribution for 3.13
2+ # matrix allows to avoid duplicated code in github_workflows_build-dot, github_workflows_build-whl, github_workflows_build-slim
3+ # 2025-08-23a: merged code proposed per Gemini 2.5 flash, it corrected also PYTHONIOENCODING="utf-8" error
4+ # 2025-08-23b: moved manually to Python-3.13.7
5+ on :
6+ workflow_dispatch :
7+
8+ jobs :
9+ build-winpython :
10+ runs-on : windows-latest
11+
12+ strategy :
13+ fail-fast : true # Allows other matrix jobs to complete even if one fails
14+ matrix :
15+ # Define different WinPython build configurations
16+ flavor_config :
17+ # WinPython Dot configuration
18+ - FLAVOR : " dotc"
19+ REQUIREMENTS : " winpython\\ portable\\ cycle_2025_04\\ requir.64-3_13_5_1dotb3.txt"
20+ REQUIREMENTS_WHL : " "
21+ ZIP : " 1"
22+ SEVEN_Z : " 0"
23+ EXE : " 1"
24+ ARTIFACT_NAME : " publish_dotc"
25+ # WinPython Slim configuration
26+ - FLAVOR : " slimc"
27+ REQUIREMENTS : " winpython\\ portable\\ cycle_2025_04\\ requir.64-3_13_5_1slimb3.txt"
28+ REQUIREMENTS_WHL : " "
29+ ZIP : " 0"
30+ SEVEN_Z : " 1"
31+ EXE : " 1"
32+ ARTIFACT_NAME : " publish_slimc"
33+ # WinPython Whl configuration
34+ - FLAVOR : " whlc"
35+ REQUIREMENTS : " winpython\\ portable\\ cycle_2025_04\\ requir.64-3_13_5_1dotb3.txt" # Note: Original whl used dotb3 requirements, verify if this is intended
36+ REQUIREMENTS_WHL : " winpython\\ portable\\ cycle_2025_04\\ requir.64-3_13_5_1whlb3_wheels.txt"
37+ ZIP : " 0"
38+ SEVEN_Z : " 1"
39+ EXE : " 0"
40+ ARTIFACT_NAME : " publish_whlc"
41+
42+ steps :
43+ - name : Checkout repository
44+ uses : actions/checkout@v4
45+
46+ - name : Set static variables and Python version
47+ shell : bash
48+ run : |
49+ echo "WINPYARCH=64" >> $GITHUB_ENV
50+ echo "WINPYVERSION=313" >> $GITHUB_ENV
51+
52+ #3.13.7 as the base for now (3.13.6 was skipped)
53+ # Gemini says: can update this section to dynamically select Python versions based on matrix if needed.
54+ echo "python_source=https://github.com/astral-sh/python-build-standalone/releases/download/20250818/cpython-3.13.7+20250818-x86_64-pc-windows-msvc-install_only_stripped.tar.gz >> $GITHUB_ENV
55+ echo "python_sha256=d60173a7693c3134b8364814b80f98ddde0638e0e75e5b004f37452fccf67a33" >> $GITHUB_ENV
56+ echo "build_location=WPy64-31370b3" >> $GITHUB_ENV
57+ echo "WINPYVER=3.13.7.0${{ matrix.flavor_config.FLAVOR }}b3" >> $GITHUB_ENV
58+ echo "WINPYVER2=3.13.7.0" >> $GITHUB_ENV
59+
60+ # Use Python 3.13.5 former base
61+ #echo "python_source=https://github.com/astral-sh/python-build-standalone/releases/download/20250723/cpython-3.13.5+20250723-x86_64-pc-windows-msvc-install_only_stripped.tar.gz" >> $GITHUB_ENV
62+ #echo "python_sha256=4d88fdda4a59e0d6d45953c37c2fcb4e114dd5a2d41cb5b24b75b42ab8328ff8" >> $GITHUB_ENV
63+ #echo "build_location=WPy64-31350b3" >> $GITHUB_ENV # This will be consistent across builds
64+ #echo "WINPYVER=3.13.5.1${{ matrix.flavor_config.FLAVOR }}b3" >> $GITHUB_ENV
65+ #echo "WINPYVER2=3.13.5.1" >> $GITHUB_ENV
66+
67+
68+ # Set matrix-specific variables
69+ echo "WINPYFLAVOR=${{ matrix.flavor_config.FLAVOR }}" >> $GITHUB_ENV
70+ echo "WINPYrequirements=${{ matrix.flavor_config.REQUIREMENTS }}" >> $GITHUB_ENV
71+ echo "WINPYrequirementswhl=${{ matrix.flavor_config.REQUIREMENTS_WHL }}" >> $GITHUB_ENV
72+ echo "WINPYZIP=${{ matrix.flavor_config.ZIP }}" >> $GITHUB_ENV
73+ echo "WINPY7Z=${{ matrix.flavor_config.SEVEN_Z }}" >> $GITHUB_ENV
74+ echo "WINPYEXE=${{ matrix.flavor_config.EXE }}" >> $GITHUB_ENV
75+
76+ - name : See variables
77+ shell : pwsh
78+ run : |
79+ Write-Output "WINPYVERSION is $env:WINPYVERSION"
80+ Write-Output "WINPYFLAVOR is $env:WINPYFLAVOR"
81+ Write-Output "python_source is $env:python_source"
82+ Write-Output "python_sha256 is $env:python_sha256"
83+ Write-Output "WINPYrequirements is $env:WINPYrequirements"
84+ Write-Output "WINPYrequirementswhl is $env:WINPYrequirementswhl"
85+ Write-Output "WINPYZIP is $env:WINPYZIP"
86+ Write-Output "WINPY7Z is $env:WINPY7Z"
87+ Write-Output "WINPYEXE is $env:WINPYEXE"
88+ Write-Output "build_location is $env:build_location"
89+ Write-Output "WINPYVER is $env:WINPYVER"
90+ Write-Output "WINPYVER2 is $env:WINPYVER2"
91+
92+ - name : Download python-3 standalone
93+ shell : pwsh
94+ run : |
95+ curl.exe -L -o "python-3-embed.tar.gz" $env:python_source
96+ # Calculate SHA256 hash
97+ $filePath = "python-3-embed.tar.gz"
98+ $expectedHash = $env:python_sha256
99+
100+ $hashObject = Get-FileHash -Path $filePath -Algorithm SHA256
101+ $actualHash = $hashObject.Hash.ToLower()
102+
103+ if ($actualHash -eq $expectedHash.ToLower()) {
104+ Write-Output "Hash matches."
105+ } else {
106+ Write-Output "Hash does NOT match."
107+ Write-Output "Actual: $actualHash"
108+ Write-Output "Expected: $expectedHash"
109+ exit 1
110+ }
111+
112+ - name : Extract python-3-embed.tar.gz to dotpython
113+ shell : bash
114+ run : |
115+ mkdir dotpython
116+ tar -xf python-3-embed.tar.gz -C dotpython
117+
118+ - name : Copy launchers_final files to dotpython
119+ shell : bash
120+ run : |
121+ cp -r winpython/portable/launchers_final/* dotpython/
122+ mkdir "dotpython\wheelhouse"
123+
124+ - name : List dotpython contents (for debugging)
125+ shell : pwsh
126+ run : |
127+ Get-ChildItem dotpython
128+
129+ - name : Prepare WinPython target structure
130+ shell : pwsh
131+ run : |
132+ New-Item -ItemType Directory -Path $env:build_location
133+ Get-ChildItem -Path dotpython -Force | Move-Item -Destination $env:build_location -Force
134+
135+ - name : Upgrade pip and patch launchers
136+ shell : pwsh
137+ run : |
138+ & "$env:build_location\python\python.exe" -m pip install --upgrade pip
139+ & "$env:build_location\python\python.exe" -c "from wppm import wppm;dist=wppm.Distribution(r'$env:build_location');dist.patch_standard_packages('pip', to_movable=True)"
140+
141+ - name : Write env.ini file
142+ shell : pwsh
143+ run : |
144+ $destDir = "$env:build_location\python\scripts"
145+ echo "WINPYthon_exe=$env:WINPYthon_exe" > env.ini
146+ echo "WINPYthon_subdirectory_name=$env:WINPYthon_subdirectory_name" >> env.ini
147+ echo "WINPYVER=$env:WINPYVER" >> env.ini
148+ echo "WINPYVER2=$env:WINPYVER2" >> env.ini
149+ echo "WINPYFLAVOR=$env:WINPYFLAVOR" >> env.ini
150+ echo "WINPYARCH=$env:WINPYARCH" >> env.ini
151+ Copy-Item -Path "env.ini" -Destination "$destDir\env.ini"
152+
153+ - name : Download main requirements to wheelhouse
154+ shell : pwsh
155+ run : |
156+ & "$env:build_location\python\python.exe" -m pip download --dest dotpython\wheelhouse --no-deps --require-hashes -r $env:WINPYrequirements
157+
158+ - name : Download additional wheelhouse requirements
159+ shell : pwsh
160+ run : |
161+ $destwheelhouse="$env:build_location\wheelhouse"
162+ if ($env:WINPYrequirementswhl -eq "") {
163+ Write-Output "No additional wheelhouse requirements."
164+ } else {
165+ & "$env:build_location\python\python.exe" -m pip download --dest $destwheelhouse --no-deps --require-hashes -r $env:WINPYrequirementswhl
166+ }
167+
168+ - name : Install requirements
169+ shell : pwsh
170+ run : |
171+ & "$env:build_location\python\python.exe" -m pip install --no-deps --no-index --trusted-host=None --find-links=dotpython\wheelhouse --require-hashes -r $env:WINPYrequirements
172+
173+ - name : Generate Markdown content and pylock file
174+ shell : pwsh
175+ run : |
176+ mkdir publish_output
177+
178+ # Ensure unicode for wppm output
179+ $env:PYTHONIOENCODING="utf-8"
180+
181+ $destfile_md = "publish_output\WinPython$env:WINPYFLAVOR-$env:WINPYARCHbit-$env:WINPYVER2.md"
182+ & "$env:build_location\python\python.exe" -m wppm -md | Out-File -FilePath $destfile_md -Encoding utf8
183+
184+ & "$env:build_location\python\python.exe" -m pip freeze | Out-File -FilePath dotpython\freeze.txt
185+ $destfile_pylock = "publish_output\pylock.$env:WINPYARCH-$($env:WINPYVER -replace '\.', '_').toml"
186+ & "$env:build_location\python\python.exe" -m pip lock --no-deps --find-links=dotpython\wheelhouse -r dotpython\freeze.txt -o $destfile_pylock
187+
188+ $outreq = "publish_output\requir.$env:WINPYARCH-$($env:WINPYVER -replace '\.', '_').txt"
189+ & "$env:build_location\python\python.exe" -X utf8 -c "from wppm import wheelhouse as wh; wh.pylock_to_req(r'$destfile_pylock', r'$outreq')"
190+
191+ - name : Zip the result
192+ shell : pwsh
193+ if : ${{ matrix.flavor_config.ZIP == '1' }}
194+ run : |
195+ $destfile = "publish_output\WinPython$env:WINPYARCH-$env:WINPYVER.zip"
196+ Compress-Archive -Path "$env:build_location" -DestinationPath $destfile
197+
198+ - name : 7z archive the result
199+ shell : pwsh
200+ if : ${{ matrix.flavor_config.SEVEN_Z == '1' }}
201+ run : |
202+ $destfile7z = "publish_output\WinPython$env:WINPYARCH-$env:WINPYVER.7z"
203+ $sourceDir = "$env:build_location"
204+ 7z a $destfile7z $sourceDir
205+
206+ - name : 7z executable archive the result
207+ shell : pwsh
208+ if : ${{ matrix.flavor_config.EXE == '1' }}
209+ run : |
210+ $destfile7z = "publish_output\WinPython$env:WINPYARCH-$env:WINPYVER.exe"
211+ $sourceDir = "$env:build_location"
212+ 7z a -sfx $destfile7z $sourceDir
213+
214+ - name : Upload WinPython folder as artifact
215+ uses : actions/upload-artifact@v4
216+ with :
217+ name : ${{ matrix.flavor_config.ARTIFACT_NAME }}
218+ path : publish_output
219+ # retention-days: 30 # keeps artifact for 30 days
0 commit comments