Fix PowerShell syntax: assign cache-hit to variable before if statement #24
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: ML BootCamp CI Pipeline | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - master | |
| paths: | |
| - 'Data/**' | |
| - 'Scripts/**' | |
| - 'Notebooks/**' | |
| - 'pyproject.toml' | |
| - 'requirements.txt' | |
| - '.github/workflows/ci.yml' | |
| pull_request: | |
| branches: | |
| - main | |
| - master | |
| paths: | |
| - 'Data/**' | |
| - 'Scripts/**' | |
| - 'Notebooks/**' | |
| - 'pyproject.toml' | |
| - 'requirements.txt' | |
| workflow_dispatch: | |
| jobs: | |
| train-model: | |
| runs-on: self-hosted | |
| timeout-minutes: 45 # Prevent infinite hangs | |
| defaults: | |
| run: | |
| shell: powershell | |
| env: | |
| MLFLOW_TRACKING_URI: sqlite:///D:/ML 101/ML_101_BootCamp/mlflow.db | |
| MLFLOW_EXPERIMENT_NAME: customer_churn_optimization | |
| MODEL_NAME: customer_churn_model | |
| GIT_SHA: ${{ github.sha }} | |
| GIT_REF: ${{ github.ref_name }} | |
| PYTHONIOENCODING: utf-8 | |
| PYTHONUTF8: 1 | |
| PIP_DISABLE_PIP_VERSION_CHECK: 1 | |
| PIP_NO_INPUT: 1 | |
| PIP_PREFER_BINARY: 1 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Verify Python installation | |
| run: | | |
| Write-Host "=== Python Environment Check ===" | |
| $pythonCmd = Get-Command python -ErrorAction SilentlyContinue | |
| if ($pythonCmd) { | |
| $pythonPath = $pythonCmd.Source | |
| Write-Host "✅ Python found at: $pythonPath" | |
| python --version | |
| python -m pip --version | |
| } else { | |
| Write-Host "❌ Python not found in PATH" | |
| exit 1 | |
| } | |
| - name: Cache pip packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~\AppData\Local\pip\cache | |
| key: pip-${{ runner.os }}-${{ hashFiles('**/requirements.txt') }}-v3 | |
| restore-keys: | | |
| pip-${{ runner.os }}-${{ hashFiles('**/requirements.txt') }}- | |
| pip-${{ runner.os }}- | |
| - name: Cache virtual environment | |
| id: cache-venv | |
| uses: actions/cache@v4 | |
| with: | |
| path: .venv | |
| key: venv-${{ runner.os }}-py${{ hashFiles('.python-version') }}-${{ hashFiles('**/requirements.txt') }}-v3 | |
| restore-keys: | | |
| venv-${{ runner.os }}-py${{ hashFiles('.python-version') }}-${{ hashFiles('**/requirements.txt') }}- | |
| venv-${{ runner.os }}-py${{ hashFiles('.python-version') }}- | |
| - name: Display cache status | |
| run: | | |
| Write-Host "=== Cache Status ===" -ForegroundColor Cyan | |
| $cacheHit = "${{ steps.cache-venv.outputs.cache-hit }}" | |
| if ($cacheHit -eq "true") { | |
| Write-Host "Virtual env cache hit: $cacheHit" -ForegroundColor Green | |
| } else { | |
| Write-Host "Virtual env cache hit: $cacheHit" -ForegroundColor Yellow | |
| } | |
| - name: Create virtual environment | |
| run: | | |
| if (!(Test-Path ".venv")) { | |
| Write-Host "Creating virtual environment..." | |
| python -m venv .venv | |
| Write-Host "✅ Virtual environment created" | |
| } else { | |
| Write-Host "✅ Virtual environment already exists (from cache)" | |
| Write-Host "Cache hit: ${{ steps.cache-venv.outputs.cache-hit }}" | |
| } | |
| - name: Install dependencies | |
| timeout-minutes: 15 | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| & ".venv\Scripts\Activate.ps1" | |
| # Check if cache was restored and packages are valid | |
| $cacheHit = "${{ steps.cache-venv.outputs.cache-hit }}" | |
| if ($cacheHit -eq "true") { | |
| Write-Host "📦 Checking cached dependencies..." | |
| try { | |
| python -c "import mlflow, sklearn, pandas, numpy, optuna; print('✅ All packages verified from cache')" 2>$null | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-Host "✅ Using cached virtual environment - skipping install" | |
| return | |
| } | |
| } catch { | |
| Write-Host "⚠️ Cache validation failed, reinstalling..." | |
| } | |
| } | |
| Write-Host "📦 Installing dependencies..." | |
| # Upgrade pip with minimal output | |
| python -m pip install --upgrade pip wheel --quiet 2>&1 | Out-Null | |
| # Install dependencies with optimized settings | |
| python -m pip install -r requirements.txt ` | |
| --only-binary :all: ` | |
| --compile ` | |
| --no-warn-script-location ` | |
| 2>&1 | Select-String -Pattern "(Collecting|Installing collected|Successfully installed)" | Write-Host | |
| Write-Host "✅ Dependencies installed" | |
| python -c "import mlflow, sklearn, pandas, numpy, optuna; print('✅ Packages verified')" | |
| - name: Verify git info | |
| run: | | |
| git config user.name "CI Bot" | |
| git config user.email "ci-bot@example.com" | |
| git log -1 --pretty=format:"Commit: %H%nAuthor: %an%nDate: %ai%nMessage: %s" | |
| - name: Verify data files exist | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| if (!(Test-Path "Data/customer_churn_dataset_prepared.csv")) { | |
| Write-Host "❌ Training data not found!" | |
| exit 1 | |
| } | |
| Write-Host "✅ Data files verified:" | |
| Get-ChildItem Data/*.csv | ForEach-Object { Write-Host " - $($_.Name)" } | |
| - name: Run model training | |
| timeout-minutes: 30 | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| & ".venv\Scripts\Activate.ps1" | |
| Write-Host "Starting model training..." | |
| python Scripts/model_training.py | |
| Write-Host "✅ Training completed" | |
| - name: Training summary | |
| if: always() | |
| run: | | |
| "# ML Bootcamp Training Report" >> $env:GITHUB_STEP_SUMMARY | |
| "" >> $env:GITHUB_STEP_SUMMARY | |
| "**Commit:** ${{ github.sha }}" >> $env:GITHUB_STEP_SUMMARY | |
| "**Branch:** ${{ github.ref_name }}" >> $env:GITHUB_STEP_SUMMARY | |
| "**Runner:** self-hosted (local laptop)" >> $env:GITHUB_STEP_SUMMARY | |
| "" >> $env:GITHUB_STEP_SUMMARY | |
| "✅ Training completed. Check MLflow UI for metrics & model registry." >> $env:GITHUB_STEP_SUMMARY |