1+ name : Build WinPython Distribution for 3.14
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.14.0rc2
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_14_0_1dotrc2.txt"
20+ REQUIREMENTS_WHL : " "
21+ ZIP : " 1"
22+ SEVEN_Z : " 0"
23+ EXE : " 1"
24+ ARTIFACT_NAME : " publish_dotc"
25+
26+
27+ steps :
28+ - name : Checkout repository
29+ uses : actions/checkout@v4
30+
31+ - name : Set static variables and Python version
32+ shell : bash
33+ run : |
34+ echo "WINPYARCH=64" >> $GITHUB_ENV
35+ echo "WINPYVERSION=314" >> $GITHUB_ENV
36+
37+ #3.14.0 as the base for now
38+ # Gemini says: can update this section to dynamically select Python versions based on matrix if needed.
39+ echo "python_source=https://github.com/astral-sh/python-build-standalone/releases/download/20250818/cpython-3.14.0rc2+20250818-x86_64-pc-windows-msvc-install_only_stripped.tar.gz" >> $GITHUB_ENV
40+ echo "python_sha256=361a49531a5d4bdc72bbccc81f7b5881b5eb751e3b47683b233cacae5aeeaeed" >> $GITHUB_ENV
41+ echo "build_location=WPy64-3140rc2" >> $GITHUB_ENV
42+ echo "WINPYVER=3.14.0.0${{ matrix.flavor_config.FLAVOR }}b3" >> $GITHUB_ENV
43+ echo "WINPYVER2=3.14.0.0" >> $GITHUB_ENV
44+
45+ # Set matrix-specific variables
46+ echo "WINPYFLAVOR=${{ matrix.flavor_config.FLAVOR }}" >> $GITHUB_ENV
47+ echo "WINPYrequirements=${{ matrix.flavor_config.REQUIREMENTS }}" >> $GITHUB_ENV
48+ echo "WINPYrequirementswhl=${{ matrix.flavor_config.REQUIREMENTS_WHL }}" >> $GITHUB_ENV
49+ echo "WINPYZIP=${{ matrix.flavor_config.ZIP }}" >> $GITHUB_ENV
50+ echo "WINPY7Z=${{ matrix.flavor_config.SEVEN_Z }}" >> $GITHUB_ENV
51+ echo "WINPYEXE=${{ matrix.flavor_config.EXE }}" >> $GITHUB_ENV
52+
53+ - name : See variables
54+ shell : pwsh
55+ run : |
56+ Write-Output "WINPYVERSION is $env:WINPYVERSION"
57+ Write-Output "WINPYFLAVOR is $env:WINPYFLAVOR"
58+ Write-Output "python_source is $env:python_source"
59+ Write-Output "python_sha256 is $env:python_sha256"
60+ Write-Output "WINPYrequirements is $env:WINPYrequirements"
61+ Write-Output "WINPYrequirementswhl is $env:WINPYrequirementswhl"
62+ Write-Output "WINPYZIP is $env:WINPYZIP"
63+ Write-Output "WINPY7Z is $env:WINPY7Z"
64+ Write-Output "WINPYEXE is $env:WINPYEXE"
65+ Write-Output "build_location is $env:build_location"
66+ Write-Output "WINPYVER is $env:WINPYVER"
67+ Write-Output "WINPYVER2 is $env:WINPYVER2"
68+
69+ - name : Download python-3 standalone
70+ shell : pwsh
71+ run : |
72+ curl.exe -L -o "python-3-embed.tar.gz" $env:python_source
73+ # Calculate SHA256 hash
74+ $filePath = "python-3-embed.tar.gz"
75+ $expectedHash = $env:python_sha256
76+
77+ $hashObject = Get-FileHash -Path $filePath -Algorithm SHA256
78+ $actualHash = $hashObject.Hash.ToLower()
79+
80+ if ($actualHash -eq $expectedHash.ToLower()) {
81+ Write-Output "Hash matches."
82+ } else {
83+ Write-Output "Hash does NOT match."
84+ Write-Output "Actual: $actualHash"
85+ Write-Output "Expected: $expectedHash"
86+ exit 1
87+ }
88+
89+ - name : Extract python-3-embed.tar.gz to dotpython
90+ shell : bash
91+ run : |
92+ mkdir dotpython
93+ tar -xf python-3-embed.tar.gz -C dotpython
94+
95+ - name : Copy launchers_final files to dotpython
96+ shell : bash
97+ run : |
98+ cp -r winpython/portable/launchers_final/* dotpython/
99+ mkdir "dotpython\wheelhouse"
100+
101+ - name : List dotpython contents (for debugging)
102+ shell : pwsh
103+ run : |
104+ Get-ChildItem dotpython
105+
106+ - name : Prepare WinPython target structure
107+ shell : pwsh
108+ run : |
109+ New-Item -ItemType Directory -Path $env:build_location
110+ Get-ChildItem -Path dotpython -Force | Move-Item -Destination $env:build_location -Force
111+
112+ - name : Upgrade pip and patch launchers
113+ shell : pwsh
114+ run : |
115+ & "$env:build_location\python\python.exe" -m pip install --upgrade pip
116+ & "$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)"
117+
118+ - name : Write env.ini file
119+ shell : pwsh
120+ run : |
121+ $destDir = "$env:build_location\python\scripts"
122+ echo "WINPYthon_exe=$env:WINPYthon_exe" > env.ini
123+ echo "WINPYthon_subdirectory_name=$env:WINPYthon_subdirectory_name" >> env.ini
124+ echo "WINPYVER=$env:WINPYVER" >> env.ini
125+ echo "WINPYVER2=$env:WINPYVER2" >> env.ini
126+ echo "WINPYFLAVOR=$env:WINPYFLAVOR" >> env.ini
127+ echo "WINPYARCH=$env:WINPYARCH" >> env.ini
128+ Copy-Item -Path "env.ini" -Destination "$destDir\env.ini"
129+
130+ - name : Download main requirements to wheelhouse
131+ shell : pwsh
132+ run : |
133+ & "$env:build_location\python\python.exe" -m pip download --dest dotpython\wheelhouse --no-deps --require-hashes -r $env:WINPYrequirements
134+
135+ - name : Download additional wheelhouse requirements
136+ shell : pwsh
137+ run : |
138+ $destwheelhouse="$env:build_location\wheelhouse"
139+ if ($env:WINPYrequirementswhl -eq "") {
140+ Write-Output "No additional wheelhouse requirements."
141+ } else {
142+ & "$env:build_location\python\python.exe" -m pip download --dest $destwheelhouse --no-deps --require-hashes -r $env:WINPYrequirementswhl
143+ }
144+
145+ - name : Install requirements
146+ shell : pwsh
147+ run : |
148+ & "$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
149+
150+ - name : Generate Markdown content and pylock file
151+ shell : pwsh
152+ run : |
153+ mkdir publish_output
154+
155+ # Ensure unicode for wppm output
156+ $env:PYTHONIOENCODING="utf-8"
157+
158+ $destfile_md = "publish_output\WinPython$env:WINPYFLAVOR-$env:WINPYARCHbit-$env:WINPYVER2.md"
159+ & "$env:build_location\python\python.exe" -m wppm -md | Out-File -FilePath $destfile_md -Encoding utf8
160+
161+ & "$env:build_location\python\python.exe" -m pip freeze | Out-File -FilePath dotpython\freeze.txt
162+ $destfile_pylock = "publish_output\pylock.$env:WINPYARCH-$($env:WINPYVER -replace '\.', '_').toml"
163+ & "$env:build_location\python\python.exe" -m pip lock --no-deps --find-links=dotpython\wheelhouse -r dotpython\freeze.txt -o $destfile_pylock
164+
165+ $outreq = "publish_output\requir.$env:WINPYARCH-$($env:WINPYVER -replace '\.', '_').txt"
166+ & "$env:build_location\python\python.exe" -X utf8 -c "from wppm import wheelhouse as wh; wh.pylock_to_req(r'$destfile_pylock', r'$outreq')"
167+
168+ - name : Zip the result
169+ shell : pwsh
170+ if : ${{ matrix.flavor_config.ZIP == '1' }}
171+ run : |
172+ $destfile = "publish_output\WinPython$env:WINPYARCH-$env:WINPYVER.zip"
173+ Compress-Archive -Path "$env:build_location" -DestinationPath $destfile
174+
175+ - name : 7z archive the result
176+ shell : pwsh
177+ if : ${{ matrix.flavor_config.SEVEN_Z == '1' }}
178+ run : |
179+ $destfile7z = "publish_output\WinPython$env:WINPYARCH-$env:WINPYVER.7z"
180+ $sourceDir = "$env:build_location"
181+ 7z a $destfile7z $sourceDir
182+
183+ - name : 7z executable archive the result
184+ shell : pwsh
185+ if : ${{ matrix.flavor_config.EXE == '1' }}
186+ run : |
187+ $destfile7z = "publish_output\WinPython$env:WINPYARCH-$env:WINPYVER.exe"
188+ $sourceDir = "$env:build_location"
189+ 7z a -sfx $destfile7z $sourceDir
190+
191+ - name : Upload WinPython folder as artifact
192+ uses : actions/upload-artifact@v4
193+ with :
194+ name : ${{ matrix.flavor_config.ARTIFACT_NAME }}
195+ path : publish_output
196+ # retention-days: 30 # keeps artifact for 30 days
0 commit comments