Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 13 additions & 138 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
Expand Down Expand Up @@ -75,38 +73,13 @@ jobs:
docker-test:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.head_ref != 'release-please--branches--main'
needs: [lint]
steps:
- name: Clear Space
# Note: Manual cleanup sufficient for CPU images (python:3.12-slim base ~150MB)
# Only CUDA images need aggressive cleanup due to their ~10-15GB size
run: |
rm -rf /usr/share/dotnet
rm -rf /opt/ghc
rm -rf "/usr/local/share/boost"
rm -rf "$AGENT_TOOLSDIRECTORY"
docker system prune -af
df -h

- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Set up uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true

- name: Setup dependencies
run: uv sync

- name: Build CPU Docker image
uses: docker/build-push-action@v6
with:
Expand All @@ -124,92 +97,16 @@ jobs:
echo "Testing CPU handler in Docker environment..."
docker run --rm flash-cpu:test ./test-handler.sh

docker-test-lb:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.head_ref != 'release-please--branches--main'
needs: [lint]
steps:
- name: Free Disk Space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
swap-storage: true

- name: Additional cleanup and report
run: |
docker system prune -af
df -h

- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Set up uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true

- name: Setup dependencies
run: uv sync

- name: Build Load Balancer Docker image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile-lb
platforms: linux/amd64
push: false
tags: flash-lb:test
cache-from: type=gha
cache-to: type=gha,mode=max
load: true

docker-test-lb-cpu:
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.head_ref != 'release-please--branches--main'
needs: [lint]
steps:
- name: Clear Space
# Note: Manual cleanup sufficient for CPU images (python:3.12-slim base ~150MB)
# Only CUDA images need aggressive cleanup due to their ~10-15GB size
run: |
rm -rf /usr/share/dotnet
rm -rf /opt/ghc
rm -rf "/usr/local/share/boost"
rm -rf "$AGENT_TOOLSDIRECTORY"
docker system prune -af
df -h

- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Set up uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true

- name: Setup dependencies
run: uv sync

- name: Build CPU Load Balancer Docker image
uses: docker/build-push-action@v6
with:
Expand All @@ -222,14 +119,19 @@ jobs:
cache-to: type=gha,mode=max
load: true

- name: Test LB handler execution in Docker environment
run: |
echo "Testing LB handler in Docker environment..."
docker run --rm flash-lb-cpu:test ./test-lb-handler.sh

docker-validation:
runs-on: ubuntu-latest
needs: [test, lint, docker-test, docker-test-lb, docker-test-lb-cpu]
needs: [test, lint, docker-test, docker-test-lb-cpu]
if: always()
steps:
- name: Check all jobs succeeded
run: |
results=("${{ needs.test.result }}" "${{ needs.lint.result }}" "${{ needs.docker-test.result }}" "${{ needs.docker-test-lb.result }}" "${{ needs.docker-test-lb-cpu.result }}")
results=("${{ needs.test.result }}" "${{ needs.lint.result }}" "${{ needs.docker-test.result }}" "${{ needs.docker-test-lb-cpu.result }}")
for result in "${results[@]}"; do
if [[ "$result" != "success" && "$result" != "skipped" ]]; then
echo "One or more quality checks failed (got: $result)"
Expand Down Expand Up @@ -262,18 +164,9 @@ jobs:
needs: [release]
if: needs.release.outputs.release_created
steps:
- name: Free Disk Space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
swap-storage: true

- name: Additional cleanup and report
- name: Clear Space
run: |
rm -rf /usr/share/dotnet /opt/ghc /usr/local/share/boost "$AGENT_TOOLSDIRECTORY"
docker system prune -af
df -h

Expand Down Expand Up @@ -394,18 +287,9 @@ jobs:
needs: [release]
if: needs.release.outputs.release_created
steps:
- name: Free Disk Space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
swap-storage: true

- name: Additional cleanup and report
- name: Clear Space
run: |
rm -rf /usr/share/dotnet /opt/ghc /usr/local/share/boost "$AGENT_TOOLSDIRECTORY"
docker system prune -af
df -h

Expand Down Expand Up @@ -463,18 +347,9 @@ jobs:
needs: [release]
if: needs.release.outputs.release_created
steps:
- name: Free Disk Space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: true
swap-storage: true

- name: Additional cleanup and report
- name: Clear Space
run: |
rm -rf /usr/share/dotnet /opt/ghc /usr/local/share/boost "$AGENT_TOOLSDIRECTORY"
docker system prune -af
df -h

Expand Down
2 changes: 1 addition & 1 deletion release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
{"type": "chore", "section": "Miscellaneous", "hidden": true}
],
"extra-files": [
"src/__init__.py"
"src/version.py"
]
}
},
Expand Down
8 changes: 6 additions & 2 deletions src/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@

from logger import setup_logging
from unpack_volume import maybe_unpack
from version import format_version_banner

# Initialize logging configuration
setup_logging()

logger = logging.getLogger(__name__)

# Unpack Flash deployment artifacts if running in Flash mode
# This is a no-op for Live Serverless and local development
maybe_unpack()

logger = logging.getLogger(__name__)
# Log after unpack so bundled runpod_flash is on sys.path
logger.info(format_version_banner())


def _load_generated_handler() -> Optional[Any]:
Expand Down Expand Up @@ -62,7 +66,7 @@ def _load_generated_handler() -> Optional[Any]:
except ImportError as e:
logger.warning(
"Generated handler %s failed to import (missing dependency: %s). "
"Deploy with --use-local-flash to include latest runpod_flash. "
"Redeploy to include latest runpod_flash. "
"Falling back to FunctionRequest handler.",
handler_file,
e,
Expand Down
4 changes: 4 additions & 0 deletions src/lb_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

from logger import setup_logging
from unpack_volume import maybe_unpack
from version import format_version_banner

# Initialize logging configuration
setup_logging()
Expand All @@ -38,6 +39,9 @@
# This is a no-op for Live Serverless and local development
maybe_unpack()

# Log after unpack so bundled runpod_flash is on sys.path
logger.info(format_version_banner())

# Import from bundled /app/runpod_flash (no system package)
# These imports must happen AFTER maybe_unpack() so /app is in sys.path
from runpod_flash.protos.remote_execution import FunctionRequest, FunctionResponse # noqa: E402
Expand Down
16 changes: 11 additions & 5 deletions src/test-lb-handler.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@ trap cleanup EXIT

# Start FastAPI server in background
echo "Starting FastAPI server on port $PORT..."
PYTHONPATH=. uv run python3 -m uvicorn lb_handler:app --host $HOST --port $PORT --log-level error > /tmp/lb_handler.log 2>&1 &
if [ -f /.dockerenv ]; then
# Docker: use system python with pre-installed packages
PYTHONPATH=. python3 -m uvicorn lb_handler:app --host $HOST --port $PORT --log-level error > /tmp/lb_handler.log 2>&1 &
else
# Local: use uv run to manage dependencies
PYTHONPATH=. uv run python3 -m uvicorn lb_handler:app --host $HOST --port $PORT --log-level error > /tmp/lb_handler.log 2>&1 &
fi
SERVER_PID=$!

# Wait for server to be ready
echo "Waiting for server to be ready..."
attempt=0
while [ $attempt -lt $TEST_TIMEOUT ]; do
if curl -s -f "http://$HOST:$PORT/health" > /dev/null 2>&1; then
if curl -s -f "http://$HOST:$PORT/ping" > /dev/null 2>&1; then
echo "✓ Server is ready"
break
fi
Expand All @@ -46,10 +52,10 @@ while [ $attempt -lt $TEST_TIMEOUT ]; do
fi
done

# Test /health endpoint
# Test /ping endpoint
echo ""
echo "Testing /health endpoint..."
health_response=$(curl -s "http://$HOST:$PORT/health")
echo "Testing /ping endpoint..."
health_response=$(curl -s "http://$HOST:$PORT/ping")
echo "Response: $health_response"

# Run /execute tests
Expand Down
38 changes: 38 additions & 0 deletions src/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Version utilities for flash-worker boot logging."""

from importlib.metadata import PackageNotFoundError, version

__version__ = "1.1.0" # x-release-please-version


def _get_version(package_name: str) -> str:
try:
return version(package_name)
except PackageNotFoundError:
return "unknown"


def get_worker_version() -> str:
return __version__


def get_flash_version() -> str:
"""Read bundled flash version, falling back to pip metadata."""
try:
from runpod_flash import __version__ as flash_ver

return str(flash_ver)
except (ImportError, AttributeError):
return _get_version("runpod-flash")


def get_runpod_version() -> str:
return _get_version("runpod")


def format_version_banner() -> str:
return (
f"Starting Flash Worker {get_worker_version()} | "
f"runpod-flash {get_flash_version()} | "
f"runpod {get_runpod_version()}"
)
4 changes: 4 additions & 0 deletions tests/unit/test_lb_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@


# Mock heavy dependencies before importing lb_handler to prevent side effects
_mock_version = MagicMock()
_mock_version.format_version_banner = MagicMock(return_value="Starting Flash Worker vtest")

_MOCK_MODULES = {
"logger": MagicMock(),
"unpack_volume": MagicMock(),
"remote_executor": MagicMock(),
"version": _mock_version,
"runpod_flash": MagicMock(),
"runpod_flash.protos": MagicMock(),
"runpod_flash.protos.remote_execution": MagicMock(),
Expand Down
Loading