305 lines
10 KiB
YAML
305 lines
10 KiB
YAML
name: Shared Cross-Platform Test Logic
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
test-timeout:
|
|
description: "Timeout for langflow server startup test (minutes)"
|
|
required: false
|
|
type: number
|
|
default: 5
|
|
install-method:
|
|
description: "Installation method: 'wheel' for local wheels, 'pypi' for PyPI packages"
|
|
required: true
|
|
type: string
|
|
langflow-version:
|
|
description: "Langflow version to install from PyPI (only used if install-method is 'pypi')"
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
base-artifact-name:
|
|
description: "Name of the base package artifact (only used if install-method is 'wheel')"
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
main-artifact-name:
|
|
description: "Name of the main package artifact (only used if install-method is 'wheel')"
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
run-id:
|
|
description: "GitHub run ID to download artifacts from (leave empty for current run)"
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
|
|
jobs:
|
|
test-installation:
|
|
name: Install & Run - ${{ matrix.os }} ${{ matrix.arch }} ${{ matrix.python-version }}
|
|
runs-on: ${{ matrix.runner }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
# Linux AMD64
|
|
- os: linux
|
|
arch: amd64
|
|
runner: ubuntu-latest
|
|
python-version: "3.10"
|
|
- os: linux
|
|
arch: amd64
|
|
runner: ubuntu-latest
|
|
python-version: "3.13"
|
|
# macOS AMD64
|
|
- os: macos
|
|
arch: amd64
|
|
runner: macos-13
|
|
python-version: "3.10"
|
|
- os: macos
|
|
arch: amd64
|
|
runner: macos-13
|
|
python-version: "3.13"
|
|
# macOS ARM64 (Apple Silicon)
|
|
- os: macos
|
|
arch: arm64
|
|
runner: macos-latest
|
|
python-version: "3.10"
|
|
- os: macos
|
|
arch: arm64
|
|
runner: macos-latest
|
|
python-version: "3.13"
|
|
# Windows AMD64
|
|
- os: windows
|
|
arch: amd64
|
|
runner: windows-latest
|
|
python-version: "3.10"
|
|
- os: windows
|
|
arch: amd64
|
|
runner: windows-latest
|
|
python-version: "3.12"
|
|
|
|
steps:
|
|
- 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
|
|
|
|
# Download artifacts for wheel installation
|
|
- name: Download base package artifact
|
|
if: inputs.install-method == 'wheel'
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: ${{ inputs.base-artifact-name }}
|
|
path: ./base-dist
|
|
|
|
- name: Download main package artifact
|
|
if: inputs.install-method == 'wheel'
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: ${{ inputs.main-artifact-name }}
|
|
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: inputs.install-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: inputs.install-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: inputs.install-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: inputs.install-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: inputs.install-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: inputs.install-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: ${{ inputs.test-timeout }}
|
|
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
|
|
$timeoutSeconds = ${{ inputs.test-timeout }} * 60
|
|
$elapsed = 0
|
|
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
|
|
$elapsed += 5
|
|
}
|
|
} while ($elapsed -lt $timeoutSeconds)
|
|
|
|
if ($elapsed -ge $timeoutSeconds) {
|
|
Write-Host "❌ Server failed to start within timeout on ${{ matrix.os }}-${{ matrix.arch }}"
|
|
exit 1
|
|
}
|
|
|
|
# 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: ${{ inputs.test-timeout }}
|
|
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 (using bash loop instead of timeout command)
|
|
TIMEOUT_SECONDS=$((${{ inputs.test-timeout }} * 60))
|
|
ELAPSED=0
|
|
while [ $ELAPSED -lt $TIMEOUT_SECONDS ]; 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
|
|
ELAPSED=$((ELAPSED + 5))
|
|
done
|
|
|
|
if [ $ELAPSED -ge $TIMEOUT_SECONDS ]; then
|
|
echo "❌ Server failed to start within timeout on ${{ matrix.os }}-${{ matrix.arch }}"
|
|
kill $SERVER_PID 2>/dev/null || true
|
|
exit 1
|
|
fi
|
|
|
|
# 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
|
|
|