update python path #2
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Release Python CWMS | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version number' | |
| required: true | |
| default: '0.8' | |
| env: | |
| # WinPython Configuration - Update these variables as needed | |
| WINPYTHON_VERSION: "16.6.20250620final" | |
| WINPYTHON_FILENAME: "Winpython64-3.12.10.1dot.zip" | |
| WINPYTHON_DOWNLOAD_URL: "https://github.com/winpython/winpython/releases/download/16.6.20250620final/Winpython64-3.12.10.1dot.zip" | |
| # Alternative: You can also construct the URL from parts | |
| # WINPYTHON_BASE_URL: "https://github.com/winpython/winpython/releases/download" | |
| # Full URL would be: ${{ env.WINPYTHON_BASE_URL }}/${{ env.WINPYTHON_VERSION }}/${{ env.WINPYTHON_FILENAME }} | |
| jobs: | |
| build: | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Download WinPython | |
| run: | | |
| $url = "${{ env.WINPYTHON_DOWNLOAD_URL }}" | |
| $filename = "${{ env.WINPYTHON_FILENAME }}" | |
| Write-Host "Downloading WinPython from: $url" | |
| Write-Host "Saving as: $filename" | |
| Invoke-WebRequest -Uri $url -OutFile $filename | |
| # Verify the file was downloaded | |
| if (Test-Path $filename) { | |
| $size = (Get-Item $filename).Length / 1MB | |
| Write-Host "✓ Downloaded successfully - Size: $([math]::Round($size, 2)) MB" | |
| } else { | |
| Write-Error "❌ Failed to download $filename" | |
| exit 1 | |
| } | |
| - name: Extract WinPython | |
| run: | | |
| $filename = "${{ env.WINPYTHON_FILENAME }}" | |
| Write-Host "Extracting $filename..." | |
| Expand-Archive -Path $filename -DestinationPath "winpython_extracted" | |
| # List what was extracted | |
| $extractedDirs = Get-ChildItem -Path "winpython_extracted" -Directory | |
| Write-Host "Extracted directories:" | |
| $extractedDirs | ForEach-Object { Write-Host " - $($_.Name)" } | |
| - name: Install packages from requirements | |
| run: | | |
| $winpythonDir = Get-ChildItem -Path "winpython_extracted" -Directory | Select-Object -First 1 | |
| Write-Host "Using WinPython directory: $($winpythonDir.Name)" | |
| # The python directory is simply named "python" (not python-*) | |
| $pythonDirPath = Join-Path $winpythonDir.FullName "python" | |
| $pipPath = Join-Path $pythonDirPath "Scripts\pip.exe" | |
| $pythonPath = Join-Path $pythonDirPath "python.exe" | |
| Write-Host "Python directory path: $pythonDirPath" | |
| Write-Host "Looking for pip at: $pipPath" | |
| Write-Host "Looking for python at: $pythonPath" | |
| # Verify directories and files exist | |
| if (-not (Test-Path $pythonDirPath)) { | |
| Write-Error "Python directory not found at: $pythonDirPath" | |
| Write-Host "Available directories in WinPython:" | |
| Get-ChildItem -Path $winpythonDir.FullName -Directory | ForEach-Object { Write-Host " $($_.Name)" } | |
| exit 1 | |
| } | |
| if (-not (Test-Path $pythonPath)) { | |
| Write-Error "Python executable not found at: $pythonPath" | |
| exit 1 | |
| } | |
| if (-not (Test-Path $pipPath)) { | |
| Write-Error "Pip not found at: $pipPath" | |
| Write-Host "Contents of Scripts directory:" | |
| $scriptsDir = Join-Path $pythonDirPath "Scripts" | |
| if (Test-Path $scriptsDir) { | |
| Get-ChildItem -Path $scriptsDir | ForEach-Object { Write-Host " $($_.Name)" } | |
| } | |
| exit 1 | |
| } | |
| if (Test-Path "requirements_binary_only.txt") { | |
| Write-Host "Installing packages from requirements_binary_only.txt..." | |
| Write-Host "Using python: $pythonPath" | |
| # Use python -m pip for more reliability | |
| & $pythonPath -m pip install -r requirements_binary_only.txt --only-binary=all | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Error "Package installation failed with exit code: $LASTEXITCODE" | |
| exit 1 | |
| } | |
| Write-Host "✓ Package installation completed successfully" | |
| } else { | |
| Write-Host "No requirements_binary_only.txt found, skipping package installation" | |
| } | |
| - name: Run setup script (if exists) | |
| run: | | |
| $winpythonDir = Get-ChildItem -Path "winpython_extracted" -Directory | Select-Object -First 1 | |
| # The python directory is simply named "python" | |
| $pythonDirPath = Join-Path $winpythonDir.FullName "python" | |
| $pythonPath = Join-Path $pythonDirPath "python.exe" | |
| if (-not (Test-Path $pythonPath)) { | |
| Write-Error "Python executable not found at: $pythonPath" | |
| exit 1 | |
| } | |
| if (Test-Path "setup_environment.py") { | |
| Write-Host "Running setup_environment.py..." | |
| Write-Host "Using python: $pythonPath" | |
| & $pythonPath setup_environment.py | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Error "Setup script failed with exit code: $LASTEXITCODE" | |
| exit 1 | |
| } | |
| Write-Host "✓ Setup script completed successfully" | |
| } else { | |
| Write-Host "No setup_environment.py found, skipping custom setup" | |
| } | |
| - name: Create final directory structure | |
| run: | | |
| $winpythonDir = Get-ChildItem -Path "winpython_extracted" -Directory | Select-Object -First 1 | |
| $version = if ($env:GITHUB_EVENT_NAME -eq "workflow_dispatch") { | |
| "${{ github.event.inputs.version }}" | |
| } else { | |
| "${{ github.ref_name }}" -replace "^v", "" | |
| } | |
| $finalDir = "pythonCWMS$version" | |
| Write-Host "Creating final directory: $finalDir" | |
| Write-Host "Source WinPython directory: $($winpythonDir.Name)" | |
| New-Item -ItemType Directory -Path $finalDir -Force | |
| Copy-Item -Path "$($winpythonDir.FullName)\*" -Destination $finalDir -Recurse -Force | |
| # Copy any additional files from repo (excluding git files) | |
| Write-Host "Copying additional repository files..." | |
| Get-ChildItem -Path "." -Exclude ".git*", "winpython_extracted", "*.zip", $finalDir | | |
| ForEach-Object { | |
| Write-Host " Copying: $($_.Name)" | |
| Copy-Item -Path $_.FullName -Destination $finalDir -Recurse -Force | |
| } | |
| echo "FINAL_DIR=$finalDir" >> $env:GITHUB_ENV | |
| echo "VERSION=$version" >> $env:GITHUB_ENV | |
| # Store the WinPython subdirectory name for the config | |
| $winpythonSubDir = $winpythonDir.Name | |
| echo "WINPYTHON_SUBDIR=$winpythonSubDir" >> $env:GITHUB_ENV | |
| Write-Host "WinPython subdirectory: $winpythonSubDir" | |
| - name: Install 7-Zip | |
| run: | | |
| Write-Host "Installing 7-Zip..." | |
| choco install 7zip -y | |
| - name: Create 7z archive | |
| run: | | |
| $archiveName = "pythonCWMS${{ env.VERSION }}.7z" | |
| Write-Host "Creating archive: $archiveName" | |
| Write-Host "Compressing directory: ${{ env.FINAL_DIR }}" | |
| & "C:\Program Files\7-Zip\7z.exe" a -t7z -mx=9 $archiveName "${{ env.FINAL_DIR }}" | |
| if (Test-Path $archiveName) { | |
| $size = (Get-Item $archiveName).Length / 1MB | |
| Write-Host "✓ Archive created successfully - Size: $([math]::Round($size, 2)) MB" | |
| echo "ARCHIVE_SIZE_MB=$([math]::Round($size, 2))" >> $env:GITHUB_ENV | |
| } else { | |
| Write-Error "❌ Failed to create archive" | |
| exit 1 | |
| } | |
| echo "ARCHIVE_NAME=$archiveName" >> $env:GITHUB_ENV | |
| - name: Calculate SHA256 hash | |
| run: | | |
| Write-Host "Calculating SHA256 hash for ${{ env.ARCHIVE_NAME }}..." | |
| $hash = Get-FileHash -Path "${{ env.ARCHIVE_NAME }}" -Algorithm SHA256 | |
| $hashString = $hash.Hash | |
| echo "ARCHIVE_HASH=$hashString" >> $env:GITHUB_ENV | |
| Write-Host "✓ SHA256: $hashString" | |
| - name: Generate config JSON | |
| run: | | |
| $repoOwner = "${{ github.repository_owner }}" | |
| $repoName = "${{ github.event.repository.name }}" | |
| $version = "${{ env.VERSION }}" | |
| $archiveName = "${{ env.ARCHIVE_NAME }}" | |
| $hash = "${{ env.ARCHIVE_HASH }}" | |
| $winpythonSubDir = "${{ env.WINPYTHON_SUBDIR }}" | |
| $winpythonVersion = "${{ env.WINPYTHON_VERSION }}" | |
| $winpythonFilename = "${{ env.WINPYTHON_FILENAME }}" | |
| Write-Host "Generating configuration file..." | |
| # Construct the download URL | |
| $downloadUrl = "https://github.com/$repoOwner/$repoName/releases/download/v$version/$archiveName" | |
| # The python subdirectory is simply "python" | |
| $pythonExeSubDir = "$winpythonSubDir\python" | |
| Write-Host "Python executable subdirectory: $pythonExeSubDir" | |
| # Create the config object | |
| $config = @{ | |
| python_download_url = $downloadUrl | |
| python_expected_hash_sha256 = $hash | |
| default_install_directory = "C:\hec\python" | |
| default_env_var_name = "PYTHON_CWMS_HOME" | |
| python_exe_sub_directory = $pythonExeSubDir | |
| version = $version | |
| archive_filename = $archiveName | |
| archive_size_mb = [math]::Round((Get-Item "${{ env.ARCHIVE_NAME }}").Length / 1MB, 2) | |
| created_date = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ") | |
| source_winpython_version = $winpythonVersion | |
| source_winpython_filename = $winpythonFilename | |
| } | |
| # Convert to JSON and save | |
| $configJson = $config | ConvertTo-Json -Depth 10 | |
| $configJson | Out-File -FilePath "pythonCWMS_config.json" -Encoding UTF8 | |
| Write-Host "✓ Generated config file:" | |
| Get-Content "pythonCWMS_config.json" | |
| - name: Validate config file | |
| run: | | |
| Write-Host "Validating configuration file..." | |
| # Test that the JSON is valid | |
| try { | |
| $config = Get-Content "pythonCWMS_config.json" | ConvertFrom-Json | |
| Write-Host "✓ Config JSON is valid" | |
| Write-Host "✓ Download URL: $($config.python_download_url)" | |
| Write-Host "✓ Hash: $($config.python_expected_hash_sha256)" | |
| Write-Host "✓ Python exe path: $($config.python_exe_sub_directory)" | |
| Write-Host "✓ Source WinPython: $($config.source_winpython_filename)" | |
| } | |
| catch { | |
| Write-Error "❌ Config JSON is invalid: $_" | |
| exit 1 | |
| } | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: ${{ github.ref_name || format('v{0}', github.event.inputs.version) }} | |
| name: Python CWMS ${{ env.VERSION }} | |
| draft: false | |
| prerelease: false | |
| files: | | |
| ${{ env.ARCHIVE_NAME }} | |
| pythonCWMS_config.json | |
| body: | | |
| ## Python CWMS ${{ env.VERSION }} | |
| Portable Python environment with CWMS libraries and dependencies. | |
| ### Downloads: | |
| - **`${{ env.ARCHIVE_NAME }}`** - Main Python environment archive (${{ env.ARCHIVE_SIZE_MB }} MB) | |
| - **`pythonCWMS_config.json`** - Configuration file for automated installers | |
| ### Archive Details: | |
| - **Size:** ${{ env.ARCHIVE_SIZE_MB }} MB | |
| - **SHA256:** `${{ env.ARCHIVE_HASH }}` | |
| - **Source:** ${{ env.WINPYTHON_FILENAME }} | |
| ### Contents: | |
| - WinPython 3.12.10.1 (from ${{ env.WINPYTHON_VERSION }}) | |
| - Libraries from requirements_binary_only.txt | |
| - Custom setup and configuration | |
| ### Usage: | |
| 1. Extract the .7z file to your desired location | |
| 2. Run `${{ env.FINAL_DIR }}\WinPython Command Prompt.exe` | |
| 3. Your environment is ready to use! | |
| ### For Automated Installation: | |
| Use the `pythonCWMS_config.json` file with your installer scripts. | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |