From 938d35812b2a47d0ef88ba666d72402a232e77cd Mon Sep 17 00:00:00 2001 From: Eric Pinzur <2641606+epinzur@users.noreply.github.com> Date: Thu, 31 Jul 2025 17:34:31 +0200 Subject: [PATCH] chore:more cross-platform test deubgging (#9270) --- .github/workflows/cross-platform-test.yml | 319 +++++++++++++++++++--- 1 file changed, 281 insertions(+), 38 deletions(-) diff --git a/.github/workflows/cross-platform-test.yml b/.github/workflows/cross-platform-test.yml index df7501e91..81158d734 100644 --- a/.github/workflows/cross-platform-test.yml +++ b/.github/workflows/cross-platform-test.yml @@ -67,7 +67,7 @@ jobs: echo "base-artifact-name=adhoc-dist-base" >> $GITHUB_OUTPUT echo "main-artifact-name=adhoc-dist-main" >> $GITHUB_OUTPUT - test-installation: + test-installation-stable: name: Install & Run - ${{ matrix.os }} ${{ matrix.arch }} ${{ matrix.python-version }} needs: [build-if-needed] if: always() && (needs.build-if-needed.result == 'success' || needs.build-if-needed.result == 'skipped') @@ -85,11 +85,6 @@ jobs: arch: amd64 runner: ubuntu-latest python-version: "3.12" - - os: linux - arch: amd64 - runner: ubuntu-latest - python-version: "3.13" - continue-on-error: true # macOS AMD64 - os: macos arch: amd64 @@ -99,11 +94,6 @@ jobs: arch: amd64 runner: macos-13 python-version: "3.12" - - os: macos - arch: amd64 - runner: macos-13 - python-version: "3.13" - continue-on-error: true # macOS ARM64 (Apple Silicon) - os: macos arch: arm64 @@ -113,11 +103,6 @@ jobs: arch: arm64 runner: macos-latest python-version: "3.12" - - os: macos - arch: arm64 - runner: macos-latest - python-version: "3.13" - continue-on-error: true # Windows AMD64 - os: windows arch: amd64 @@ -127,11 +112,258 @@ jobs: arch: amd64 runner: windows-latest python-version: "3.12" + + steps: + - name: Determine install method + id: install-method + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + if [ -n "${{ inputs.langflow-version }}" ]; then + echo "method=pypi" >> $GITHUB_OUTPUT + else + echo "method=wheel" >> $GITHUB_OUTPUT + fi + else + # workflow_call always uses wheel method (backward compatibility) + echo "method=wheel" >> $GITHUB_OUTPUT + fi + shell: bash + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + architecture: ${{ matrix.arch == 'amd64' && 'x64' || matrix.arch }} + + - name: Setup UV + uses: astral-sh/setup-uv@v6 + with: + enable-cache: false + ignore-empty-workdir: true + + # Download artifacts for wheel installation + - name: Download base package artifact + if: steps.install-method.outputs.method == 'wheel' + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.base-artifact-name || needs.build-if-needed.outputs.base-artifact-name || 'adhoc-dist-base' }} + path: ./base-dist + + - name: Download main package artifact + if: steps.install-method.outputs.method == 'wheel' + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.main-artifact-name || needs.build-if-needed.outputs.main-artifact-name || 'adhoc-dist-main' }} + path: ./main-dist + + - name: Create fresh virtual environment + run: | + uv venv test-env --seed + shell: bash + + # Wheel installation steps + - name: Install base package from wheel (Windows) + if: steps.install-method.outputs.method == 'wheel' && matrix.os == 'windows' + run: | + ls -la ./base-dist/ + find ./base-dist -name "*.whl" -type f + WHEEL_FILE=$(find ./base-dist -name "*.whl" -type f | head -1) + if [ -n "$WHEEL_FILE" ]; then + uv pip install --python ./test-env/Scripts/python.exe "$WHEEL_FILE" + else + echo "No wheel file found in ./base-dist/" + exit 1 + fi + shell: bash + + - name: Install main package from wheel (Windows) + if: steps.install-method.outputs.method == 'wheel' && matrix.os == 'windows' + run: | + ls -la ./main-dist/ + find ./main-dist -name "*.whl" -type f + WHEEL_FILE=$(find ./main-dist -name "*.whl" -type f | head -1) + if [ -n "$WHEEL_FILE" ]; then + uv pip install --python ./test-env/Scripts/python.exe "$WHEEL_FILE" + else + echo "No wheel file found in ./main-dist/" + exit 1 + fi + shell: bash + + - name: Install base package from wheel (Unix) + if: steps.install-method.outputs.method == 'wheel' && matrix.os != 'windows' + run: | + ls -la ./base-dist/ + find ./base-dist -name "*.whl" -type f + WHEEL_FILE=$(find ./base-dist -name "*.whl" -type f | head -1) + if [ -n "$WHEEL_FILE" ]; then + uv pip install --python ./test-env/bin/python "$WHEEL_FILE" + else + echo "No wheel file found in ./base-dist/" + exit 1 + fi + shell: bash + + - name: Install main package from wheel (Unix) + if: steps.install-method.outputs.method == 'wheel' && matrix.os != 'windows' + run: | + ls -la ./main-dist/ + find ./main-dist -name "*.whl" -type f + WHEEL_FILE=$(find ./main-dist -name "*.whl" -type f | head -1) + if [ -n "$WHEEL_FILE" ]; then + uv pip install --python ./test-env/bin/python "$WHEEL_FILE" + else + echo "No wheel file found in ./main-dist/" + exit 1 + fi + shell: bash + + # PyPI installation steps + - name: Install langflow from PyPI (Windows) + if: steps.install-method.outputs.method == 'pypi' && matrix.os == 'windows' + run: | + if [ -n "${{ inputs.langflow-version }}" ]; then + uv pip install --python ./test-env/Scripts/python.exe langflow==${{ inputs.langflow-version }} + else + uv pip install --python ./test-env/Scripts/python.exe langflow + fi + shell: bash + + - name: Install langflow from PyPI (Unix) + if: steps.install-method.outputs.method == 'pypi' && matrix.os != 'windows' + run: | + if [ -n "${{ inputs.langflow-version }}" ]; then + uv pip install --python ./test-env/bin/python langflow==${{ inputs.langflow-version }} + else + uv pip install --python ./test-env/bin/python langflow + fi + shell: bash + + # Install additional dependencies + - name: Install additional dependencies (Windows) + if: matrix.os == 'windows' + run: | + uv pip install --python ./test-env/Scripts/python.exe openai + shell: bash + + - name: Install additional dependencies (Unix) + if: matrix.os != 'windows' + run: | + uv pip install --python ./test-env/bin/python openai + shell: bash + + # Test steps + - name: Test CLI help command (Windows) + if: matrix.os == 'windows' + run: | + test-env\Scripts\python.exe -m langflow --help + shell: cmd + + - name: Test CLI help command (Unix) + if: matrix.os != 'windows' + run: | + ./test-env/bin/python -m langflow --help + shell: bash + + - name: Test server startup (Windows) + if: matrix.os == 'windows' + timeout-minutes: 5 + run: | + # Start server in background + $serverProcess = Start-Process -FilePath ".\test-env\Scripts\python.exe" -ArgumentList "-m", "langflow", "run", "--host", "localhost", "--port", "7860", "--backend-only" -PassThru -WindowStyle Hidden + + # Wait for server to be ready (GitHub Actions will timeout after 5 minutes) + do { + try { + $response = Invoke-WebRequest -Uri "http://localhost:7860/health_check" -UseBasicParsing -TimeoutSec 5 + if ($response.StatusCode -eq 200) { + Write-Host "✅ Server is ready on ${{ matrix.os }}-${{ matrix.arch }}" + break + } + } catch { + Start-Sleep -Seconds 5 + } + } while ($true) + + # Stop the server process + Stop-Process -Id $serverProcess.Id -Force -ErrorAction SilentlyContinue + shell: powershell + + - name: Test server startup (Unix) + if: matrix.os != 'windows' + timeout-minutes: 5 + run: | + # Start server in background + ./test-env/bin/python -m langflow run --host localhost --port 7860 --backend-only & + SERVER_PID=$! + + # Wait for server to be ready (GitHub Actions will timeout after 5 minutes) + while true; do + if curl -f http://localhost:7860/health_check >/dev/null 2>&1; then + echo "✅ Server is ready on ${{ matrix.os }}-${{ matrix.arch }}" + break + fi + sleep 5 + done + + # Clean shutdown + kill $SERVER_PID 2>/dev/null || true + sleep 5 + shell: bash + + - name: Test import in Python (Windows) + if: matrix.os == 'windows' + run: | + test-env\Scripts\python.exe -c " + try: + import langflow + print('✅ langflow import successful on ${{ matrix.os }}-${{ matrix.arch }}') + except Exception as e: + print(f'❌ langflow import failed on ${{ matrix.os }}-${{ matrix.arch }}: {e}') + exit(1) + " + shell: cmd + + - name: Test import in Python (Unix) + if: matrix.os != 'windows' + run: | + ./test-env/bin/python -c " + try: + import langflow + print('✅ langflow import successful on ${{ matrix.os }}-${{ matrix.arch }}') + except Exception as e: + print(f'❌ langflow import failed on ${{ matrix.os }}-${{ matrix.arch }}: {e}') + exit(1) + " + shell: bash + + test-installation-experimental: + name: Install & Run - ${{ matrix.os }} ${{ matrix.arch }} ${{ matrix.python-version }} (Experimental) + needs: [build-if-needed] + if: always() && (needs.build-if-needed.result == 'success' || needs.build-if-needed.result == 'skipped') + runs-on: ${{ matrix.runner }} + continue-on-error: true + strategy: + fail-fast: false + matrix: + include: + # Python 3.13 - Experimental + - os: linux + arch: amd64 + runner: ubuntu-latest + python-version: "3.13" + - os: macos + arch: amd64 + runner: macos-13 + python-version: "3.13" + - os: macos + arch: arm64 + runner: macos-latest + python-version: "3.13" - os: windows arch: amd64 runner: windows-latest python-version: "3.13" - continue-on-error: true steps: - name: Determine install method @@ -359,38 +591,49 @@ jobs: test-summary: name: Cross-Platform Test Summary - needs: test-installation + needs: [test-installation-stable, test-installation-experimental] runs-on: ubuntu-latest if: always() steps: - name: Check test results run: | - result="${{ needs.test-installation.result }}" - echo "Test installation result: $result" - - # Log appropriate message but don't fail for continue-on-error jobs - if [ "$result" = "success" ]; then - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - if [ -n "${{ inputs.langflow-version }}" ]; then - echo "✅ PyPI installation tests passed" + stable_result="${{ needs.test-installation-stable.result }}" + experimental_result="${{ needs.test-installation-experimental.result }}" + + echo "Stable platforms result: $stable_result" + echo "Experimental platforms result: $experimental_result" + + # Stable platforms must succeed, experimental can fail + if [ "$stable_result" = "success" ]; then + if [ "$experimental_result" = "success" ]; then + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + if [ -n "${{ inputs.langflow-version }}" ]; then + echo "✅ All PyPI installation tests passed (including Python 3.13)" + else + echo "✅ All source build and installation tests passed (including Python 3.13)" + fi else - echo "✅ Source build and installation tests passed" + echo "✅ All cross-platform tests passed - PyPI upload can proceed" fi else - echo "✅ All cross-platform tests passed - PyPI upload can proceed" - fi - elif [ "$result" = "failure" ]; then - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - if [ -n "${{ inputs.langflow-version }}" ]; then - echo "⚠️ PyPI installation tests had failures (some may be continue-on-error)" + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + if [ -n "${{ inputs.langflow-version }}" ]; then + echo "✅ PyPI installation tests passed (Python 3.13 experimental failures are acceptable)" + else + echo "✅ Source build and installation tests passed (Python 3.13 experimental failures are acceptable)" + fi else - echo "⚠️ Source build and installation tests had failures (some may be continue-on-error)" + echo "✅ Cross-platform tests passed - Python 3.13 experimental failures are acceptable - PyPI upload can proceed" fi - else - echo "⚠️ Cross-platform tests had failures (checking if continue-on-error allows PyPI upload)" fi - # Don't exit 1 here - let continue-on-error handle the workflow flow + elif [ "$stable_result" = "failure" ]; then + echo "❌ Critical platform tests failed - blocking release" + echo "Stable platforms (Python 3.10, 3.12) must pass for release" + exit 1 + elif [ "$stable_result" = "cancelled" ]; then + echo "❌ Critical platform tests were cancelled" + exit 1 else - echo "❌ Cross-platform tests were cancelled or skipped" + echo "❌ Critical platform tests were skipped unexpectedly" exit 1 fi \ No newline at end of file